This blog post is the third in a series that cover Azure Active Directory Single Sign-On (SSO) authentication in native mobile applications.

  1. Authenticating iOS app users with Azure Active Directory
  2. How to Best handle AAD access tokens in native mobile apps
  3. Using Azure SSO tokens for Multiple AAD Resources From Native Mobile Apps (this post)
  4. Sharing Azure SSO access tokens across multiple native mobile apps.

Introduction

In an enterprise context it is highly likely there are multiple web services that your native mobile app needs to consume. I had exactly this scenario at one of my clients who asked if they could maintain the same SSO token in the background in the mobile app and use it for accessing multiple web services. I spent some time digging through the documentation and conducting some experiments to confirm some points and this post is to share my findings.

Cannot Share Azure AD Tokens for Multiple Resources

The first thing that comes to mind is to use the same access token for multiple Azure AD resources. Unfortunately this is not allowed. Azure AD issues a token for a certain resource (which is mapped to an Azure AD app). When we call AcquireToken, we need to provide a single resourceID. The result is the token can only be used for resource matching the supplied identifier.

There are ways where you could use the same token (as we will see later in this post), but it is not recommended as it complicates operations logging, authentication process tracing, etc. Therefore it is better to look at the other options provided by Azure and the ADAL library.

Use Refresh-Token to Acquire Tokens for Multiple Resources

The ADAL library supports acquiring multiple access tokens for multiple resources using a “refresh token”. This means once a user is authenticated, the ADAL’s authentication context is able to generate an access token to multiple resources without authenticating the user again. This is covered briefly by the MSDN documentation. A sample implementation to retrieve this token is shown below.

[code language=”csharp” gutter=”false”]
public async Task<string> RefreshTokens()
{
var tokenEntry = await tokensRepository.GetTokens();
var authorizationParameters = new AuthorizationParameters (_controller);

var result = "Refreshed an existing Token";
bool hasARefreshToken = true;

if (tokenEntry == null)
{
var localAuthResult = await _authContext.AcquireTokenAsync (
resourceId1,
clientId,
new Uri (redirectUrl),
authorizationParameters,
UserIdentifier.AnyUser,
null);

tokenEntry = new Tokens {
WebApi1AccessToken = localAuthResult.AccessToken,
RefreshToken = localAuthResult.RefreshToken,
Email = localAuthResult.UserInfo.DisplayableId,
ExpiresOn = localAuthResult.ExpiresOn
};
hasARefreshToken = false;
result = "Acquired a new Token";
}

var refreshAuthResult = await _authContext.AcquireTokenByRefreshTokenAsync(
tokenEntry.RefreshToken,
clientId,
resourceId2);

tokenEntry.WebApi2AccessToken = refreshAuthResult.AccessToken;
tokenEntry.RefreshToken = refreshAuthResult.RefreshToken;
tokenEntry.ExpiresOn = refreshAuthResult.ExpiresOn;

if (hasARefreshToken)
{
// this will only be called when we try refreshing the tokens (not when we are acquiring new tokens.
refreshAuthResult = await _authContext.AcquireTokenByRefreshTokenAsync (
refreshAuthResult.RefreshToken,
clientId,
resourceId1);

tokenEntry.WebApi1AccessToken = refreshAuthResult.AccessToken;
tokenEntry.RefreshToken = refreshAuthResult.RefreshToken;
tokenEntry.ExpiresOn = refreshAuthResult.ExpiresOn;
}

await tokensRepository.InsertOrUpdateAsync (tokenEntry);

return result;
}
[/code]

As you can see from above, we check if we have an access token from previous calls, and if we do, we refresh the access tokens for both web services. Notice how the _authContext.AcquireTokenByRefreshTokenAsync() method provides an overloading parameter that takes a resourceId. This enables us to get multiple access tokens for multiple resources without having to re-authenticate the user. The rest of the code is similar to what we have seen in the previous two posts.

ADAL Library Can Produce New Tokens For Other Resources

In the previous two posts we looked at ADAL and how it uses the TokenCache. Although ADAL does not support persistent caching of tokens yet on mobile apps, it still uses the TokenCache for in-memory caching. This enables ADAL to generate new access tokens if the AuthenticationContext still exists from previous authentication calls. Remember in the previous post we said it is recommended to keep a reference to the authentication-context? Here it comes in handy as it enables us to generate new access tokens for accessing multiple Azure AD resources.

[code language=”csharp” gutter=”false”]
var localAuthResult = await _authContext.AcquireTokenAsync (
resourceId2,
clientId,
new Uri(redirectUrl),
authorizationParameters,
UserIdentifier.AnyUser,
null
);
[/code]

Calling AcquireToken() (even with no refresh token) would give us a new access token to the requested resource. This is due to ADAL checking if we have a refresh token in-memory which ADAL then uses that to generate a new access token for the resource.

An alternative

The third alternative is the simplest (but not necessarily the best). In this option, we can use the same access token to consume multiple Azure AD resources. To do this, we need to use the same Azure AD app ID when setting the two APIs for authentication via Azure AD. This requires some understanding of how the Azure AD authentication happens on our web apps.

If you refer to Taiseer Joudeh’s tutorial you will see that in our web app, we need to tell the authentication framework what our Authority is and the Audience (Azure AD App Id). If we set up both of our web APIs to use the same Audience (Azure AD app Id) we link them both into the same Azure AD application which allows use of the same access token to use both web APIs.

[code language=”csharp” gutter=”false”]
// linking our web app authentication to an Azure AD application
private void ConfigureAuth(IAppBuilder app)
{
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = ConfigurationManager.AppSettings["Audience"],
Tenant = ConfigurationManager.AppSettings["Tenant"]
});
}
[/code]

[code language=”xml” gutter=”false”]
<appSettings>
<add key="Tenant" value="hasaltaiargmail.onmicrosoft.com" />
<add key="Audience" value="http://my-Azure-AD-Application-Id" />
</appSettings>
[/code]

As I said before, this is very simple and requires less code, but could cause complications in terms of security logging and maintenance. At the end of the day, it depends on your context and what you are trying to achieve.

Conclusion

We looked at how we could use Azure AD SSO with ADAL to access multiple resources from native mobile apps. As we saw, there are three main options, and the choice could be made based on the context of your app. I hope you find this useful and if you have any questions or you need help with some development that you are doing, then just get in touch.

This blog post is the third in a series that cover Azure Active Directory Single Sign On (SSO) Authentication in native mobile applications.

  1. Authenticating iOS app users with Azure Active Directory
  2. How to Best handle AAD access tokens in native mobile apps
  3. Using Azure SSO tokens for Multiple AAD Resources From Native Mobile Apps (this post)
  4. Sharing Azure SSO access tokens across multiple native mobile apps.
Category:
Azure Platform, Mobile, Security, Uncategorized, WebAPI
Tags:
, , , , , , , , ,

Comments are closed.