ConfidentialClientApplication AcquireTokenSilentAsync始终失败

时间:2017-02-04 02:55:51

标签: c# asp.net-mvc authentication

我试图对微软权限使用OpenIdConnectAuthentication。我能够进行身份验证,但是当尝试获取访问令牌时,呼叫失败,希望我重新进行身份验证,我这样做。我好像从来没有拉过正确的代币。以下是获取访问令牌的代码。

public async Task<string> GetUserAccessTokenAsync()
{
    string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
    //string signedInUserID = User.Identity.GetUserId();
    tokenCache = new MSALSessionCache(
        signedInUserID,
        HttpContext.Current.GetOwinContext().Environment["System.Web.HttpContextBase"] as HttpContextBase);
    var cachedItems = tokenCache.ReadItems(appId); // see what's in the cache

    ConfidentialClientApplication cca = new ConfidentialClientApplication(
        appId,
        redirectUri,
        new ClientCredential(appSecret),
        tokenCache);

    try
    {
        AuthenticationResult result = await cca.AcquireTokenSilentAsync(scopes.Split(new char[] { ' ' }));
        return result.Token;
    }

    // Unable to retrieve the access token silently.
    catch (MsalSilentTokenAcquisitionException)
    {
        HttpContext.Current.Request.GetOwinContext().Authentication.Challenge(
            new AuthenticationProperties() { RedirectUri = "/" },
            OpenIdConnectAuthenticationDefaults.AuthenticationType);

        //throw new Exception("Resource.Error_AuthChallengeNeeded");
        return null;
    }
}

我不确定我错过了什么。到目前为止,我已经使用Microsoft Graph REST ASPNET Connect示例来指导我。我的最终目标是验证用户身份,然后使用其个人资料中的一些项目和MS rest api。

1 个答案:

答案 0 :(得分:0)

我能够追踪到这一点。因为我使用的是Asp.net Identity auth和UseOpenIdConnectAuthentication,所以我必须手动将外部登录声明添加到ClaimsPrincipal。这就是我的ExternalLoginCallback(string returnUrl)的样子:

        public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
    {
        var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
        if (loginInfo == null)
        {
            return RedirectToAction("Login");
        }

        // Sign in the user with this external login provider if the user already has a login
        var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);

        logger.Info(loginInfo.Email + " attempted an external login with a result of " + result.ToString());

        switch (result)
        {
            case SignInStatus.Success:                  
                foreach (Claim c in loginInfo.ExternalIdentity.Claims)
                {
                    SignInManager.AuthenticationManager.AuthenticationResponseGrant.Identity.AddClaim(new Claim(c.Type + "_external", c.Value));
                }

                var user = UserManager.FindById(SignInManager.AuthenticationManager.AuthenticationResponseGrant.Identity.GetUserId());

                user.LastLogin = DateTime.Now.ToUniversalTime();
                await UserManager.UpdateAsync(user);

                return RedirectToLocal(returnUrl);
            case SignInStatus.LockedOut:
                return View("Lockout");
            case SignInStatus.RequiresVerification:
                return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = false });
            case SignInStatus.Failure:
            default:
                // If the user does not have an account, then prompt the user to create an account
                ViewBag.ReturnUrl = returnUrl;
                ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
                return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email });
        }
    }

因为外部身份的声明名称与asp.net身份相匹配,所以我不得不重命名蛤蜊。然后还可以在代码中的任何位置进行调整,以查找外部身份声明。