【问题标题】:Asp.Net Refresh Token "invalid_grant" when created manually手动创建时的 Asp.Net 刷新令牌“invalid_grant”
【发布时间】:2019-12-24 00:11:48
【问题描述】:

我在 ASP.NET 中从接收 googleIdToken(GoogleAuth) 的端点生成访问令牌。访问令牌已成功生成并且工作正常,我可以使用它毫无问题地向我的 API 发出请求。当我尝试从同一个端点生成刷新令牌时,问题就出现了;我可以看到刷新令牌已添加到数据库中,但是当我尝试使用刷新令牌获取新的访问令牌时,它返回“invalid_grant”。

调试发现我的ApplicationOAuthProvider中的GrantRefreshToken方法在检索到刷新令牌后没有执行。

以下是我创建访问令牌和刷新令牌的方法:

我的端点:

        [System.Web.Http.HttpPost]
        [System.Web.Http.AllowAnonymous]
        public async Task<IHttpActionResult> GenerateEHSTokenFromGAuth(ExternalSignInRequest request){
                //gets user info from google
                var tokenInfo = await GoogleJsonWebSignature.ValidateAsync(request.TokenId);

                //Some logic to match google user to my users table.

                // Generate AuthTicket
                var oAuthIdentity = await user.GenerateUserIdentityAsync(_userManager, OAuthDefaults.AuthenticationType);
                var formData = GetRequestInfo(request);
                var ticket = await _authService.CreateAuthTicket(oAuthIdentity, formData);
                var token = _authService.CreateToken(ticket);

                var cookiesIdentity = await user.GenerateUserIdentityAsync(_userManager, CookieAuthenticationDefaults.AuthenticationType);
                AuthenticationManager.SignIn(cookiesIdentity);

                //Create refresh token
                Microsoft.Owin.Security.Infrastructure.AuthenticationTokenCreateContext context =
                    new Microsoft.Owin.Security.Infrastructure.AuthenticationTokenCreateContext(
                        HttpContext.Current.GetOwinContext(),
                        Startup.OAuthOptions.AccessTokenFormat, ticket);

                await Startup.OAuthOptions.RefreshTokenProvider.CreateAsync(context);
                var refreshToken = context.Token;

                var accessTokenExpiration = ((DateTimeOffset)ticket.Properties.ExpiresUtc).Subtract((DateTimeOffset)ticket.Properties.IssuedUtc).TotalSeconds;

                ticket.Properties.Dictionary.Add("refresh_token", refreshToken);
                ticket.Properties.Dictionary.Add("access_token", token);
                ticket.Properties.Dictionary.Add("expires_in", accessTokenExpiration.ToString());
                ticket.Properties.Dictionary.Add("token_type", "bearer");

                context.SerializeTicket();

                return Ok(ticket.Properties.Dictionary);
        } 

RefreshTokenProvider:

public async Task CreateAsync(AuthenticationTokenCreateContext context)
        {
            var username = context.Ticket.Identity.Name;
            var unit = (IUnitOfWork)DependencyResolver.Current.GetService(typeof(IUnitOfWork));
            var refreshTokenLifeTime = ConfigurationManager.AppSettings["RefreshLifetimeMinutes"];
            var aspnetRefreshTokenId = Guid.NewGuid();
            var data = await context.Request.ReadFormAsync();
            var userName = context.Ticket.Identity.Name;

            var token = new AspNetRefreshToken()
            {
                AspNetRefreshTokenId = aspnetRefreshTokenId,
                UserName = userName,
                IssuedTime = DateTime.UtcNow,
                DeviceSource = GetDeviceSource(),
                ExpiredTime = DateTime.UtcNow.AddMinutes(Convert.ToDouble(refreshTokenLifeTime))
            };

            token.ProtectedTicket = context.SerializeTicket();

            //Remove old refresh tokens
            var tokensToRemove = unit.AspNetRefreshTokenRepository.Get()
                .Where(x => (x.DeviceSource == deviceSource || x.DeviceSource == null) && x.UserName == userName || x.ExpiredTime < DateTime.UtcNow);

            foreach (var tokenToRemove in tokensToRemove)
                unit.AspNetRefreshTokenRepository.Remove(tokenToRemove.AspNetRefreshTokenId);

            unit.AspNetRefreshTokenRepository.Add(token);
            context.SetToken(aspnetRefreshTokenId.ToString());
            unit.Save();
        } 

这是当我尝试使用刷新令牌获取访问令牌时调用的方法。我可以看到令牌是从数据库中检索到的,但是在执行此方法后,执行结束并且我收到了 invalid_grant 消息。

public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
        {
            var unit = (IUnitOfWork)DependencyResolver.Current.GetService(typeof(IUnitOfWork));
            var data = await context.Request.ReadFormAsync();
            var deviceSource = data.Get("device_source");

            Guid tokenId = Guid.Empty;
            var validGuid = Guid.TryParse(context.Token, out tokenId);

            if (!validGuid)
                return;

            var token = unit.AspNetRefreshTokenRepository.Get()
                .FirstOrDefault(x => x.AspNetRefreshTokenId == tokenId && x.DeviceSource == deviceSource);

            if (token == null)
                return;

            context.DeserializeTicket(token.ProtectedTicket);
            unit.AspNetRefreshTokenRepository.Remove(new Guid(context.Token));
            unit.Save();
        } 

【问题讨论】:

    标签: asp.net owin


    【解决方案1】:

    嗯,问题是我使用错误的 TokenFomat 创建上下文。如果您需要为刷新令牌创建上下文,则需要为该上下文提供 RefreshTokenFormat。

    所以不是

    Microsoft.Owin.Security.Infrastructure.AuthenticationTokenCreateContext context =
                    new Microsoft.Owin.Security.Infrastructure.AuthenticationTokenCreateContext(
                        HttpContext.Current.GetOwinContext(),
                        Startup.OAuthOptions.AccessTokenFormat, ticket);
    

    做:

    Microsoft.Owin.Security.Infrastructure.AuthenticationTokenCreateContext context =
                    new Microsoft.Owin.Security.Infrastructure.AuthenticationTokenCreateContext(
                        HttpContext.Current.GetOwinContext(),
                        Startup.OAuthOptions.RefreshTokenFormat, ticket);
    

    这将执行 GrantRefreshToken 您在其中创建新的访问令牌。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-28
      • 1970-01-01
      • 1970-01-01
      • 2017-07-25
      • 1970-01-01
      • 1970-01-01
      • 2012-12-27
      • 2014-12-30
      相关资源
      最近更新 更多