Azure BOTs – getting extra access tokens

Existing docs show how to enable use of OAuth2 in an Azure Bot application to sign-in the user and get an access token to MS Graph for the user. The following describes an approach for getting access tokens to more than one resource, without re-displaying the sign in dialog (using the V2 Azure AD endpoint). In a nutshell, the procedure uses the existing authentication dialog to acquire one token and then the OAuth2 Extension flow (on-behalf-of flow) to acquire additional access tokens with the originally acquired token. The originally acquired token must fulfill two conditions to be useful for such an exchange: it’s audience must be the bot application itself and it’s version must be the same as the version expected by all the other resource servers the bot needs access tokens for.

  1. Use the AAD portal App Registration (Preview) blade to expose a new API Scope on the bot application (already registered in AAD), e.g. ‘https://mybot/all’.
  2. Edit the manifest of your bot in AAD and make sure that the accessTokenAcceptedVersion has the same value (e.g. 2) as all the other API applications you will need tokens for (otherwise, you will get ‘ AADSTS500137: The token issuer doesn’t match the api version ‘ error when trying to do an OBO token exchange).
  3. Modify the OAuth Connection Settings in the Bot Settings blade. Instead of the MS Graph scopes used in the sample, enter the name of your bot’s scope defined above (e.g. https://mybot/all). This will mean that upon authentication your bot will have an access token for itself (the aud claim will point to the bot application) – the ‘original’ token that will be used to get tokens to other resource servers.
  4. Use the original token to acquire additional tokens using the OBO flow. The following MSAL code shows to use an token (the ‘original token’) to get another token for another resource (MS Graph with Mail.Read scope).
var client = new ConfidentialClientApplication(
    "53c0ee74-....c8ed", // bot app id
    "https://login.microsoftonline.com/tenant.onmicrosoft.com", // authority
    "https://mybot", // bot app reply url in AAD, not a resolvable url
    new ClientCredential("<app key>"), // bot app secret in AAD
    null, // user token cache
    null); // app token cache
var newTokens = await client.AcquireTokenOnBehalfOfAsync(
    new string[] { "https://graph.microsoft.com/Mail.Read" }, // scopes for the new resource server
    new UserAssertion(
        token, // the original token obtained through bot auth dialogs
        "urn:ietf:params:oauth:grant-type:jwt-bearer"));

For clarity, this code does not reference configuration settings nor does it cache the acquired tokens.

Leave a comment