简体   繁体   中英

Persist sign-in Microsoft-Graph c# SDK

I'm using Microsoft Graph C#.NET SDK to access user's mail inbox. The problem is that when I do authentication the token that Microsoft sends me back is valid just for 1 hour or so and it expires so early. But it's so annoying for user to login every 1 hours just to see the outlook mail inbox. I need to make this login PERSISTENT.

Here is the code that I use:

 public static async Task Run()
            {
                string secret = "MyDamnPrivateSecret";
                PublicClientApplication clientApp = new PublicClientApplication(secret);
                GraphServiceClient graphClient = new GraphServiceClient("https://graph.microsoft.com/v1.0", new DelegateAuthenticationProvider(async (requestMessage) =>
                {
                    requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", await GetTokenAsync(clientApp));
                }));
//Processing mailbox ...
            }

    private static async Task<string> GetTokenAsync(PublicClientApplication clientApp)
        {
            if (string.IsNullOrEmpty(Properties.Settings.Default.token) || string.IsNullOrWhiteSpace(Properties.Settings.Default.token))
            {
                //need to pass scope of activity to get token  
                string[] Scopes = { "User.Read", "Mail.ReadWrite" };
            string token = null;
            AuthenticationResult authResult = await clientApp.AcquireTokenAsync(Scopes);
            token = authResult.AccessToken;
            Properties.Settings.Default.token = token;
            Properties.Settings.Default.Save();
            return token;
            }
            else
            {
                return Properties.Settings.Default.token;
            }

        }

Is there any way to make expiration time last longer? Or make a refresh token or something to persist login?

You'll need to request the offline_access scope to get a refresh token. If you're using an older version of MSAL, you'll need to implement and pass a token cache in the PublicClientApplication constructor which I think that MSAL will use to automatically refresh the access token. I think the newer version handles the tokenCache for you.

From the docs , this is the recommended call pattern: first try to call AcquireTokenSilentAsync, and if it fails with a MsalUiRequiredException, call AcquireTokenAsync.

private static async Task<string> GetTokenAsync(PublicClientApplication clientApp)
    {
        AuthenticationResult result = null;

        try
        {
            string[] scopes = { "User.Read", "Mail.ReadWrite", "offline_access" };
            // Get the token from the cache.
            result = await app.AcquireTokenSilentAsync(scopes, clientApp.Users.FirstOrDefault());
            return result.AccessToken;
        }
        catch (MsalUiRequiredException ex)
        {
            // A MsalUiRequiredException happened on AcquireTokenSilentAsync. 
            // This indicates you need to call AcquireTokenAsync to acquire a token
            System.Diagnostics.Debug.WriteLine($"MsalUiRequiredException: {ex.Message}");

            try
            {
                // Dialog opens for user.
                result = await app.AcquireTokenAsync(scopes);
                return result.AccessToken;
            }
            catch (MsalException msalex)
            {
                ResultText.Text = $"Error Acquiring Token:{System.Environment.NewLine}{msalex}";
            }
        }
        catch (Exception ex)
        {
            ResultText.Text = $"Error Acquiring Token Silently:{System.Environment.NewLine}{ex}";
            return;
        }
    }

Here's a sample for reference. https://github.com/Azure-Samples/active-directory-dotnet-desktop-msgraph-v2

In your code, AcquireTokenAsync does always trigger login.

Instead, you need to implement a token cache and use AcquireTokenSilentAsync .

For more information, please review the following link:

Microsoft Graph SDK - Login

I will try to clarify the issues here:

  1. MSAL .net is build for different platforms - .net desktop, .net core, UWP, xamarin android and xamarin iOS. On some of these platforms (UWP and xamarin) we persist the token cache for you. On the others, we expect you to persist the cache. The reason is that we cannot provide token serialization logic that works well for all scenarios (eg ASP.NET server farms), so we expect you to do it. We provide samples and guidance around it this. Details and some reference implementations on the MSAL wiki :

  2. The sample code provided by @Michael is ok for MSAL v1. In MSAL v2 the things are a bit different and you can find the pattern of calling is also on the MSAL wiki :

  3. We request and store the refresh token (RT). If the auth token (AT) is expired, we will request a new one based on the RT - this will happen without user interaction. This should all be transparent to you, ie it should just work :). Make sure that your token cache serialization works, ie you get an account when performing

// perform an interactive login first 
// otherwise there will be no AT / RT in the store
var accounts = await app.GetAccountsAsync();
// there should be an account that you can use
  1. Most of our samples show how to call the Graph. See all the samples by scenario here . For your use case I recommend you check out Calling the Graph from a WPF app

Also check out @Daniel Dobalian's answer for default expiration of AT and RT: MSAL token expires after 1 hour

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM