Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion msteams-platform/TOC.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
href: ./concepts/authentication/auth-bot-AAD
- name: Silent authentication and SSO
href: ./concepts/authentication/auth-silent-AAD
- name: Configuring authentication providers
- name: Configuring identity providers
href: ./concepts/authentication/auth-configure
- name: Activity Feed
href: ./concepts/activity-feed
Expand Down
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified msteams-platform/concepts/authentication/Sequence Diagrams.vsdx
Binary file not shown.
150 changes: 70 additions & 80 deletions msteams-platform/concepts/authentication/auth-bot-AAD.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Authentication for bots using Azure Active Directory
description: Describes AAD authentication in Teams and how to use it in your bots
keywords: teams authentication bots AAD
ms.date: 02/28/2018
ms.date: 03/01/2018
---
# Authenticate a user in a Microsoft Teams bot

Expand All @@ -14,116 +14,106 @@ The authentication flow described in this article is very similar to that of tab

For a general overview of authentication flow for bots see the topic [Authentication flow in bots](~/concepts/authentication/auth-flow-bot).

## Configure an authentication provider
## Configuring identity providers

See the topic [Configure an authentication provider](~/concepts/authentication/auth-configure) for detailed steps on configuring Azure Active Directory for authentication.
See the topic [Configure identity providers](~/concepts/authentication/configure-AAD) for detailed steps on configuring OAuth 2.0 callback redirect URL(s) when using Azure Active Directory as an identity provider.

## Initiate authentication flow

Usually authentication flow is triggered by a user action. You should not drive the authentication pop-up automatically because this is likely to trigger the browser's pop-up blocker as well as confuse the user.
Authentication flow should be triggered by a user action. You should not open the authentication pop-up automatically because this is likely to trigger the browser's pop-up blocker as well as confuse the user.

## Add UI to start authentication

Add UI to the bot to enable the user to sign in when needed. Here it is done from the bot's hero card.
Add UI to the bot to enable the user to sign in when needed. Here it is done from a Thumbnail card, in TypeScript:

```TypeScript
let buttons = new Array<builder.CardAction>();
buttons.push(new builder.CardAction(session)
.type("signin")
.title("Sign In")
.value(config.get("app.baseUri") + "/bot-auth/simple-start?width=5000&height=5000"),
);

let messageBackButton = builder.CardAction.messageBack(session, JSON.stringify({ action: "getProfile" }), "Get Profile")
.displayText("Get Profile")
.text(Strings.messageBack_button_text); // this matches match for MessageBackReceiverDialog
buttons.push(messageBackButton);

let messageBackButton2 = builder.CardAction.messageBack(session, JSON.stringify({ action: "signout" }), "Sign Out")
.displayText("Sign Out")
.text(Strings.messageBack_button_text); // this matches match for MessageBackReceiverDialog
buttons.push(messageBackButton2);

// Show prompt of options
protected async promptForAction(session: builder.Session): Promise<void> {
let msg = new builder.Message(session)
.addAttachment(new builder.ThumbnailCard(session)
.title(this.providerDisplayName)
.buttons([
builder.CardAction.messageBack(session, "{}", "Sign in")
.text("SignIn")
.displayText("Sign in"),
builder.CardAction.messageBack(session, "{}", "Show profile")
.text("ShowProfile")
.displayText("Show profile"),
builder.CardAction.messageBack(session, "{}", "Sign out")
.text("SignOut")
.displayText("Sign out"),
]));
session.send(msg);
}
```

Three buttons have been added to the Hero Card: Sign in, Get Profile, and Sign Out.
Three buttons have been added to the Hero Card: Sign in, Show Profile, and Sign out.

## Sign the user in

selecting the Sign in button generates an event that is handled in `getInvokeHandler` using this code:

```TypeScript
if ((event as any).name === "signin/verifyState") {
let aadApi = new AADRequestAPI();
let response = await aadApi.getAsync("https://graph.microsoft.com/v1.0/me/", { Authorization: " Bearer " + (event as any).value.state.accessToken }, null);

let info = JSON.parse(response);

session.send(info.displayName + "<br />" + info.mail + "<br />" + info.officeLocation);

callback(null, "", 200);
return;
}
```

