Skip to content

[JS] feat: Authentication #670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 94 commits into from
Nov 11, 2023
Merged

[JS] feat: Authentication #670

merged 94 commits into from
Nov 11, 2023

Conversation

singhk97
Copy link
Collaborator

@singhk97 singhk97 commented Oct 12, 2023

Linked issues

closes: #738, #739

Details

Foundations of handling user authentication.

  1. Authentication class encapsulates logic to authentication for a single connection.
    • It currently supports bot and messaging extension authentication through the OAuthPrompt, using BF Token service implicitly.
    • Subsequent PR will include support bot and messaging extension authentication without BF Token service.
  2. AuthenticationManager class handles multiple user configured connections and exposes signInUser and signOutUser methods for application code initiate authentication.
  3. Users create AuthenticationOptions object to configure authentication:
    • settings: contains one or more user authentication settings
    • default: the default setting to use in the auto sign in flow.
    • autoSignIn: whether to sign user in by default at the start of every turn. Set to true by default.

Public api:

Authentication.ts

/**
 * User authentication service.
 */
export class Authentication<TState extends TurnState = DefaultTurnState> {
    public readonly settings: OAuthPromptSettings;

    /**
     * Creates a new instance of the `Authentication` class.
     * @param {Application} app - The application instance.
     * @param {string} name - The name of the connection.
     * @param {OAuthPromptSettings} settings - Authentication settings.
     * @param {Storage} storage - A storage instance otherwise Memory Storage is used.
     * @param {MessagingExtensionAuthentication} messagingExtensionsAuth - Handles messaging extension flow authentication.
     * @param {BotAuthentication} botAuth - Handles bot-flow authentication.
     */
    constructor(
        app: Application<TState>,
        name: string,
        settings: OAuthPromptSettings,
        storage?: Storage,
        messagingExtensionsAuth?: MessagingExtensionAuthentication,
        botAuth?: BotAuthentication<TState>
    );

    /**
     * Signs in a user.
     *
     * This method will be called automatically by the Application class.
     * @template TState
     * @param {TurnContext} context - Current turn context.
     * @param {TState} state Application state.
     * @returns {string | undefined} The authentication token or undefined if the user is still login in.
     */
    public signInUser(context: TurnContext, state: TState): Promise<string | undefined>;

    /**
     * Signs out a user.
     * @template TState
     * @param {TurnContext} context - Current turn context.
     * @param {TState} state - Application state.
     * @returns {Promise<void>} A Promise representing the asynchronous operation.
     */
    public signOutUser(context: TurnContext, state: TState): Promise<void>;

    /**
     * Check is the user is signed, if they are then returns the token.
     * @param {TurnContext} context Current turn context.
     * @returns {string | undefined} The token string or undefined if the user is not signed in.
     */
    public isUserSignedIn(context: TurnContext): Promise<string | undefined>;

    /**
     * The handler function is called when the user has successfully signed in.
     * This only applies if sign in was initiated by the user sending a message to the bot.
     * This handler will not be triggered if a messaging extension triggered the authentication flow.
     * @template TState
     * @param {(context: TurnContext, state: TState) => Promise<void>} handler The handler function to call when the user has successfully signed in
     */
    public onUserSignInSuccess(handler: (context: TurnContext, state: TState) => Promise<void>): Promise<void>;

    /**
     * This handler function is called when the user sign in flow fails.
     * This only applies if sign in was initiated by the user sending a message to the bot.
     * This handler will not be triggered if a messaging extension triggered the authentication flow.
     * @template TState
     * @param {(context: TurnContext, state: TState, error: AuthError) => Promise<void>} handler The handler function to call when the user failed to signed in.
     */
    public onUserSignInFailure(
        handler: (context: TurnContext, state: TState, error: AuthError) => Promise<void>
    ): Promise<void>;
}

AuthenticationManager.ts

/**
 * The user authentication manager.
 */
export class AuthenticationManager<TState extends TurnState = DefaultTurnState> {
    /**
     * Creates a new instance of the `AuthenticationManager` class.
     * @param {Application} app - The application instance.
     * @param {AuthenticationOptions} options - Authentication options.
     * @param {Storage} storage - A storage instance otherwise Memory Storage is used.
     */
    constructor(app: Application<TState>, options: AuthenticationOptions, storage?: Storage);

