AcquireTokenAsync not returning a new token
Asked Answered
T

1

0

My WebAPI application gets a token from a service on start-up. This token is then to be used in a shared HTTP Client to prevent port exhaustion.

When this token is about to expire, I want to get a new one and save it in my service for re-use.

In my implementation, a token is retrieved - however it has the same expiry as the original token:

    // Retrieve the token and assign to AuthenticationResult
    private async Task GetAPIToken()
    {
        AuthenticationContext authContext = new AuthenticationContext(Authority);
        var clientCredential = new ClientCredential(clientId, clientSecret);

        // Same token after multiple calls
        AuthenticationResult = await authContext.AcquireTokenAsync(resourceId, clientCredential).ConfigureAwait(false);
    }

How can I save the latest authentication token?

Tamikatamiko answered 20/7, 2021 at 16:24 Comment(9)
Out of curiosity, what's the reason for doing Task.Run(async () => await GetAPIToken()).Wait(); instead of GetAPIToken().Wait();?Septuplet
Regarding the main question, are you sure that the retrieved value is not saved to the static AuthenticationResult property, and not happening something else like the retrieved value being already expired upon arrival?Septuplet
I'm not sure if .wait() alone would run synchronously. Yep I'm sure the latest token which is retrieved is correct.. the static token's expiration is the same as when it's first retrieved, even though a new request has come in and renewed itTamikatamiko
Based on the code you've shown to us, I can see no reason why the retrieved value would not be saved to the static AuthenticationResult property. The only worrisome point is that the AuthenticationResult is not always accessed while holding the lock, so it's not accessed with volatile semantics. But I doubt that converting it to a volatile field (private static volatile AuthenticationResult AuthenticationResult;) will fix the issue. Honestly there are lots of things that I don't like in your code, but nevertheless it should work as expected.Septuplet
My preferred way to handle the expiration problem would be to do it completely asynchronously, by using something like the AsyncExpiringLazy<T> type found in this package.Septuplet
Does AuthenticationResult eventually update? Or are you saying it never updates? How do you know it doesn't? Have you traced your calls to GetAPIToken? And ... isn't valid code - can you show the rest of the method please?Bobettebobina
@TheodorZoulias You were correct, my 'latest' token being retrieved was actually a cached version of the original token. The value was being correctly assigned.Tamikatamiko
OK. So this question is probably now falling in the "Not reproducible or was caused by a typo" category. 😃Septuplet
The hint @Bobettebobina to share more of GetAPIToken made me realise the AuthContext was holding onto the token. I'll update with an answerTamikatamiko
T
3

The issue here was that AuthenticationContext authContext = new AuthenticationContext(Authority); will cache a token and retrieve it if it hasn't expired.

Disabling the cache and managing the token lifecycle myself works as a solution:

AuthenticationContext authContext = new AuthenticationContext(Authority, null);

Tamikatamiko answered 21/7, 2021 at 11:42 Comment(1)
Thank you! This was the solution for my problem. Basically we updated a package related to Azure API Authentication and for some reason the tokens began being stored, whereas they were not in the past. I had been around this issue for days but finally saw your answer here and everything is working as expected now. Don't know how updating the package changed the caching configuration but that's a whole other story.Osterhus

© 2022 - 2024 — McMap. All rights reserved.