Single sign-on demo for enterprise apps using OAuth

Deploy Status


In this demo, we will show you how to authorize a user to access resources on an enterprise app with a bot. Two types of resources are used to demonstrate the interoperability of OAuth: Microsoft Graph and GitHub API.

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.

Test out the hosted sample

How to run locally

This demo integrates with multiple services. There are multiple services you need to setup in order to host the demo.

  1. Clone the code
  2. Setup OAuth via GitHub
  3. Setup OAuth via Azure Active Directory
  4. Setup Azure Bot Services
  5. Prepare and run the code

Clone the code

To host this demo, you will need to clone the code and run locally.

  1. Clone this repository
  2. 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 GITHUB_OAUTH_REDIRECT_URI=http://localhost:3000/api/github/oauth/callback
        • Same as Azure Active Directory, this is the URL for GitHub to send its result

Setup OAuth via GitHub

If you want to authenticate on GitHub, follow the steps below.

  1. Sign into GitHub and create a new OAuth application
    1. Browse to
    2. Select “OAuth Apps”
    3. Click “New OAuth App” button
    4. Fill out “Application name” and “Homepage URL”, for example, “Web Chat SSO Sample”
      • The “Application name” and “Homepage URL” will be shown to the user when they authorize your GitHub OAuth app
    5. In “Application callback URL”, enter http://localhost:3000/api/github/oauth/callback
    6. Click “Register application”
  2. Save the “Client ID” and “Client Secret” to /rest-api/.env

Setup OAuth via Azure Active Directory

If you want to authenticate on Azure Active Directory, follow the steps below.

Setup Azure Bot Services

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.

  1. Save the Microsoft App ID and password to /bot/.env
    • MICROSOFT_APP_ID=12345678-1234-5678-abcd-12345678abcd
    • MICROSOFT_APP_PASSWORD=a1b2c3d4e5f6
  2. 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.

  1. Run ngrok http -host-header=localhost:3978 3978
  2. 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 ""
    • Via Azure Portal
      • Browse to your Bot Channel Registration
      • Select “Settings”
      • In “Configuration” section, set “Messaging Endpoint” to

Prepare and run the code

  1. Under app, bot, and rest-api folder, run the following:
    1. npm install
    2. npm start
  2. Browse to http://localhost:3000/ to start the demo

Things to try out



This sample includes multiple parts:



Organization of JavaScript code

In our demo, we built an enteprise single-page app using React. Then, we use a <script> tag to embed Web Chat. This is for separating the code so developers reading this sample can study the changes and easily understand the interactions between them.

You are not required to code your web app in React or use Web Chat via <script> tag. In fact, you can write both your web app and embed Web Chat using either pure JavaScript or React.

Wiring up components

Since the demo is running in a heterogeneous environment (both React and pure JavaScript), additional wire-ups are required. We use DOM events to wire up the enterprise app (authentication UI) and Web Chat.

In your production system, since you are probably in a homogenous environment (either React or pure JavaScript), you may want to use Redux or other mechanisms to wire up different UI components.

This demo is coded in heterogeneous environment. Web Chat code is written in pure JavaScript, and the website is written in React. This makes the Web Chat integration code easier to extract from the webpage code.

Content of the .env files

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.





OAuth provider support single redirect URI only

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

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.

Frequently asked questions

How can I reset my authorization?

After having signed in on this app, click the profile photo on the upper-right hand corner, select “Review access on” or “Review access on GitHub”. Then, you will be redirected to the OAuth provider page to remove your authorization.

Further reading

OAuth access token vs. refresh token

To make this demo simpler to understand, instead of refresh token, we are obtaining the access token via Authorization Code Grant flow. Access token is short-lived and considered secure to live inside the browser.

In your production scenario, you may want to obtain the refresh token with “Authorization Code Grant” flow instead of using the access token. We did not use the refresh token in this sample as it requires server-to-server communications and secured persistent storage, it would greatly increase the complexity of this demo.

Threat model

To reduce complexity, this sample is limited in scope. In your production system, you should consider enhancing it and review its threat model.

Mixed conversations

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.