c#asp.net mvc MSAL AcquireTokenSilentAsync在45分钟后失败

时间:2019-03-06 18:16:31

标签: .net oauth-2.0 azure-active-directory microsoft-graph msal

我在Web应用程序中使用OAuth和O365单点登录。当应用程序启动时,提示用户使用SSO登录。获取令牌有效,并且登录成功。用户登录后,他们将使用图客户端与Graph进行交互,该图客户端将建立一个ConfidentialClientApplication并访问会话令牌存储。那也很好。但是在45分钟到一个小时后,该客户端呼叫失败。令牌存储中有一个对象,但是当CCA调用GetAccountsAsync()时,它始终返回0,因此AcquireTokenSilentAsync失败。我是否未能在令牌存储中存储一些相关信息?我在这里做错什么以及如何解决?我尝试重新发出挑战,然后再次访问令牌存储,但是结果是一样的:尽管存储中有对象,但GetAccountsAsync返回0个帐户。

我想知道这是否与我一直基于的TokenStore示例有关。我曾尝试将令牌存储在Session和Cache中,并且它们都在用户首次通过身份验证时起作用,但是似乎在某些时候发生了使令牌在后续请求中失效的情况。

从Startup.Auth.cs:

 public void ConfigureAuth(IAppBuilder app)
    {
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions() { CookieSecure = CookieSecureOption.Never, CookieName = "AppCookie", ExpireTimeSpan = TimeSpan.FromDays(7) });

        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                ClientId = clientId,
                Authority = authority,
                PostLogoutRedirectUri = postLogoutRedirectUri,
                ResponseType = OpenIdConnectResponseType.CodeIdToken,
                TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                {
                    ValidateIssuer = false,
                    RoleClaimType = "roles",
                    NameClaimType = "upn"
                },
                UseTokenLifetime = true,
                RedirectUri = postLogoutRedirectUri,
                Scope = "openid profile offline_access " + graphScopes,

                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    RedirectToIdentityProvider = (context) =>
                    {

                        string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;
                        context.ProtocolMessage.RedirectUri = appBaseUrl;
                        context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl;
                        return Task.FromResult(0);
                    },

                    AuthorizationCodeReceived = OnAuthorization,
                    AuthenticationFailed = OnAuthenticationFailed
                }
            });
    }

    private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
    {
        context.OwinContext.Response.Redirect("/Home/Error?message=" + context.Exception.Message);
        return Task.FromResult(0);
    }

    private async Task OnAuthorization(AuthorizationCodeReceivedNotification context)
    {
        var code = context.Code;
        string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;

        SessionTokenStore tokenStore = new SessionTokenStore(signedInUserID, context.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase);
        ConfidentialClientApplication cca = new ConfidentialClientApplication(clientId, postLogoutRedirectUri, new ClientCredential(appKey), tokenStore.GetMsalCacheInstance(), null);

        var accounts = await cca.GetAccountsAsync();

        try
        {
            AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, graphScopes.Split(' '));
        }
        catch (MsalException ex)
        {
            string message = "AcquireTokenByAuthorizationCodeAsync threw an exception";
            context.HandleResponse();
            context.Response.Redirect($"/Home/Error?message={message}&debug={ex.Message}");
        }
        catch (Microsoft.Graph.ServiceException ex)
        {
            string message = "GetUserDetailsAsync threw an exception";
            context.HandleResponse();
            context.Response.Redirect($"/Home/Error?message={message}&debug={ex.Message}");
        }
        catch (Exception ex)
        {

            throw ex;
        }
    }

获取Graph客户端:

 private static GraphServiceClient GetAuthenticatedClient()
    {
        try
        {
            return new GraphServiceClient(
        new DelegateAuthenticationProvider(
            async (requestMessage) =>
            {
                string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
                SessionTokenStore tokenStore = new SessionTokenStore(signedInUserID, new HttpContextWrapper(HttpContext.Current));

                ConfidentialClientApplication cca = new ConfidentialClientApplication(appId, redirectUri.ToString(), new ClientCredential(appSecret), tokenStore.GetMsalCacheInstance(), null);

                var accounts = await cca.GetAccountsAsync();

                try
                {
                    var result = await cca.AcquireTokenSilentAsync(graphScopes.Split(' '), accounts.FirstOrDefault(), null, true);
                    requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
                }
                catch (MsalUiRequiredException ex)
                {

                    if (ex.ErrorCode == MsalUiRequiredException.UserNullError)
                    {
                        new HttpContextWrapper(HttpContext.Current).GetOwinContext().Authentication.Challenge(
                            new AuthenticationProperties { RedirectUri = redirectUri }, OpenIdConnectAuthenticationDefaults.AuthenticationType);

                        var account = await cca.GetAccountAsync(signedInUserID);

                        var result = await cca.AcquireTokenSilentAsync(graphScopes.Split(' '), account, null, true);
                        requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
                    }
                    else
                    {
                        throw ex;
                    }
                }
            }));
        }
        catch (Exception e)
        {

            throw e;
        }
    }

0 个答案:

没有答案