Skip to content

Commit 8f60575

Browse files
authored
[JS] feat: add jsdoc for authentication code (#850)
## Linked issues closes: #849 ## Details 1. Add JSDoc for authentication code 2. Move `TeamsSsoSettings` out of `TeamsBotSsoPromt`, as it's not only for this prompt ## Attestation Checklist - [x] My code follows the style guidelines of this project - I have checked for/fixed spelling, linting, and other errors - I have commented my code for clarity - I have made corresponding changes to the documentation (we use [TypeDoc](https://typedoc.org/) to document our code) - My changes generate no new warnings - I have added tests that validates my changes, and provides sufficient test coverage. I have tested with: - Local testing - E2E testing in Teams - New and existing unit tests pass locally with my changes
1 parent 9cc56ab commit 8f60575

13 files changed

+388
-16
lines changed

js/packages/teams-ai/src/authentication/AdaptiveCardAuthenticationBase.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,16 @@ export interface AdaptiveCardLoginRequest {
2626

2727
/**
2828
* @internal
29+
*
30+
* Base class to handle adaptive card authentication.
2931
*/
3032
export abstract class AdaptiveCardAuthenticationBase {
33+
34+
/**
35+
* Authenticates the user.
36+
* @param {TurnContext} context - The turn context.
37+
* @returns {Promise<string | undefined>} - The authentication token, or undefined if authentication failed. Teams will ask user to sign-in if authentication failed.
38+
*/
3139
public async authenticate(context: TurnContext): Promise<string | undefined> {
3240
const value = context.activity.value;
3341

@@ -90,15 +98,36 @@ export abstract class AdaptiveCardAuthenticationBase {
9098
return;
9199
}
92100

101+
/**
102+
* Checks if the activity is a valid Adaptive Card activity that supports authentication.
103+
* @param context - The turn context.
104+
* @returns A boolean indicating if the activity is valid.
105+
*/
93106
public isValidActivity(context: TurnContext): boolean {
94107
return context.activity.type == ActivityTypes.Invoke && context.activity.name == ACTION_INVOKE_NAME;
95108
}
96109

110+
/**
111+
* Handles the SSO token exchange.
112+
* @param context - The turn context.
113+
* @returns A promise that resolves to the token response or undefined if token exchange failed.
114+
*/
97115
public abstract handleSsoTokenExchange(
98116
context: TurnContext
99117
): Promise<TokenResponse | undefined>
100118

119+
/**
120+
* Handles the user sign-in.
121+
* @param context - The turn context.
122+
* @param magicCode - The magic code from user sign-in.
123+
* @returns A promise that resolves to the token response or undefined if failed to verify the magic code.
124+
*/
101125
public abstract handleUserSignIn(context: TurnContext, magicCode: string): Promise<TokenResponse | undefined>
102126

127+
/**
128+
* Gets the login request for Adaptive Card authentication.
129+
* @param context - The turn context.
130+
* @returns A promise that resolves to the login request.
131+
*/
103132
public abstract getLoginRequest(context: TurnContext): Promise<AdaptiveCardLoginRequest>
104133
}

js/packages/teams-ai/src/authentication/Authentication.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { MessageExtensionAuthenticationBase } from './MessageExtensionAuthentica
1616
import { BotAuthenticationBase, deleteTokenFromState, setTokenInState } from './BotAuthenticationBase';
1717
import * as UserTokenAccess from './UserTokenAccess';
1818
import { AdaptiveCardAuthenticationBase } from './AdaptiveCardAuthenticationBase';
19-
import { TeamsSsoSettings } from './TeamsBotSsoPrompt';
19+
import { TeamsSsoSettings } from './TeamsSsoSettings';
2020
import { OAuthPromptMessageExtensionAuthentication } from './OAuthMessageExtensionAuthentication';
2121
import { OAuthBotAuthentication } from './OAuthBotAuthentication';
2222
import { TeamsSsoBotAuthentication } from './TeamsSsoBotAuthentication';

js/packages/teams-ai/src/authentication/BotAuthenticationBase.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,22 @@ interface UserAuthState {
2222

2323
/**
2424
* @internal
25+
*
26+
* Base class to handle Teams conversational bot authentication.
27+
* @template TState - The type of the turn state.
2528
*/
2629
export abstract class BotAuthenticationBase<TState extends TurnState> {
2730
protected _storage: Storage;
2831
protected _settingName: string;
2932
private _userSignInSuccessHandler?: (context: TurnContext, state: TState) => Promise<void>;
3033
private _userSignInFailureHandler?: (context: TurnContext, state: TState, error: AuthError) => Promise<void>;
3134

35+
/**
36+
* Creates a new instance of BotAuthenticationBase.
37+
* @param {Application<TState>} app - The application instance.
38+
* @param {string} settingName - The name of the setting.
39+
* @param {Storage} [storage] - The storage to save states.
40+
*/
3241
public constructor(app: Application<TState>, settingName: string, storage?: Storage) {
3342
this._settingName = settingName;
3443

@@ -51,6 +60,12 @@ export abstract class BotAuthenticationBase<TState extends TurnState> {
5160
);
5261
}
5362

63+
/**
64+
* Authenticates the user.
65+
* @param {TurnContext} context - The turn context.
66+
* @param {TState} state - The turn state.
67+
* @returns {Promise<string | undefined>} - The authentication token, or undefined if authentication failed.
68+
*/
5469
public async authenticate(context: TurnContext, state: TState): Promise<string | undefined> {
5570
// Get property names to use
5671
const userAuthStatePropertyName = this.getUserAuthStatePropertyName(context);
@@ -82,6 +97,11 @@ export abstract class BotAuthenticationBase<TState extends TurnState> {
8297
return undefined;
8398
}
8499

100+
/**
101+
* Checks if the activity is a valid message activity
102+
* @param {TurnContext} context - The turn context.
103+
* @returns {boolean} - True if the activity is a valid message activity.
104+
*/
85105
public isValidActivity(context: TurnContext): boolean {
86106
// Should be a message activity with non-empty text property.
87107
return (
@@ -112,6 +132,11 @@ export abstract class BotAuthenticationBase<TState extends TurnState> {
112132
this._userSignInFailureHandler = handler;
113133
}
114134

135+
/**
136+
* Handles the signin/verifyState activity. The onUserSignInSuccess and onUserSignInFailure handlers will be called based on the result.
137+
* @param {TurnContext} context - The turn context.
138+
* @param {TState} state - The turn state.
139+
*/
115140
public async handleSignInActivity(context: TurnContext, state: TState): Promise<void> {
116141
try {
117142
const userDialogStatePropertyName = this.getUserDialogStatePropertyName(context);
@@ -149,6 +174,11 @@ export abstract class BotAuthenticationBase<TState extends TurnState> {
149174
}
150175
}
151176

177+
/**
178+
* Deletes the user auth state and user dialog state from the turn state. So that the next message can start a new authentication flow.
179+
* @param {TurnContext} context - The turn context.
180+
* @param {TState} state - The turn state.
181+
*/
152182
public deleteAuthFlowState(context: TurnContext, state: TState) {
153183
// Delete user auth state
154184
const userAuthStatePropertyName = this.getUserAuthStatePropertyName(context);
@@ -163,10 +193,20 @@ export abstract class BotAuthenticationBase<TState extends TurnState> {
163193
}
164194
}
165195

196+
/**
197+
* Gets the property name for storing user authentication state.
198+
* @param {TurnContext} context - The turn context.
199+
* @returns {string} - The property name.
200+
*/
166201
public getUserAuthStatePropertyName(context: TurnContext): string {
167202
return `__${context.activity.from.id}:${this._settingName}:Bot:AuthState__`;
168203
}
169204

205+
/**
206+
* Gets the property name for storing user dialog state.
207+
* @param {TurnContext} context - The turn context.
208+
* @returns {string} - The property name.
209+
*/
170210
public getUserDialogStatePropertyName(context: TurnContext): string {
171211
return `__${context.activity.from.id}:${this._settingName}:DialogState__`;
172212
}
@@ -188,12 +228,26 @@ export abstract class BotAuthenticationBase<TState extends TurnState> {
188228
return context.activity.type === ActivityTypes.Invoke && context.activity.name === tokenExchangeOperationName;
189229
}
190230

231+
/**
232+
* Run or continue the authentication dialog.
233+
* @param {TurnContext} context - The turn context.
234+
* @param {TState} state - The turn state.
235+
* @param {string} dialogStateProperty - The property name for storing dialog state.
236+
* @returns {Promise<DialogTurnResult<TokenResponse>>} - A promise that resolves to the dialog turn result containing the token response.
237+
*/
191238
public abstract runDialog(
192239
context: TurnContext,
193240
state: TState,
194241
dialogStateProperty: string
195242
): Promise<DialogTurnResult<TokenResponse>>;
196243

244+
/**
245+
* Continues the authentication dialog.
246+
* @param {TurnContext} context - The turn context.
247+
* @param {TState} state - The turn state.
248+
* @param {string} dialogStateProperty - The property name for storing dialog state.
249+
* @returns {Promise<DialogTurnResult<TokenResponse>>} - A promise that resolves to the dialog turn result containing the token response.
250+
*/
197251
public abstract continueDialog(
198252
context: TurnContext,
199253
state: TState,

js/packages/teams-ai/src/authentication/MessageExtensionAuthenticationBase.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,15 @@ import { MessageExtensionsInvokeNames } from '../MessageExtensions';
33

44
/**
55
* @internal
6+
* Base class to handle authentication for Teams Message Extension.
67
*/
78
export abstract class MessageExtensionAuthenticationBase {
9+
10+
/**
11+
* Authenticates the user.
12+
* @param {TurnContext} context - The turn context.
13+
* @returns {Promise<string | undefined>} - The authentication token, or undefined if authentication failed. Teams will ask user to sign-in if authentication failed.
14+
*/
815
public async authenticate(context: TurnContext): Promise<string | undefined> {
916
const value = context.activity.value;
1017
const tokenExchangeRequest = value.authentication;
@@ -75,6 +82,11 @@ export abstract class MessageExtensionAuthenticationBase {
7582
return;
7683
}
7784

85+
/**
86+
* Checks if the activity is a valid Message Extension activity that supports authentication.
87+
* @param {TurnContext} context - The turn context.
88+
* @returns {boolean} - A boolean indicating if the activity is valid.
89+
*/
7890
public isValidActivity(context: TurnContext): boolean {
7991
return (
8092
context.activity.type == ActivityTypes.Invoke &&
@@ -85,11 +97,27 @@ export abstract class MessageExtensionAuthenticationBase {
8597
);
8698
}
8799

100+
/**
101+
* Handles the SSO token exchange.
102+
* @param {TurnContext} context - The turn context.
103+
* @returns {Promise<TokenResponse | undefined>} - A promise that resolves to the token response or undefined if token exchange failed.
104+
*/
88105
public abstract handleSsoTokenExchange(
89106
context: TurnContext
90107
): Promise<TokenResponse | undefined>
91108

109+
/**
110+
* Handles the user sign-in.
111+
* @param {TurnContext} context - The turn context.
112+
* @param {string} magicCode - The magic code from user sign-in.
113+
* @returns {Promise<TokenResponse | undefined>} - A promise that resolves to the token response or undefined if failed to verify the magic code.
114+
*/
92115
public abstract handleUserSignIn(context: TurnContext, magicCode: string): Promise<TokenResponse | undefined>
93116

117+
/**
118+
* Gets the sign-in link for the user.
119+
* @param {TurnContext} context - The turn context.
120+
* @returns {Promise<string | undefined>} - A promise that resolves to the sign-in link or undefined if no sign-in link available.
121+
*/
94122
public abstract getSignInLink(context: TurnContext): Promise<string | undefined>
95123
}

js/packages/teams-ai/src/authentication/OAuthAdaptiveCardAuthentication.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,26 @@ import { AdaptiveCardAuthenticationBase, AdaptiveCardLoginRequest } from './Adap
66
import { AuthError, OAuthSettings } from './Authentication';
77
import * as UserTokenAccess from './UserTokenAccess';
88

9+
/**
10+
* @internal
11+
*
12+
* Handles authentication for Adaptive Cards in Teams.
13+
*/
914
export class OAuthAdaptiveCardAuthentication extends AdaptiveCardAuthenticationBase {
15+
16+
/**
17+
* Creates a new instance of OAuthAdaptiveCardAuthentication.
18+
* @param settings The OAuthSettings.
19+
*/
1020
public constructor(private readonly settings: OAuthSettings) {
1121
super();
1222
}
1323

24+
/**
25+
* Handles the SSO token exchange.
26+
* @param context The turn context.
27+
* @returns A promise that resolves to the token response or undefined if token exchange failed.
28+
*/
1429
public async handleSsoTokenExchange(context: TurnContext): Promise<TokenResponse | undefined> {
1530
const tokenExchangeRequest = context.activity.value.authentication;
1631

@@ -21,10 +36,21 @@ export class OAuthAdaptiveCardAuthentication extends AdaptiveCardAuthenticationB
2136
return await UserTokenAccess.exchangeToken(context, this.settings, tokenExchangeRequest);
2237
}
2338

39+
/**
40+
* Handles the signin/verifyState activity.
41+
* @param context The turn context.
42+
* @param magicCode The magic code from sign-in.
43+
* @returns A promise that resolves to undefined. The parent class will trigger silentAuth again.
44+
*/
2445
public async handleUserSignIn(context: TurnContext, magicCode: string): Promise<TokenResponse | undefined> {
2546
return await UserTokenAccess.getUserToken(context, this.settings, magicCode);
2647
}
2748

49+
/**
50+
* Gets the sign-in link for the user.
51+
* @param context The turn context.
52+
* @returns A promise that resolves to the sign-in link or undefined if no sign-in link available.
53+
*/
2854
public async getLoginRequest(context: TurnContext): Promise<AdaptiveCardLoginRequest> {
2955
const signInResource = await UserTokenAccess.getSignInResource(context, this.settings);
3056
const signInLink = signInResource.signInLink;

js/packages/teams-ai/src/authentication/OAuthBotAuthentication.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,22 @@ import { Application } from '../Application';
1616
import { TurnState } from '../TurnState';
1717
import { TurnStateProperty } from '../TurnStateProperty';
1818

19+
/**
20+
* @internal
21+
*
22+
* Handles authentication for Teams bots.
23+
* @template TState - The type of the turn state object.
24+
*/
1925
export class OAuthBotAuthentication<TState extends TurnState> extends BotAuthenticationBase<TState> {
2026
private _oauthPrompt: OAuthPrompt;
2127

28+
/**
29+
* Initializes a new instance of the OAuthBotAuthentication class.
30+
* @param app - The application object.
31+
* @param oauthPromptSettings - The settings for OAuthPrompt.
32+
* @param settingName - The name of the setting.
33+
* @param storage - The storage object for storing state.
34+
*/
2235
public constructor(
2336
app: Application<TState>,
2437
oauthPromptSettings: OAuthPromptSettings, // Child classes will have different types for this
@@ -34,6 +47,13 @@ export class OAuthBotAuthentication<TState extends TurnState> extends BotAuthent
3447
app.adapter.use(new FilteredTeamsSSOTokenExchangeMiddleware(this._storage, oauthPromptSettings.connectionName));
3548
}
3649

50+
/**
51+
* Run or continue the OAuthPrompt dialog and returns the result.
52+
* @param context - The turn context object.
53+
* @param state - The turn state object.
54+
* @param dialogStateProperty - The name of the dialog state property.
55+
* @returns A promise that resolves to the dialog turn result containing the token response.
56+
*/
3757
public async runDialog(
3858
context: TurnContext,
3959
state: TState,
@@ -47,6 +67,14 @@ export class OAuthBotAuthentication<TState extends TurnState> extends BotAuthent
4767
return results;
4868
}
4969

70+
71+
/**
72+
* Continue the OAuthPrompt dialog and returns the result.
73+
* @param context - The turn context object.
74+
* @param state - The turn state object.
75+
* @param dialogStateProperty - The name of the dialog state property.
76+
* @returns A promise that resolves to the dialog turn result containing the token response.
77+
*/
5078
public async continueDialog(
5179
context: TurnContext,
5280
state: TState,
@@ -56,6 +84,13 @@ export class OAuthBotAuthentication<TState extends TurnState> extends BotAuthent
5684
return await dialogContext.continueDialog();
5785
}
5886

87+
/**
88+
* Creates a new DialogContext for OAuthPrompt.
89+
* @param context - The turn context object.
90+
* @param state - The turn state object.
91+
* @param dialogStateProperty - The name of the dialog state property.
92+
* @returns A promise that resolves to the dialog context.
93+
*/
5994
private async createDialogContext(
6095
context: TurnContext,
6196
state: TState,

0 commit comments

Comments
 (0)