为什么我的应用程序总是总是调用Program.PublicClientApp.AcquireTokenAsync? [英] Why does my application always end up calling Program.PublicClientApp.AcquireTokenAsync?

查看:63
本文介绍了为什么我的应用程序总是总是调用Program.PublicClientApp.AcquireTokenAsync?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的代码,用于身份验证,以便在 Outlook 中使用 Microsoft Graph :

This is my code to authenticate for using Microsoft Graph with Outlook:

public async Task AquireToken()
{
    try
    {
        if (_AuthResult == null)
        {
            _AuthResult = await Program.PublicClientApp.AcquireTokenSilentAsync(
                _scopes, Program.PublicClientApp.Users.FirstOrDefault());
        }
    }
    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
        {
            _AuthResult = await Program.PublicClientApp.AcquireTokenAsync(_scopes);
        }
        catch (MsalException msalex)
        {
            _ResultsText = $"Error Acquiring Token:{System.Environment.NewLine}{msalex}";
        }
    }
    catch (Exception ex)
    {
        _ResultsText = $"Error Acquiring Token Silently:{System.Environment.NewLine}{ex}";
    }

    if (_AuthResult != null)
    {
        _ResultsText = await GetHttpContentWithToken(_graphAPIEndpoint, _AuthResult.AccessToken);
    }
}

它基于

It is based on the samples provided by Microsoft. In the console output it says:

令牌过期:2017年4月9日14:18:06 +01:00

Token Expires: 04/09/2017 14:18:06 +01:00

该代码显示自:

$"Token Expires: {_AuthResult.ExpiresOn.ToLocalTime()}" + Environment.NewLine;

因此,这表示令牌有效期为一小时.因此,如果我再次运行实用程序,我希望它使用相同的令牌,直到需要新的令牌为止.但事实并非如此.它会始终显示提示.

Thus, this implies that the token is valid for one hour. So if I run my utility again I am expecting it to use the same token until it needs to ask for a new one. But it doesn't. It always shows the prompt.

我错过了哪一步?

根据注释中的请求,以下是来自异常的详细信息:

As per the request in the comments, this is the details from the exception:

MsalUiRequiredException:在AcquiretokenSilent API中传递了空用户.传递用户对象或调用acquireToken进行身份验证.

MsalUiRequiredException: Null user was passed in AcquiretokenSilent API. Pass in a user object or call acquireToken authenticate.

这可能有帮助

Microsoft Graph SDK-登录

我需要查看提供的答案:

I need to review the answer provided:

您需要实现令牌缓存并使用AcquireTokenSilentAsync. https://docs.microsoft.com/zh-cn/outlook/rest/dotnet-tutorial 有一个网络应用程序示例.

you need to implement a token cache and use AcquireTokenSilentAsync. https://docs.microsoft.com/en-us/outlook/rest/dotnet-tutorial has a web app example.

推荐答案

我利用了注册表.成功登录后,请保存令牌,然后在每次需要使用 GraphServiceClient 时回调该令牌.如果令牌已过期或出现错误,则可以重新调用登录过程并保存新令牌.

I made use of the registry. Save the token when you get a successful log in then call the token back each time you need to make use of the GraphServiceClient. If the token has expired or an error appears you can recall the log in process and save the new token.

 public static async Task<GraphServiceClient> GetAuthenticatedClientAsync()
    {
        GraphServiceClient graphClient = new GraphServiceClient(
            new DelegateAuthenticationProvider(
                async (requestMessage) =>
                {
                    string appID = ConfigurationManager.AppSettings["ida:AppId"];

                    PublicClientApplication PublicClientApp = new PublicClientApplication(appID);
                    string[] _scopes = new string[] { "Calendars.read", "Calendars.readwrite", "Mail.read", "User.read" };

                    AuthenticationResult authResult = null;

                    string keyName = @"Software\xxx\Security";
                    string valueName = "Status";
                    string token = "";

                    RegistryKey regKey = Registry.CurrentUser.OpenSubKey(keyName, false);
                    if (regKey != null)
                    {
                        token = (string)regKey.GetValue(valueName);
                    }

                    if (regKey == null || string.IsNullOrEmpty(token))
                    {
                        authResult = await PublicClientApp.AcquireTokenAsync(_scopes); //Opens Microsoft Login Screen
                        //code if key Not Exist
                        RegistryKey key;
                        key = Registry.CurrentUser.CreateSubKey(@"Software\xxx\Security");
                        key.OpenSubKey(@"Software\xxx\Security", true);
                        key.SetValue("Status", authResult.AccessToken);
                        key.SetValue("Expire", authResult.ExpiresOn.ToString());
                        key.Close();
                        // Append the access token to the request.
                        requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", token);
                    }
                    else
                    {
                        //code if key Exists
                        RegistryKey reg = Registry.CurrentUser.OpenSubKey(@"Software\xxx\Login", true);
                        // set value of "abc" to "efd"
                        token = (string)regKey.GetValue(valueName);
                        // Append the access token to the request.
                        requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", token);
                    }
                }));
        try
        {      
            Microsoft.Graph.User me = await graphClient.Me.Request().GetAsync();

        }
        catch(Exception e)
        {
            if (e.ToString().Contains("Access token validation failure") || e.ToString().Contains("Access token has expired"))
            {
                string keyName = @"Software\xxx\Security";
                using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true))
                {
                    if (key != null)
                    {
                        key.DeleteValue("Status");
                        key.DeleteValue("Expire");
                    }
                    else
                    {
                        MessageBox.Show("Error! Something went wrong. Please contact your administrator.", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
                await GetAuthenticatedClientAsync();
            }
        }

        return graphClient;
    }

这篇关于为什么我的应用程序总是总是调用Program.PublicClientApp.AcquireTokenAsync?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