Here the bot makes a call to the `me` Graph endpoint with the token it gets from the invoke payload. Graph responds with the user information for the person who logged in. The response is then parsed and specific parts of it are sent to the chat session.
Because of the validation that must be performed for security reasons and the support for the mobile versions of Teams, the code isn't shown here, but [here's an example of the code that kicks off the process when the user presses the Sign in button.](https://github.com/OfficeDev/microsoft-teams-sample-auth-node/blob/e84020562d7c8b83f4a357a4a4d91298c5d2989d/src/dialogs/BaseIdentityDialog.ts#L154-L195).

### Notes
The validation and mobile support are explained in the topic [Authentication flow in bots](~/concepts/authentication/auth-flow-bot).

Authentication flow must start on a page that's on your domain; don't start it by going directly to your identity provider's login or consent page. In this example, even though we're using Azure AD, we begin at `/tab-auth/simple-start` rather than going directly to the Graph endpoint at `https://graph.microsoft.com/v1.0/me/`. If you skip this step, the login popup may fail to close when you call `notifySuccess()` or `notifyFailure()`.
Be sure to add the domain of your authentication redirect URL to the [`validDomains`](~/resources/schema/manifest-schema#validdomains) section of the manifest. If you don't, the login popup will not appear.

Add the domain of your authentication redirect URL to the [`validDomains`](~/resources/schema/manifest-schema#validdomains) section of the manifest. Failure to do so might result in an empty pop-up.
## Showing user profile information

## Get the users profile

When the user selects the `Get Profile` button in the Hero card the following code is executed.
Although getting an access token is difficult because of all the transitions back and forth across different websites and the security issues that must be addressed, once you have a token, obtaining information from Azure Active Directory is straightforward. The bot makes a call to the `me` Graph endpoint with the access token. Graph responds with the user information for the person who logged in. Information from the response is used to construct a bot card and sent.

```TypeScript
case "getProfile":
// See if we have an AAD token
const graphResource = "https://graph.microsoft.com";
let aadTokens = session.userData.aadTokens || {};
let graphToken = aadTokens[graphResource] as TokenResponse;

if (!graphToken) {
// We don't have a Graph token for the user, ask them to sign in
session.send(new builder.Message(session)
.addAttachment(new builder.HeroCard(session)
.text("You're not yet signed in. Please click on the Sign In button to log in.")
.buttons([
new builder.CardAction(session)
.type("signin")
.title("Sign In")
.value(config.get("app.baseUri") + "/bot-auth/simple-start?width=5000&height=5000"),
])));
// Show user profile
protected async showUserProfile(session: builder.Session): Promise<void> {
let azureADApi = this.authProvider as AzureADv1Provider;
let userToken = this.getUserToken(session);

if (userToken) {
let profile = await azureADApi.getProfileAsync(userToken.accessToken);
let profileCard = new builder.ThumbnailCard()
.title(profile.displayName)
.subtitle(profile.mail)
.text(`${profile.jobTitle}<br/> ${profile.officeLocation}`);
session.send(new builder.Message().addAttachment(profileCard));
} else {
// Use the Graph token to get the basic profile
try {
let requestHelper = new AADRequestAPI();
let response = await requestHelper.getAsync("https://graph.microsoft.com/v1.0/me/", { Authorization: "Bearer " + graphToken.access_token }, null);

let info = JSON.parse(response);
session.send(info.displayName + "<br />" + info.mail + "<br />" + info.officeLocation);
} catch (e) {
console.log(e);
session.send("There was an error getting the user's profile.");
}
session.send("Please sign in to AzureAD so I can access your profile.");
}

await this.promptForAction(session);
}

// Helper function to make the Graph API call
public async getProfileAsync(accessToken: string): Promise<any> {
let options = {
url: "https://graph.microsoft.com/v1.0/me",
json: true,
headers: {
"Authorization": `Bearer ${accessToken}`,
},
};
return await request.get(options);
}
```

If the user is not signed in they are prompted to do so now. Otherwise basic information is obtained from Graph.
If the user is not signed in they are prompted to do so.

## Sign the user out

```TypeScript
case "signout":
session.userData.aadTokens = {};
session.send("Ok, I've cleared your tokens.");
break;
// Handle user logout request
private async handleLogout(session: builder.Session): Promise<void> {
if (!utils.getUserToken(session, this.providerName)) {
session.send(`You're already signed out of ${this.providerDisplayName}.`);
} else {
utils.setUserToken(session, this.providerName, null);
session.send(`You're now signed out of ${this.providerDisplayName}.`);
}

await this.promptForAction(session);
}
```

## Other samples

For sample code showing the bot authentication process see:

* [Microsoft Teams bot authentication sample](https://github.com/OfficeDev/microsoft-teams-sample-auth-node)
* [Microsoft Teams bot authentication sample](https://github.com/OfficeDev/microsoft-teams-sample-auth-node)
24 changes: 12 additions & 12 deletions msteams-platform/concepts/authentication/auth-configure.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
---
title: Configure an authentication provider
description: Describes how to configure an authentication provider
keywords: teams authentication AAD
ms.date: 02/28/2018
title: Configuring OAuth 2.0 identity providers
description: Describes how to configure identity providers with a focus on AAD
keywords: teams authentication AAD oauth identity provider
ms.date: 03/01/2018
---
# Configure an authentication provider
# Configuring identity providers

## Configure Azure Active Directory for authentication
## Configuring an application to use Azure Active Directory as an identity provider

Most service providers require you to register your application with their service before you can authenticate and consume service resources. To do this with AAD follow these steps:
Identity providers supporting OAuth 2.0 will not authenticate requests from unknown applications; applications must be registered ahead of time. To do this with AAD, follow these steps:

1. Open the [Application Registration Portal](https://apps.dev.microsoft.com/), click on *Add an app* and follow the steps to register your app. If your app has already been registered (for example if you have previously registered a bot in your app) locate your app.

2. Select your app to view it's properties. Find the *Platforms* section for the app and select *Add Platform*.
2. Select your app to view its properties. Find the *Platforms* section for the app and select *Add Platform*.

![View team](~/assets/images/authentication/AppRegistration.png)

Expand All @@ -24,16 +24,16 @@ Most service providers require you to register your application with their servi

![View team](~/assets/images/authentication/Platforms.png)

Add the redirect and logout URLs in the Web section of Platforms. For the TypeScript/Node.js and C# sample apps on GitHub, the redirect URLs will be similar to this:
Add the OAuth 2.0 redirect and logout URLs in the Web section of Platforms. For the TypeScript/Node.js and C# sample apps on GitHub, the redirect URLs will be similar to this:

Redirect URLs: https://yourhost/bot-auth/simple-start
Redirect URLs: https://\<hostname\>/bot-auth/simple-start

No logout URL is required.

`yourhost` is replaced by your actual host. This might be a dedicated hosting site, Glitch or an ngrok redirect to localhost on your development machine. You may not have this information yet if you have not completed or hosted your app (or the sample app mentioned above), but you can always return to this page when that information is known.
Replace `<hostname>` with your actual host. This might be a dedicated hosting site such as Azure, Glitch, or an ngrok tunnel to localhost on your development machine such as `abcd1234.ngrok.io`. You may not have this information yet if you have not completed or hosted your app (or the sample app mentioned above), but you can always return to this page when that information is known.

## Other authentication providers

* **LinkedIn** Follow the instructions in [Configuring your LinkedIn application](https://developer.linkedin.com/docs/oauth2)

* **Google** Obtain OAuth2 client credentials from the [Google API Console](https://console.developers.google.com/)
* **Google** Obtain OAuth2 client credentials from the [Google API Console](https://console.developers.google.com/)
14 changes: 8 additions & 6 deletions msteams-platform/concepts/authentication/auth-flow-bot.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Authentication flow for bots
description: Describes authentication flow in bots
keywords: teams authentication flow bots
ms.date: 02/28/2018
ms.date: 03/01/2018
---
# Microsoft Teams authentication flow for bots

Expand All @@ -23,12 +23,14 @@ for an example that demonstrates authentication flow for bots using Node using t
5. The start page redirects the user to the identity provider's `authorize` endpoint. ([View code](https://github.com/OfficeDev/microsoft-teams-sample-auth-node/blob/469952a26d618dbf884a3be53c7d921cc580b1e2/public/html/auth-start.html#L51-L56))
6. On the provider's site, the user signs in and grants access to the bot.
7. The provider takes the user to the bot's OAuth redirect page, with an authorization code.
8. The bot redeems the authorization code for an access token, and **provisionally** associates the token with the user that initiated the sign-in flow.
8. The bot redeems the authorization code for an access token, and **provisionally** associates the token with the user that initiated the sign-in flow. Below, we call this a *provisional token*.
* In the example, the bot associates the value of the `state` parameter with the id of the user that initiated the sign-in process so it can later match it with the `state` value returned by the identity provider. ([View code](https://github.com/OfficeDev/microsoft-teams-sample-auth-node/blob/469952a26d618dbf884a3be53c7d921cc580b1e2/src/AuthBot.ts#L70-L99))
* **IMPORTANT**: The bot stores the token it receives from the identity provider and associates it with a specific user, but it is marked as "pending validation". The token is not used while in this state. If the `state` pamrameter is valid, Teams then uses a [two-step authentication](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) process to ensure that the user who authorized the bot with the identity provider is the same user who is chatting with the bot. This guards against [man-in-the-middle](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) and [phishing](https://en.wikipedia.org/wiki/Phishing) attacks. On the desktop and web versions of Teams, the verification code is generated and verified automatically; on mobile devices the user may have to enter it manually [as described below](#Mobile-clients). ([View code](https://github.com/OfficeDev/microsoft-teams-sample-auth-node/blob/469952a26d618dbf884a3be53c7d921cc580b1e2/src/AuthBot.ts#L100-L113))
* **IMPORTANT**: The bot stores the token it receives from the identity provider and associates it with a specific user, but it is marked as "pending validation". The provisional token cannot be used yet: it must be further validated:
1. **Validate what's received from the identity provider.** The value of the `state` parameter must be confirmed against what was saved earlier.
1. **Validate what's received from Teams.** A [two-step authentication](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) validation is performed to ensure that the user who authorized the bot with the identity provider is the same user who is chatting with the bot. This guards against [man-in-the-middle](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) and [phishing](https://en.wikipedia.org/wiki/Phishing) attacks. The bot generates a verification code and stores it, associated with the user. On the desktop and web versions of Teams, the verification code is sent automatically by Teams as described below in steps 9 and 10; on mobile devices the user may have to enter it manually [as described below](#Mobile-clients). ([View code](https://github.com/OfficeDev/microsoft-teams-sample-auth-node/blob/469952a26d618dbf884a3be53c7d921cc580b1e2/src/AuthBot.ts#L100-L113))
9. The OAuth callback renders a page that calls `notifySuccess("<verification code>")`. ([View code](https://github.com/OfficeDev/microsoft-teams-sample-auth-node/blob/master/src/views/oauth-callback-success.hbs))
10. Teams closes the popup and sends the string given to `notifySuccess()` back to the bot. The bot receives an invoke message with `name = signin/verifyState`.
11. The bot checks the incoming verification code against the code stored in the user's provisional token. ([View code](https://github.com/OfficeDev/microsoft-teams-sample-auth-node/blob/469952a26d618dbf884a3be53c7d921cc580b1e2/src/dialogs/BaseIdentityDialog.ts#L127-L140))
10. Teams closes the popup and sends the `<verification code>` sent to `notifySuccess()` back to the bot. The bot receives an [invoke](https://docs.microsoft.com/en-us/bot-framework/dotnet/bot-builder-dotnet-activities#invoke) message with `name = signin/verifyState`.
11. The bot checks the incoming verification code against the verification code stored with the user's provisional token. ([View code](https://github.com/OfficeDev/microsoft-teams-sample-auth-node/blob/469952a26d618dbf884a3be53c7d921cc580b1e2/src/dialogs/BaseIdentityDialog.ts#L127-L140))
12. If they match, the bot marks the token as validated and ready for use. Otherwise, the auth flow fails, and the bot deletes the provisional token.

## Mobile clients
Expand All @@ -44,7 +46,7 @@ When the OAuth callback runs in a mobile browser, the call to `notifySuccess()`

If you want to limit signing in to web and desktop only, you can choose to omit the `fallbackUrl` parameter, or point it to your own error page that asks the user to sign in on web or desktop.

Once the Microsoft Teams mobile clients support the complete signin action protocol, including passing the verification code via `notifySuccess()`, they will launch the auth start page in a popup window and ignore `fallbackUrl`.
Once the Microsoft Teams mobile clients support the complete signin action protocol, including passing the verification code via `notifySuccess()`, they will launch the auth start page in a popup window and ignore `fallbackUrl`, just like the desktop and web clients.

## Samples

Expand Down
Loading