    /**
     * @template TState
     * Gets the authentication instance for the specified connection name.
     * @param {string} name The setting name.
     * @returns {Authentication<TState>} The authentication instance.
     */
    public get(name: string): Authentication<TState>;

    /**
     * Signs in a user.
     * @template TState
     * @param {TurnContext} context The turn context.
     * @param {TState} state The turn state.
     * @param {string} settingName Optional. The name of the setting to use. If not specified, the default setting name is used.
     * @returns {Promise<SignInResponse>} The sign in response.
     */
    public signUserIn(context: TurnContext, state: TState, settingName?: string): Promise<SignInResponse>;

    /**
     * Signs out a user.
     * @template TState
     * @param {TurnContext} context The turn context.
     * @param {TState} state The turn state.
     * @param {string} settingName Optional. The name of the setting to use. If not specified, the default setting name is used.
     */
    public signOutUser(context: TurnContext, state: TState, settingName?: string): Promise<void>;

AuthenticationOptions

/**
 * The options to configure the authentication manager
 */
export interface AuthenticationOptions {
    /**
     * The authentication settings.
     * Key uniquely identifies the connection string.
     */
    settings: { [key: string]: OAuthPromptSettings };

    /**
     * Describes the setting the bot should use if the user does not specify a setting name.
     */
    default?: string;

    /**
     * Defaults to true.
     * Indicates whether the bot should start the sign in flow when the user sends a message to the bot or triggers a message extension.
     * If set to false, the bot will not start the sign in flow before routing the activity to the bot logic.
     *
     * To set custom logic, set this property to the selector function.
     */
    autoSignIn?: boolean | Selector;
}

 

Task list

  • Sso-auth bot sample
  • Sso-auth message extension sample
  • Support for multiple auth configurations (ex. AADv2, github auth...etc)
  • Unit tests

Stevenic and others added 30 commits May 19, 2023 06:03
## Linked issues

closes: #611

## Details

Implement fluent APIs in new Application class.

#### Change details

New APIs:
- OnActivity(string, Handler);
- OnActivity(Regex, Handler);
- OnActivity(Router, Handler);
- OnActivity(MultiRouter, Handler);
- OnConversationUpdate(string, Handler);
- OnConversationUpdate(string[], Handler);
- OnMessage(string, Handler);
- OnMessage(Regex, Handler);
- OnMessage(Router, Handler);
- OnMessage(MultiRouter, Handler);
- OnMessageReactionsAdded(Handler);
- OnMessageReactionsRemoved(Handler);
- OnBeforeTurn(Handler);
- OnAfterTurn(Handler);

## 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

### Additional information

> Feel free to add other relevant information below
)

## Linked issues

closes: #601 

## Details
#### Change details
- use `AdaptiveCardInvokeResponse` as return type of
`ActionExecuteHandler`. The change is because the original style cannot
meet the following requirement: return values with different types in
one handler. For example, if I'd like to return Adaptive Card or text
message by some cases in `OnActionExecute("verb")`, I have to define
`OnActionExecute("verb", ActionExecuteAdaptiveCardHandler)` and
`OnActionExecute("verb", ActionExecuteTextHandler)` respectively.
Although the two handlers will be hit, only one result will be returned.
A concrete example is `SubmitAction` in gptME sample.

## 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

### Additional information

> Feel free to add other relevant information below
## Linked issues

closes: #602 

## Details
#### Change details
Delegates:
- Task\<MessagingExtensionActionResponse>
SubmitActionHandler\<TState>(ITurnContext, TState, object,
CancellationToken)
- Task\<MessagingExtensionActionResponse>
BotMessagePreviewEditHandler\<TState>(ITurnContext, TState, Activity,
CancellationToken)
- Task BotMessagePreviewSendHandler\<TState>(ITurnContext, TState,
Activity, CancellationToken)
- Task\<TaskModuleResponse> FetchTaskHandler\<TState>(ITurnContext,
TState, CancellationToken)
- Task\<MessagingExtensionResult> QueryHandler\<TState>(ITurnContext,
TState, Query<Dictionary<string, object>>, CancellationToken)
- Task\<MessagingExtensionResult>
SelectItemHandler\<TState>(ITurnContext, TState, object,
CancellationToken)
- Task\<MessagingExtensionResult>
QueryLinkHandler\<TState>(ITurnContext, TState, string,
CancellationToken)

