AcquireToken stop working after some time

Viewed 333

I am working in Xamarin forms application.

I am using below code snippet to get token for AAD sign-in.

 IEnumerable<IAccount> accounts = await App.PCA.GetAccountsAsync().ConfigureAwait(false);
            try
            {
                if (btnSignInSignOut.Text == "Sign in")
                {
                    try
                    {
                        IAccount firstAccount = accounts.FirstOrDefault();
                        authResult = await App.PCA.AcquireTokenSilent(App.Scopes, firstAccount)
                                              .ExecuteAsync()
                                              .ConfigureAwait(false);
                    }
                    catch (MsalUiRequiredException)
                    {
                        try
                        { 
                            var builder = App.PCA.AcquireTokenInteractive(App.Scopes)
                                                                       .WithParentActivityOrWindow(App.ParentWindow);

                            if (Device.RuntimePlatform != "UWP")
                            {
                                // on Android and iOS, prefer to use the system browser, which does not exist on UWP
                                SystemWebViewOptions systemWebViewOptions = new SystemWebViewOptions()
                                {                            
                                    iOSHidePrivacyPrompt = true,
                                };

                                builder.WithSystemWebViewOptions(systemWebViewOptions);
                                builder.WithUseEmbeddedWebView(false);
                            }

                            authResult = await builder.ExecuteAsync().ConfigureAwait(false);
                        }
                        catch (Exception ex2)
                        {
                            await DisplayAlert("Acquire token interactive failed. See exception message for details: ", ex2.Message, "Dismiss");
                        }
                    }

                    if (authResult != null)
                    {
                        var content = await GetHttpContentWithTokenAsync(authResult.AccessToken);
                        UpdateUserContent(content);
                    }
                }
                else
                {
                    while (accounts.Any())
                    {
                        await App.PCA.RemoveAsync(accounts.FirstOrDefault()).ConfigureAwait(false);
                        accounts = await App.PCA.GetAccountsAsync().ConfigureAwait(false);
                    }

                    
                    Device.BeginInvokeOnMainThread(() => 
                    {
                        slUser.IsVisible = false;
                        btnSignInSignOut.Text = "Sign in"; 
                    });
                }
            }
            catch (Exception ex)
            {
                await DisplayAlert("Authentication failed. See exception message for details: ", ex.Message, "Dismiss");
            }

But after some time, token expires somehow and not refresh. Due to that it always redirect user to MS login page.

My requirement is, It should automatically take the logged in user's details.

You can take reference from this code.

I have also check other options like to directly call api to get refresh token but didn't found anything helpful.

Let me know if anyone have any idea about it.

Thanks in Advance.

2 Answers

Just for clarification, MSAL does not return, issue the token, and does not expire the token. When your token expireS then MSAL will automatically refresh your token when calling the AcquireTokenSilentAsync (so you don't have to refresh your token). The reason why your application is redirecting to the login page is because when you call the authenticated API then this API is returning the response 401 (Unauthorized) which means while calling the API you are not sending the token with the request. In return when the server returns 401 (Unauthorized) response, then your application is redirecting the user to the login page.

Read more about MSAL token expiration here.

Update your code accordingly:

await SecureStorage.SetAsync("accessToken", authResult.AccessToken);

For now, MSAL already caches your authorization and can log you in silently if it’s still valid. So, as a user, you don’t need to sign in every time you use the app.

You could use SecureStorage.SetAsync to store the access token.

Sign-in:

public async Task<bool> SignInAsync()
{
 try
 {
     var accounts = await _pca.GetAccountsAsync();
    var firstAccount = accounts.FirstOrDefault();
    var authResult = await _pca.AcquireTokenSilent(Scopes, firstAccount).ExecuteAsync();

    // Store the access token securely for later use.
    await SecureStorage.SetAsync("AccessToken", authResult?.AccessToken);

    return true;
 }
 catch (MsalUiRequiredException)
 {
    try
    {
        // This means we need to login again through the MSAL window.
        var authResult = await _pca.AcquireTokenInteractive(Scopes)
                                    .WithParentActivityOrWindow(ParentWindow)
                                    .ExecuteAsync();

        // Store the access token securely for later use.
        await SecureStorage.SetAsync("AccessToken", authResult?.AccessToken);

        return true;
    }
    catch (Exception ex2)
    {
        Debug.WriteLine(ex2.ToString());
        return false;
    }
 }
 catch (Exception ex)
 {
    Debug.WriteLine(ex.ToString());
    return false;
 }
 }
Related