.Net Core 3.1 API 中的刷新令牌 Azure 广告身份验证

Posted

技术标签:

【中文标题】.Net Core 3.1 API 中的刷新令牌 Azure 广告身份验证【英文标题】:Refresh Token Azure Ad authentication in .Net Core 3.1 API 【发布时间】:2021-10-19 03:59:36 【问题描述】:

问题:- 我有一个不同的微服务,我使用了 Azure 广告身份验证。 前端使用https://login.microsoftonline.com/common/oauth2/v2.0/token 创建令牌并发送到.net core api。 问题是令牌超时时间为 1 小时,并且某些进程在后台运行,因此某些时间进程停止。 如果令牌过期,我需要在 api 端找出刷新令牌。

ConfigureServices 方法中的启动代码

services.AddAuthorization(options =>
            
                options.DefaultPolicy = new AuthorizationPolicyBuilder(
                        "Bearer")
                        .RequireAuthenticatedUser()
                        .Build();
            );

配置方法

        app.UseCustomSwagger(Configuration, provider);
        app.UseHealthChecks("/health");
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseSerilogRequestLogging();
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseApiVersioning();
        app.UseCors("CorsPolicy");

我在控制器上添加了 [Authorize] 属性。 我们还有一个用于令牌添加到声明的中间件

 public async Task InvokeAsync(HttpContext httpContext)
    
        if (httpContext.User != null && httpContext.User.Identity.IsAuthenticated)
        
            //string sPreferredUserName = httpContext.User.Claims.FirstOrDefault(x => x.Type.Equals("preferred_username", StringComparison.OrdinalIgnoreCase))?.Value;
            //if (string.IsNullOrEmpty(sPreferredUserName))
            //    ((ClaimsIdentity)httpContext.User.Identity).AddClaim(new Claim("preferred_username", httpContext.User.Identity.Name, ClaimValueTypes.String));

            ((ClaimsIdentity)httpContext.User.Identity).AddClaim(new Claim("Token", httpContext.Request.Headers["Authorization"], ClaimValueTypes.String));
            await _next(httpContext);
        
        else
        
            string result1 = "UnAuthorized";
            byte[] bytes = Encoding.ASCII.GetBytes(result1);
            await httpContext.Response.Body.WriteAsync(bytes, 0, bytes.Length);
        


    

我想要从前端检查令牌验证接收令牌和刷新令牌时,如果过期使用刷新令牌生成新令牌。 请帮忙 提前致谢

【问题讨论】:

some process running in background so some time process stop 这是否意味着您有一个需要持续使用访问令牌的长时间进程,并且每当令牌过期时,该进程就会停止?或者您的进程总是收到存储在某个地方的相同访问令牌,而您的客户端不知道令牌何时过期,因此您需要您的 api 检查令牌并让客户端知道令牌何时过期?或者是其他东西?您能否添加有关您的方案或处理进度流程的更多详细信息。 【参考方案1】:

解决方案 1:使用 System.IdentityModel.Tokens.Jwt 类。调用此方法检查token是否有效

public bool _isEmptyOrInvalid (string token)
    
        if (string.IsNullOrEmpty(token))
        
            return true;
        

        var jwtToken = new JwtSecurityToken(token);
        return (jwtToken == null) || (jwtToken.ValidFrom > DateTime.UtcNow) || (jwtToken.ValidTo < DateTime.UtcNow);
    

解决方案2:尝试从Base64格式解码令牌,您可以看到到期日期,然后您可以将其与现在的日期进行比较。

如果您想检查此方法是否有效,您可以使用this website 来解码令牌。

 public static bool isExpired(String token)
    
        if (token == null || ("").Equals(token))
        
            return true;
        

        /***
         * Make string valid for FromBase64String
         * FromBase64String cannot accept '.' characters and only accepts stringth whose length is a multitude of 4
         * If the string doesn't have the correct length trailing padding '=' characters should be added.
         */
        int indexOfFirstPoint = token.IndexOf('.') + 1;
        String toDecode = token.Substring(indexOfFirstPoint, token.LastIndexOf('.') - indexOfFirstPoint);
        while (toDecode.Length % 4 != 0)
        
            toDecode += '=';
        

        //Decode the string
        string decodedString = Encoding.ASCII.GetString(Convert.FromBase64String(toDecode));

        //Get the "exp" part of the string
        String beginning = "\"exp\":\"";
        int startPosition = decodedString.LastIndexOf(beginning) + beginning.Length;
        decodedString = decodedString.Substring(startPosition);
        int endPosition = decodedString.IndexOf("\"");
        decodedString = decodedString.Substring(0, endPosition);
        long timestamp = Convert.ToInt64(decodedString);

        DateTime date = new DateTime(1970, 1, 1).AddMilliseconds(timestamp);
        DateTime compareTo = DateTime.Now.AddMinutes(1);

        int result = DateTime.Compare(date, compareTo);

        return result < 0;
    

更多详情请参考thread

【讨论】:

以上是关于.Net Core 3.1 API 中的刷新令牌 Azure 广告身份验证的主要内容,如果未能解决你的问题,请参考以下文章

NET Core 3.1 MVC 授权/身份验证,带有在单独的 Net Core 3.1 Web Api 中从外部获取的令牌 (JWT)

使用 AspNetUserTokens 表在 ASP.NET Core Web Api 中存储刷新令牌

如何撤销存储在 Identity Server 数据库中的 asp net core 中的刷新令牌

ASP.NET Core Web Api之JWT刷新Token

在 .Net Core 中实现刷新令牌功能的最佳位置?

带有 ASP.NET Core WebAPI 的 Dart 中的令牌刷新并发问题