ADAL 3 didn’t return refresh tokens for ~5 months… and nobody noticed

JohnOliver1150070

As you know, ADAL is not meant to be a protocol library. You tell us about your client app and the resource you want to access; we get the proper tokens for you from Azure AD, via few simple primitives and without burdening with nitty-gritty protocol details.

That said… that arrangement is not 100% air tight. We do occasionally leak the abstraction: for example, we use OAuth specific terminology here and there (redirect uri…); we accept protocol parameters in extraqueryparameters; and so on. When we do so, we like to think it’s never an oversight, but a deliberate decision. We usually weigh whether the convenience of providing access to lower level constructs outperforms the complexity we’d burden you with for preserving a façade… if the convenience comes out a winner, we go for it: after all ADAL is not a science experiment, it’s something meant to make your life easier.

The refresh token in the AuthenticationResults , and corresponding AcquireTokenByRefreshToken method, is one such violation. You don’t really ever need to use the refresh token from your own app code, given that ADAL caches and will automagically use it whenever you call AcquireToken and the requested token need renewing. Ssee this and this for details. In ADAL v1 that wasn’t strictly true, given that the cache was specialized for native clients and not really suited for server side use: we had to provide you with the refresh token bits – so that you could do your own arrangements on web sites code-behind or any scenario other that the supported native client case. In ADAL v2 we improved the caching infrastructure to support server side scenarios, extending ADAL’s automatic and transparent use of the refresh token to all the mid tier flows (or, if you want me to leak protocol details… for all confidential client grants). However we weren’t completely certain that this would have addressed ALL possible scenarios, so we decided to keep exposing the refresh token in our object model.

That’s when we started noticing odd things. Developers with little or no protocol knowledge, the vast majority, happily relied on ADAL to do all the session management on their behalf and blissfully enjoyed all the automatic refresh token usage I described. So did all the people who used our GitHub samples or the VS templates as starting point for their own apps. However some developers, typically the ones with some existing protocol knowledge, skipped the samples altogether and attempted to use the library only “by intellisense”: knowing that OAuth2 does use refresh tokens, assuming that ADAL uses OAuth2 and finding methods accepting refresh tokens made them conclude that responsibility of storing and using refresh tokens was on their app code. That led to tons of extra work, code structure far more complicated than necessary, security issues and reduced functionality – for example, not all of those devs knew what a MRRT is.

Thankfully the number of the developers falling in that trap was very small in comparison to the total ADAL usage, but that made us think – do we really need to keep returning the refresh token and accept it in AcquireToken? We combed through mail threads, forum posts and customer docs searching for scenarios that could not be addressed by ADAL’s automatic usage of the refresh token – and found none. On April the 22nd we built a NuGet for ADAL v3.x with all signs of refresh tokens removed from ADAL’s programming surface, then pushed it out on NuGet.org.

Five months later, things seem to be going still pretty well. It is not entirely true that absolutely nobody noticed – but the couple of people who did, turned out to be perfectly well served by ADAL’s automatic use of cached refresh tokens.

Per the above, at this point we are reasonably confident that we can ship ADAL 3.x without leaking refresh tokens – and that’s good, because the moment of shipping is getting closer and closer (nope, I can’t share the exact date yet – sorry!).

That said, it is always possible that we missed some important scenario. That’s where YOU come into play. If you are using ADAL v2 and you are relying directly on refresh tokens bits anywhere in your code, please get in touch with us – we would like to understand whether this means we need to bring refresh tokens back after all, and if there is a way of achieving the functionality we need using ADAL cache… we would love the opportunity to show you how.

Thanks in advance for all your feedback, and happy coding!

6 Comments

  1. Yes, we do need refresh token. Please fix this issue.

    We are using Native Client flow on a client side (which is non .NET and will receive Access\Refresh and expiration date after an API call) and Bearer token middleware to protect our API and user holds access and refresh tokens and will maintain it’s validity by periodically sending Refresh token to us to update Access token. We can’t use ADAL on client, we can’t invest time to write distributed cache for ADAL on server and we really want to stick to our current scenario – it solves certain problems and works universally for providing API, web app and native app auth flows.

    See more details in my email (subj: ADAL 3.0 and refresh tokens concern ( was Re: Auth customization) )

  2. Hi Vittorio,

    one of the possible usages of RT is to implement SSO on native apps. Given the fact that it is resource-agnostic, it can be securely stored in the client (f.e. KeyChain in iOS or PasswordVault in WP) and grabbed by individual apps to silently authenticate the user.

    The scenario is described in this blog post
    http://blog.kloud.com.au/2014/12/02/implementing-azure-active-directory-sso-single-sign-on-in-xamarin-ios-apps/

    I’m pretty sure this something that ADAL might already address out-of-the-box, but I’m struggling to find a proper example.

    Any useful link?

    Thank you,
    Marco

      1. Hi Vittorio, thanks for your response.

        Just to clarify: are you saying that ADAL v3 automatically stores the RT in a shared repository among the apps and reuses it for SSO?

        So.. I authenticate with App A against mytenant.com, and when I open App B I’m already signed in because ADAL v3 does all the job for me, grabbing the RT and using it for App B as well?

        If so, well… it’s amazing, can’t wait to try it 🙂

        Thanks,
        m.

    1. Well, not necessarily among apps. ADAL will persist tokens in the keychain, hence they will be available to the same app in subsequent runs. They will be available to all apps from the same publisher too- but tokens are scoped to clientid hence they cannot be reused verbatim by multiple applications. Cross-application SSO requires more infrastructure, like a broker app – and we don’t have everything lined up for it yet. The main point of the current cache support is to save tokens for later use form the app itself in subsequent runs.

Leave a Reply

Your email address will not be published. Required fields are marked *