Skip to content


Switch branches/tags


Failed to load latest commit information.
Latest commit message
Commit time
page_type products languages title description extensions
Microsoft Teams NodeJS Helloworld - Tabs Azure AD SSO Sample
Microsoft Teams hello world sample app for tabs Azure AD SSO in Node.js
contentType createdDate
11/3/2017 12:53:17 PM

Microsoft Teams - Tabs Azure AD Single Sign-On Sample

This sample shows how to implement Azure AD single sign-on support for tabs. It will:

  1. Obtain an access token for the logged-in user using SSO

  2. Call a web service - also part of this project - to exchange this access token for one with User.Read permission

  3. Call Graph and retrieve the user's profile

Screen shot of solution


You will need:

  1. A global administrator account for an Office 365 tenant. Testing in a production tenant is not recommended! You can get a free tenant for development use by signing up for the Office 365 Developer Program.

  2. To test locally, NodeJS must be installed on your development machine.

  3. To test locally, you'll need Ngrok installed on your development machine. Make sure you've downloaded and installed Ngrok on your local machine. ngrok will tunnel requests from the Internet to your local computer and terminate the SSL connection from Teams.

NOTE: The free ngrok plan will generate a new URL every time you run it, which requires you to update your Azure AD registration, the Teams app manifest, and the project configuration. A paid account with a permanent ngrok URL is recommended.

Step 1: Register an Azure AD Application

