Building, integrating, or customizing apps and workflows within Microsoft Teams using developer tools and APIs
Hi Lienl
Thank you for reaching out to Microsoft Q&A forum
The behavior you are experiencing is related to a difference in how the Microsoft Teams mobile client handles Single Sign-On (SSO) tokens compared to the Desktop and Web clients. When your Tab application calls microsoftTeams.authentication.getAuthToken() on Desktop or Web, the returned token has an audience (aud claim) set to your application's custom API URI (e.g., api://<your-app-id>), which is the expected format for the On-Behalf-Of (OBO) token exchange flow.
The official Microsoft documentation on Teams Tab SSO describes the standard flow as:
-
getAuthToken()returns a token with audience = your app's Application ID URI - You exchange this via OBO to get a Graph token
So, the solution is you need to handle both token types in your backend. Here's the recommended approach:
1. Detect the Token Type
Decode the incoming JWT (without validation first) and inspect the **aud**claim:
import jwt from 'jsonwebtoken';
function getTokenAudience(token: string): string {
const decoded = jwt.decode(token) as { aud: string };
return decoded?.aud || '';
}
2. Branch Your Logic
async function getGraphToken(clientToken: string): Promise<string> {
const audience = getTokenAudience(clientToken);
if (audience === 'https://graph.microsoft.com') {
// Mobile: Token is already a Graph token - validate and use directly
await validateGraphToken(clientToken); // Verify signature, issuer, etc.
return clientToken;
} else {
// Desktop/Web: Perform standard OBO exchange
return await performOboExchange(clientToken);
}
}
And finally ensure your app registration includes:
"api": {
"requestedAccessTokenVersion": 2,
"oauth2PermissionScopes": [...],
"knownClientApplications": [
"Teams Desktop client ID", // Teams Desktop
"Teams Mobile client ID " // Teams Mobile
]
}
Finally, you have to validate mobile tokens properly by verifying the signature against Microsoft's public keys, confirming the issuer matches your tenant, and checking that the azp or appid claim matches your Teams application's client ID.
If the answer is helpful, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.