APIs:
- OnSubmitAction(string, SubmitActionHandler<TState>)
- OnSubmitAction(Regex, SubmitActionHandler<TState>)
- OnSubmitAction(RouteSelector, SubmitActionHandler<TState>)
- OnSubmitAction(MultipleRouteSelector, SubmitActionHandler<TState>)
- OnBotMessagePreviewEdit(string, BotMessagePreviewEditHandler<TState>)
- OnBotMessagePreviewEdit(Regex, BotMessagePreviewEditHandler<TState>)
- OnBotMessagePreviewEdit(RouteSelector,
BotMessagePreviewEditHandler<TState>)
- OnBotMessagePreviewEdit(MultipleRouteSelector,
BotMessagePreviewEditHandler<TState>)
- OnBotMessagePreviewSend(string, BotMessagePreviewSendHandler<TState>)
- OnBotMessagePreviewSend(Regex, BotMessagePreviewSendHandler<TState>)
- OnBotMessagePreviewSend(RouteSelector,
BotMessagePreviewSendHandler<TState>)
- OnBotMessagePreviewSend(MultipleRouteSelector,
BotMessagePreviewSendHandler<TState>)
- OnFetchTask(string, FetchTaskHandler<TState>)
- OnFetchTask(Regex, FetchTaskHandler<TState>)
- OnFetchTask(RouteSelector, FetchTaskHandler<TState>)
- OnFetchTask(MultipleRouteSelector, FetchTaskHandler<TState>)
- OnQuery(string, QueryHandler<TState>)
- OnQuery(Regex, QueryHandler<TState>)
- OnQuery(RouteSelector, QueryHandler<TState>)
- OnQuery(MultipleRouteSelector, QueryHandler<TState>)
- OnSelectItem(SelectItemHandler<TState>)
- OnQueryLink(QueryLinkHandler<TState>)
- OnAnonymousQueryLink(QueryLinkHandler<TState>)

## 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

### Additional information

> Feel free to add other relevant information below
## Linked issues

closes: #601 #602

## Details
#### Change details
- add AdaptiveCardInvokeResponseFactory
- improve xml doc

## 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

### Additional information

> Feel free to add other relevant information below
## Linked issues

closes: #601 #602

## Details
#### Change details
- move adaptive card handlers and message extension handlers to separate
files
- add type constraint for TState in handlers


## 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

### Additional information

> Feel free to add other relevant information below
## Linked issues

closes: #604 

## Details
#### Change details

- update echoBot to use fluent api

## Attestation Checklist

- [ ] 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

### Additional information

> Feel free to add other relevant information below
…#690)

## Linked issues

closes: #601 #602 
## Details

#### Change details

- add AdaptiveCards and MessageExtensions in Application

## 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

### Additional information

> Feel free to add other relevant information below
## Linked issues

closes: #600

## Details

Replace legacy application with new fluent one (keep in root namespace)

#### Change details

- Remove the legacy application
- Make new application under root namespace (same as the legacy one, as
well as JS/PYTHON)
- Refine the folder structure of
application/adaptivecards/messagextensions/...
- Update unit tests

## 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

### Additional information

> Feel free to add other relevant information below
## Linked issues

closes: #604 

## Details

#### Change details

- update 02.messageExtensions.a.searchCommand sample to use fluent api

## 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

### Additional information

> Feel free to add other relevant information below
## Linked issues

closes: #604 

## Details

#### Change details

- update 03.adaptiveCards.a.typeAheadBot sample to use fluent api

## 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

### Additional information

> Feel free to add other relevant information below
## Linked issues

closes: #604

## Details

Update dotnet samples to use fluent api

#### Change details

- List Bot
- DevOps Bot
- Twenty Questions Bot
- Quest Bot

## 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

### Additional information

> Feel free to add other relevant information below
## Linked issues

closes: #604 

## Details

#### Change details

- 04.ai.a.teamsChefBot
- 04.ai.b.messageExtensions.gptME

## 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

### Additional information

> Feel free to add other relevant information below
@singhk97 singhk97 merged commit 28a8c60 into main Nov 11, 2023
@singhk97 singhk97 deleted the kavin/auth-js branch November 11, 2023 01:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
7 participants