Your tab needs to run as a registered Azure AD application in order to obtain an access token from Azure AD. In this step you'll register the app in your tenant and give Teams permission to obtain access tokens on its behalf.

  1. Create an AAD application in Azure. You can do this by visiting the "Azure AD app registration" portal in Azure.

    • Set your application URI to the same URI you've created in Ngrok.

      • Ex: api://{appId} using the application ID that was assigned to your app
    • Setup your redirect URIs. This will allow Azure AD to return authentication results to the correct URI.

      • Visit Manage > Authentication.
      • Create a redirect URI in the format of:
      • Enable Implicit Grant by selecting Access Tokens and ID Tokens.
    • Setup a client secret. You will need this when you exchange the token for more API permissions from your backend.

      • Visit Manage > Certificates & secrets
      • Create a new client secret.
    • Setup your API permissions. This is what your application is allowed to request permission to access.

      • Visit Manage > API Permissions
      • Make sure you have the following Graph permissions enabled: email, offline_access, openid, profile, and User.Read.
      • Our SSO flow will give you access to the first 4 permissions, and we will have to exchange the token server-side to get an elevated token for the profile permission (for example, if we want access to the user's profile photo).
    • Expose an API that will give the Teams desktop, web and mobile clients access to the permissions above

      • Visit Manage > Expose an API
      • Add a scope and give it a scope name of access_as_user. Your API url should look like this: api://{appID}/access_as_user. In the "who can consent" step, enable it for "Admins and users". Make sure the state is set to "enabled".
      • Next, add two client applications. This is for the Teams desktop/mobile clients and the web client.
        • 5e3ce6c0-2b1f-4285-8d4b-75ee78787346
        • 1fec8e78-bce4-4aaf-ab1b-5451cc387264

Update the app manifest and config.js file

  1. Update the manifest.json file as follows:

    • Generate a new unique ID for the application and replace the id field with this GUID. On Windows, you can generate a new GUID in PowerShell with this command:
    • Ensure the package name is unique within the tenant where you will run the app
    • Replace {ngrokSubdomain} with the subdomain you've assigned to your Ngrok account in step #1 above.
    • Update your webApplicationInfo section with your Azure AD application ID that you were assigned in step #2 above.
  2. Update your config/default.json file

    • Replace the property with you Azure AD application ID
    • Replace the tab.password property with the "client secret" you were assigned in step #2
    • If you want to use a port other than 3333, fill that in here (and in your ngrok command)

Running the app locally

  1. Run Ngrok to expose your local web server via a public URL. Make sure to point it to your Ngrok URI. For example, if you're using port 3333 locally, run:
    • Win: ./ngrok http 3333 -host-header=localhost:3333 -subdomain="contoso"
    • Mac: /ngrok http 3333 -host-header=localhost:3333 -subdomain="contoso"

Leave this running while you're running the application locally, and open another command prompt for the steps which follow.

  1. Install the neccessary NPM packages and start the app
    • npm install
    • npm start

Thhe app should start running on port 3333 or the port you configured

Packaging and installing your app to Teams

  1. Package your manifest
    • gulp generate-manifest
    • This will create a zip file in the manifest folder
  2. Install in Teams
    • Open Teams and visit the app store. Depending on the version of Teams, you may see an "App Store" button in the bottom left of Teams or you can find the app store by visiting Apps > More Apps in the left-hand app rail.
    • Install the app by clicking on the Upload a custom app link in the bottom left-hand side of the app store.
    • Upload the manifest zip file created in step #1

Trying out the app

  1. Once you've installed the app, it should automatically open for you. Visit the Auth Tab to begin testing out the authentication flow.
  2. Follow the onscreen prompts. The authentication flow will print the output to your screen.
  • The first time you run the app it should get an access token from Microsoft Teams, but it won't be able to get one from the server unless the user or an administrator consents. If this is necessary, you will see a consent button.

Screen with consent button

  • Click the consent button and a pop-up window will display the consent dialog from Azure AD.

Azure AD pop-up window

  • Once you've granted all the permissions, the page will use the access token it received to make a Graph API call.

Graph call following consent

  • Once you've granted all the permissions, you can revisit this tab and you will notice that you will automatically be logged in.

Subsequent visit to tab

  • The SSO even works on mobile devices.

SSO from a mobile device

Testing the consent process

If you need to remove all consents for the application for test purposes, simply delete its service principal in the Azure AD portal. It may take a few minutes for cached values to time out. The service principal is created automatically the first time someone consents.

Service principal

App structure


Compared to the Hello World sample, this app has four additional routes:

  1. /ssoDemo renders the tab UI.
    • This is the tab called Auth Tab in personal app inside Teams. The purpose of this page is primarily to execute the auth.js file that handles initiates the authentication flow.
    • This tab can also be added to Teams channels
  2. /auth/token does not render anything but instead is the server-side route for initiating the on-behalf-of flow.
    • It takes the token it receives from the /ssoDemo page and attemps to exchange it for a new token that has elevated permissions to access the profile Graph API (which is usually used to retrieve the users profile photo).
    • If it fails (because the user hasn't granted permission to access the profile API), it returns an error to the /ssoDemo page. This error is used to display the "Consent" button which uses the Teams SDK to open the /auth/start page in a pop-up window.
  3. /auth/start and /auth/end routes are used if the user needs to grant further permissions. This experience happens in a seperate window.
    • The /auth/start page merely creates a valid AAD authorization endpoint and redirects to that AAD consent page.
    • Once the user has consented to the permissions, AAD redirects the user back to /auth/end. This page is responsible for returning the results back to the /auth page by calling the notifySuccess API.
    • This workflow is only neccessary if you want authorization to use additional Graph APIs. Most apps will find this flow unnesseccary if all they want to do is authenticate the user.
    • This workflow is the same as our standard web-based authentication flow that we've always had in Teams before we had single sign-on support. It just so happens that it's a great way to request additional permissions from the user, so it's left in this sample as an illustration of what that flow looks like.


This Javascript file is served from the /ssoDemo page and handles most of the client-side authentication workflow. This file is broken into three main functions:

  1. getClientSideToken() - This function asks Teams for an authentication token from AAD. The token is displayed so you can try it in Postman.

  2. getServerSideToken() - This function sends the token to the backend to exchange for elevated permissions using AAD's on-behalf-of flow. In this case, it sends the token to the /auth/token route.

  3. useServerSideToken() - This function uses the token to call the Microsoft Graph and display the resulting JSON.

  4. requestConsent() - This function launches the consent pop-up

Inline code runs these in sequence, running requestConsent only if an invalid_grant error is received from the server.

Additional reading

For how to get started with Microsoft Teams development see Get started on the Microsoft Teams platform with Node.js and App Studio.

For further information on Single Sign-On and how it works, visit our Single Sign-On documentation


This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact with any additional questions or comments.