Add code to enable SSO
Ensure that you register your app with Microsoft Entra ID before you add code to enable SSO.
You need to configure your tab app's client-side code to obtain an access token from Microsoft Entra ID. The access token is issued on behalf of the tab app. If your tab app requires additional Microsoft Graph permissions, you need to pass the access token to the server-side, and exchange it for Microsoft Graph token.
This section covers:
Add client-side code
To obtain app access for the current app user, your client-side code must make a call to Teams for getting an access token. You need to update client-side code for using getAuthToken()
to initiate the validation process.
Learn more about getAuthToken()
getAuthToken()
is a method in Microsoft Teams JavaScript library. It requests a Microsoft Entra access token to be issued on behalf of app. The token is acquired from the cache, if it isn't expired. If it expires, a request is sent to Microsoft Entra ID to obtain a new access token.
For more information, see getAuthToken.
When to call getAuthToken
Use getAuthToken()
at the time when you need access token for the current app user:
If access token is needed... | Call getAuthToken()... |
---|---|
When app user accesses the app | After microsoftTeams.app.initialize() . |
To use a particular functionality of the app | When the app user takes an action that requires signing in. |
Add code for getAuthToken
Add JavaScript code snippet to the tab app to:
- Call
getAuthToken()
. - Parse the access token or pass it to the server-side code.
The following code snippet shows an example of calling getAuthToken()
.
microsoftTeams.app.initialize().then(() => {
getClientSideToken()
.then((clientSideToken) => {
return getServerSideToken(clientSideToken);
})
.then((profile) => {
return useServerSideToken(profile);
})
.catch((error) => {
...
})
}
function getClientSideToken() {
return new Promise((resolve, reject) => {
display("1. Get auth token from Microsoft Teams");
microsoftTeams.authentication.getAuthToken().then((result) => {
display(result);
resolve(result);
}).catch((error) => {
reject("Error getting token: " + error);
});
});
}
You can add calls of getAuthToken()
to all functions and handlers that initiate an action where the token is needed.
When Teams receives the access token, it's cached and reused as needed. This token can be used whenever getAuthToken()
is called, until it expires, without making another call to Microsoft Entra ID.
Important
As a best practice for security of access token:
- Always call
getAuthToken()
only when you need an access token. - Teams automatically caches the access token, so there's no need to cache or store it within your app's code.
Consent dialog for getting access token
When you call getAuthToken()
and app user's consent is required for user-level permissions, a Microsoft Entra dialog is shown to the app user who's signed in.
The consent dialog that appears is for open-id scopes defined in Microsoft Entra ID. The app user must give consent only once. The app user can access and use your tab app for the granted permissions and scopes after consenting.
Important
Scenarios where consent dialogs are not needed:
- If the tenant administrator has granted consent on behalf of the tenant, app users don't need to be prompted for consent at all. This means that the app users don't see the consent dialogs, and can access the app seamlessly.
- If your Microsoft Entra app is registered in the same tenant from which you're requesting an authentication in Teams, the app user can't be asked to consent, and is granted an access token right away. App users consent to these permissions only if the Microsoft Entra app is registered in a different tenant.
If you encounter any errors, see Troubleshooting SSO authentication in Teams.
Use the access token as an identity token
The token returned to the tab app is both an access token and an ID token. The tab app can use the token as an access token to make authenticated HTTPS requests to APIs on the server-side.
The access token returned from getAuthToken()
can be used to establish the app user's identity using the following claims in the token:
name
: The app user's display name.preferred_username
: The app user's email address.oid
: A GUID representing the ID of the app user.tid
: A GUID representing the tenant that the app user is signing in to.
Teams can cache this information associated with the app user's identity, such as the user's preferences.
Note
If you need to construct a unique ID to represent the app user in your system, see Using claims to reliably identify a user.
Pass the access token to server-side code
If you need to access web APIs on your server, you need to pass the access token to your server-side code. The web APIs must decode access token to view claims for that token.
Note
If you don't receive User Principal Name (UPN) in the returned access token, add it as an optional claim in Microsoft Entra ID. For more information, see Access tokens.
The access token received in success callback of getAuthToken()
provides access (for the authenticated app user) to your web APIs. The server-side code can also parse the token for identity information, if needed.
If you need to pass the access token to get Microsoft Graph data, see Extend tab app with Microsoft Graph permissions.
Code for passing access token to server-side
The following code shows an example of passing the access token to the server-side. The token is passed in an Authorization
header when sending a request to a server-side web API. This example sends JSON data, so it uses the POST
method. The GET
is sufficient to send the access token when you're not writing to the server.
function getServerSideToken(clientSideToken) {
return new Promise((resolve, reject) => {
microsoftTeams.app.getContext().then((context) => {
fetch('/getProfileOnBehalfOf', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'tid': context.user.tenant.id,
'token': clientSideToken
}),
mode: 'cors',
cache: 'default'
})
.then((response) => {
if (response.ok) {
return response.json();
} else {
reject(response.error);
}
})
.then((responseJson) => {
if (responseJson.error) {
reject(responseJson.error);
} else {
const profile = responseJson;
resolve(profile);
}
});
});
});
}
Validate the access token
For more information on validating the access token, see validate tokens.
Example access token
The following code is a typical decoded payload of an access token:
{
aud: "2c3caa80-93f9-425e-8b85-0745f50c0d24",
iss: "https://login.microsoftonline.com/fec4f964-8bc9-4fac-b972-1c1da35adbcd/v2.0",
iat: 1521143967,
nbf: 1521143967,
exp: 1521147867,
aio: "ATQAy/8GAAAA0agfnU4DTJUlEqGLisMtBk5q6z+6DB+sgiRjB/Ni73q83y0B86yBHU/WFJnlMQJ8",
azp: "e4590ed6-62b3-5102-beff-bad2292ab01c",
azpacr: "0",
e_exp: 262800,
name: "Mila Nikolova",
oid: "6467882c-fdfd-4354-a1ed-4e13f064be25",
preferred_username: "milan@contoso.com",
scp: "access_as_user",
sub: "XkjgWjdmaZ-_xDmhgN1BMP2vL2YOfeVxfPT_o8GRWaw",
tid: "fec4f964-8bc9-4fac-b972-1c1da35adbcd",
uti: "MICAQyhrH02ov54bCtIDAA",
ver: "2.0"
}
Code samples
Sample name | Description | .NET | Node.js | Manifest |
---|---|---|---|---|
Tab SSO | Microsoft Teams sample app for tabs Microsoft Entra SSO | View | View, Teams Toolkit |
NA |
Tab, bot, and message extension (ME) SSO | This sample shows SSO for tab, bot, and ME - search, action, and link unfurling. | View | View | View |