category
In this demo, we will show you how to authorize a user to access resources on an enterprise app with a bot using Microsoft Graph.
When dealing with personal data, please respect user privacy. Follow platform guidelines and post your privacy statement online.
Different companies may use different access delegation technologies to protect their resources. In our demo, we are targeting authorization through OAuth 2.0).
Although OAuth and OpenID are often related to each other, they solve different problems. OAuth is for authorization and access delegation, while OpenID is for authentication and user identity.
Instead of OpenID, most enterprise apps use OAuth plus a user profile API to identify an individual user. In this demo, we will demonstrate how to use OAuth to obtain access to user profile API and use the API to identifying the accessor.
This demo does not include any threat models and is designed for educational purposes only. When you design a production system, threat-modelling is an important task to make sure your system is secure and provide a way to quickly identify potential source of data breaches. IETF RFC 6819 and OAuth 2.0 for Browser-Based Apps is a good starting point for threat-modelling when using OAuth 2.0.
This demo integrates with multiple services. There are multiple services you need to setup in order to host the demo.
- Clone the code
- Setup OAuth via Azure Active Directory for the Web App
- Setup OAuth via Azure Active Directory for the Bot
- Setup Azure Bot Services
- Prepare and run the code
To host this demo, you will need to clone the code and run locally.
- Clone this repository
- Create two files for environment variables,
/bot/.env
and/rest-api/.env
- In
/rest-api/.env
:
- Write
AAD_OAUTH_REDIRECT_URI=http://localhost:3000/api/aad/oauth/callback
- When Azure Active Directory completes the authorization flow, it will send the browser to this URL. This URL must be accessible by the browser from the end-user machine
- Write
- In
- Go to your Azure Active Directory
- Create a new application
- Select "App registrations"
- Click "New registration"
- Fill out "Name", for example, "Web Chat On-Behalf-Of Sample"
- In "Redirect URI (optional)" section, add a new entry
- Select "Web" as type
- Enter
http://localhost:3000/api/aad/oauth/callback
as the redirect URI
- This must match
AAD_OAUTH_REDIRECT_URI
in/rest-api/.env
we saved earlier
- This must match
- Click "Register"
- Save the client and tenant ID
- Select the "Overview" blade
- On the main pane, copy the content of "Application (client) ID" and "Directory (tenant) ID" to
/rest-api/.env
, it should looks be a GUID
AAD_OAUTH_CLIENT_ID=12345678abcd-1234-5678-abcd-12345678abcd
AAD_OAUTH_TENANT_ID=abcd1234-abcd-1234-efgh-5678abcdefgh
- Update App Registration Manifest
- Select the "Manifest" blade
- Set
accessTokenAcceptedVersion
to2
- Set
oauth2AllowImplicitFlow
totrue
- Set
- Select the "Manifest" blade
- Enable ID Tokens
- Select the "Authentication" Blade
- Towards the bottom of the "Web" section, check the box next to "ID tokens" under "Implicit grant"
- Select the "Authentication" Blade
- Go to your Azure Active Directory
- Create a new application
- Select "App registrations"
- Click "New registration"
- Fill out "Name", for example, "Web Chat On-Behalf-Of Sample"
- In "Redirect URI (optional)" section, add a new entry
- Select "Web" as type
- Enter
https://token.botframework.com/.auth/web/redirect
as the redirect URI
- Click "Register"
- Update App Registration Manifest
- Select the "Manifest" blade
- Set
accessTokenAcceptedVersion
to2
- Set
- Select the "Manifest" blade
- Create a new client secret
- Select the "Certificates & secretes" blade
- Click the "New client secret"
- Add a scope and client application
- Select the "Expose an API" blade
- Add a new scope for the bot
- Click the "Add a scope" button under "Scopes defined by this API"
- Click "Save and continue"
- Add a scope name
- Set "Who can consent?" to "Admins and users"
- Add an admin consent display name
- Add an admin consent description
- Click "Add scope"
- Save the Scope URL to configure authentication for the bot in the Bot Registration in the next section
- api://123a45b6-789c-01de-f23g-h4ij5k67a8bc/scope
- Click the "Add a scope" button under "Scopes defined by this API"
- Add a client application
- Click the "Add a client application" under "Authorized client applications"
- Set the client id to the Web Applications client id (i.e. AAD_OAUTH_CLIENT_ID from above)
- Check the box next to the scope we added in the previous step under "Authorized scopes"
- Click "Add application"
- Click the "Add a client application" under "Authorized client applications"
- Add a new scope for the bot
- Select the "Expose an API" blade
We prefer using Bot Channel Registration during development. This will help you diagnose problems locally without deploying to the server and speed up development.
You can follow our instructions on how to setup a new Bot Channel Registration.
- Add OAuth Connection for the bot to the Bot Channel Registration
- In the Bot Channel Registration open the settings blade
- Under "OAuth Connection Settings" click the "Add Setting" button
- Add new Connection Setting
- Set the connection "name"
- Set the "Service Provider" to "Azure Active Directory 2"
- Add the Client ID, Client secret, and Tenant ID from setting up the OAuth connection for the Bot
- Set the "Token Exchange URL" to the scope URL that was created in the previous section
- api://123a45b6-789c-01de-f23g-h4ij5k67a8bc/scope
- Set the "Scopes" field to the scopes you want the bot to have permission to access (ie. user.read)
- Add new Connection Setting
- Save the Microsoft App ID, password, and OAuth connection name to
/bot/.env
MicrosoftAppId=12345678-1234-5678-abcd-12345678abcd
MicrosoftAppPassword=a1b2c3d4e5f6
connectionName=botOAuthConnection
- Save the Web Chat secret to
/rest-api/.env
DIRECT_LINE_SECRET=a1b2c3.d4e5f6g7h8i9j0
When you are building your production bot, never expose your Web Chat or Direct Line secret to the client. Instead, you should use the secret to generate a limited token and send it to the client. For information, please refer to this page on how to generate a Direct Line token and Enhanced Direct Line Authentication feature.
During development, you will run your bot locally. Azure Bot Services will send activities to your bot through a public URL. You can use ngrok to expose your bot server on a public URL.
- Run
ngrok http -host-header=localhost:3978 3978
- Update your Bot Channel Registration. You can use Azure CLI or Azure Portal
- Via Azure CLI
- Run
az bot update --resource-group <your-bot-rg> --name <your-bot-name> --subscription <your-subscription-id> --endpoint "https://a1b2c3d4.ngrok.io/api/messages"
- Run
- Via Azure Portal
- Browse to your Bot Channel Registration
- Select "Settings"
- In "Configuration" section, set "Messaging Endpoint" to
https://a1b2c3d4.ngrok.io/api/messages
- Via Azure CLI
- Under
app
,bot
, andrest-api
folder, run the following:
npm install
npm start
- Browse to http://localhost:3000/ to start the demo
- Notice there is a sign-in button on top-right hand corner
- Send any message to bot
- If you are not logged into the website, Web Chat will notify you to sign in.
- Once you are signed in Web Chat will notify you to authorize the bot to access your account.
- Send 'logout' to the bot to sign out of the bot and the website
Note, the first time the user authenticates the bot, they will have to sign in directly to the bot as well as the website. After this first interaction, the user can simply grant the bot access to their information without having to authenticate the bot again.
/app/
is the React app built usingcreate-react-app
scaffold/bot/
is the bot server/rest-api/
is the REST API for handling OAuth requests
GET /api/aad/oauth/callback
will handle callback from Azure AD OAuthGET /api/aad/settings
will send Azure AD OAuth settings to the React appGET /api/directline/token
will generate a new Direct Line token for the React app- It will serve React app as a static content
- During development-time, it will also serve the bot server via
/api/messages
- To enable this feature, add
PROXY_BOT_URL=http://localhost:3978
to/web/.env
- This will forward all traffic from
https://a1b2c3d4.ngrok.io/api/messages
tohttps://localhost:3978/api/messages
- To enable this feature, add
- Developer has an existing enterprise web app that uses OAuth to access protected resources
- We assume the website uses the
MSAL.js
npm package to authenticate users
- We assume the website uses the
- Website and bot conversation supports both anonymous and authenticated access
- Forced page refresh and/or new conversation is not mandated
- End-user is able to sign in through the web page, and is recognized by the bot immediately
- Vice versa, end-user is able to sign in through the bot, and is recognized by the web page immediately
- End-user is able to sign in through the web page and sign out though the bot
- Vice versa, end-user is able to sign in through the bot and sign out through the web page
The .env
files hold the environment variables critical to run the service. These are usually security-sensitive information and must not be committed to version control. Although we recommend keeping these keys in Azure Vault, for simplicity of this sample, we would keep them in .env
files.
To ease the setup of this sample, here is the template of .env
files.
MicrosoftAppId=12345678-1234-5678-abcd-12345678abcd
MicrosoftAppPassword=a1b2c3d4e5f6
connectionName=botOAuthConnection
AAD_OAUTH_CLIENT_ID=12345678abcd-1234-5678-abcd-12345678abcd
AAD_OAUTH_REDIRECT_URI=http://localhost:3000/api/aad/oauth/callback
AAD_OAUTH_TENANT_ID=abcd1234-abcd-1234-efgh-5678abcdefgh
DIRECT_LINE_SECRET=a1b2c3.d4e5f6g7h8i9j0
In this sample, we do not use OAuth card due to technical limitations on some OAuth providers which support single redirect URI only.
In order to use the website to sign in, the developer will need to set the redirect URI to their own web API.
In order to use the bot to sign in, in the OAuth provider, the developer will need to set the redirect URI to https://token.botframework.com/.auth/web/redirect.
Since some OAuth providers do not support multiple redirect URIs, we prefer using a single redirect URI from the web API to make sure existing authorization flow is not disturbed.
After having signed in on this app, click the profile photo on the upper-right hand corner, select "Review access on Office.com". Then, you will be redirected to the OAuth provider page to remove your authorization.
- On the AAD dashboard page, wait until "App permissions" loads. Here you see how many apps you have authorized
- Click "Change app permissions"
- In the "You can revoke permission for these apps" section, click the "Revoke" button below your app registration
- Microsoft identity platform and OAuth 2.0 On-Behalf-Of flow
- RFC 6749: The OAuth 2.0 Authorization Framework
- RFC 6819: OAuth 2.0 Threat Model and Security Considerations
- RFC 7636: Proof Key for Code Exchange by OAuth Public Clients
- IETF Draft: OAuth 2.0 for Browser-Based Apps
- Bot Framework Blog: Enhanced Direct Line Authentication feature
To reduce complexity, this sample is limited in scope. In your production system, you should consider enhancing it and review its threat model.
- Refreshing the access token
- Using silent prompt for refreshing access token
- Some OAuth providers support
?prompt=none
for refreshing access token silently through<iframe>
- Some OAuth providers support
- Using Authorization Code Grant flow with refresh token
- Save the refresh token on the server side of your web app. Never expose it to the browser or the bot
- This will also create a smooth UX by reducing the need for UI popups
- Using silent prompt for refreshing access token
- Threat model
- IETF RFC 6819 is a good starting point for threat-modelling when using OAuth 2.0
To lower the barrier for the end-user to initiate a conversation with the bot, in this sample, the conversation can be both anonymous or authenticated.
That means at some points of time, the mixed conversation can be authenticated as different users. If it is not a desirable scenario for your use case, you might want to create a new conversation if the user signed out.
- 登录 发表评论
- 2 次浏览
Tags
最新内容
- 2 days 15 hours ago
- 2 days 16 hours ago
- 2 days 16 hours ago
- 2 days 16 hours ago
- 2 days 17 hours ago
- 2 days 17 hours ago
- 2 days 17 hours ago
- 2 days 17 hours ago
- 4 days 5 hours ago
- 4 days 6 hours ago