c# - 如何在服务器端处理新的刷新 token ?

标签 c# model-view-controller identityserver4

我有两个项目。一个是处理用户和身份验证的身份服务器 4。第二个需要使用第一个登录并请求 token 以访问 API。 当我需要刷新 token 时,我现在不知道如何处理新的访问 token 。如何将新 token 设置为 authentification asp dot net core。所有刷新过程都在 AuthorizationHandler 上进行。

我试图修改身份声明,但没有成功。我试图在我自己的 cookie 中存储访问 token 和刷新 token ,但我遇到了麻烦,因为当我刷新 token 时,我只能在下一个请求中使用它们(我没有实现仅修改 request.cookies 和 response.cookies。

public static async Task SetToken(TokenKind token,string value, HttpContext context)
{
    context.Response.Cookies.Append(GetTokenCookieName(token), value);
}


public static async Task<string> GetRefreshTokenAsync(HttpContext context)
{
    return await SearchToken(TokenKind.Refresh,context);
}


private static async Task<string> SearchToken(TokenKind token, HttpContext context)
{
    var tokenName = GetTokenName(token);
    var test = context.Request.Cookies;
    var apiToken = context.Request.Cookies.FirstOrDefault(x => x.Key == GetTokenCookieName(token)).Value;
    if (apiToken == null)
    {
        // Save token into cookie
        var tokenValue  = await context.GetTokenAsync(GetTokenName(TokenKind.Access));
        await SetToken(TokenKind.Access, tokenValue, context);

        var refreshTokenValue = await context.GetTokenAsync(GetTokenName(TokenKind.Refresh));
        await SetToken(TokenKind.Refresh, refreshTokenValue, context);

        switch (token)
        {
            case TokenKind.Access:
                return tokenValue;
            case TokenKind.Refresh:
                return refreshTokenValue;
            default:
                return null;
                break;
        }
    }
    else
    {
        return apiToken;
    }
}


private async Task<bool> RefreshToken(AuthorizationFilterContext mvcContext, HttpClient client)
{
    var refreshToken = await TokenUtils.GetRefreshTokenAsync(mvcContext.HttpContext);
    //await mvcContext.HttpContext.GetTokenAsync("refresh_token");

    var variables = new Dictionary<string, string>
            {
                { "grant_type", "refresh_token" },
                { "client_id", _configuration["ApplicationOptions:ClientId"] },
                { "client_secret", _configuration["ApplicationOptions:ClientSecret"] },
                { "refresh_token", refreshToken }
            };
    var content = new FormUrlEncodedContent(variables);

    var url = _configuration["ApplicationOptions:AuthorizeServer"] + "/connect/token";
    var response = await client.PostAsync(url, content);

    if (response.IsSuccessStatusCode == false)
    {
        var errorString = await response.Content.ReadAsStringAsync();
        var errorData = JsonConvert.DeserializeObject<dynamic>(errorString);
        return false;
    }

    var contentAsString = await response.Content.ReadAsStringAsync();
    var responseData = JsonConvert.DeserializeObject<dynamic>(contentAsString);
    var newAccessToken = (string)responseData.access_token;
    var newRefreshToken = (string)responseData.refresh_token;

    await TokenUtils.SetAccessToken(newAccessToken, mvcContext.HttpContext);
    await TokenUtils.SetRefreshToken(newRefreshToken, mvcContext.HttpContext);

    var result = await mvcContext.HttpContext.AuthenticateAsync();
    if (result.Succeeded)
    {
        result.Properties.StoreTokens(new List<AuthenticationToken>
                {
                    new AuthenticationToken
                    {
                        Name = OpenIdConnectParameterNames.AccessToken,
                        Value = newAccessToken
                    },
                    new AuthenticationToken
                    {
                        Name = OpenIdConnectParameterNames.RefreshToken,
                        Value = newRefreshToken
                    }
                });
        return true;
    }
    else
    {
        return false;
    }
}

我想知道用 .net 核心身份验证存储(或替换实际访问 token )的好习惯是什么。我确定我没有以正确的方式做这件事。最后我想正确处理我的 token 和我的刷新 token 不要求用户再次登录。现在使用我的解决方案,我的项目将在需要刷新 token 时拒绝访问,并且将授予下一个请求(因为需要从用户重新发送 cookie)。

最佳答案

感谢 Ruard van Elburg 我找到了解决方案(这里是 complete answer) 这就是我用来替换我的 token 的东西:

// Save the information in the cookie
var info = await mvcContext.HttpContext.AuthenticateAsync("Cookies");

info.Properties.UpdateTokenValue("refresh_token", newRefreshToken);
info.Properties.UpdateTokenValue("access_token", newAccessToken);
info.Properties.UpdateTokenValue("expires_at", expiresAt.ToString("o", CultureInfo.InvariantCulture));

await mvcContext.HttpContext.SignInAsync("Cookies", info.Principal, info.Properties);

关于c# - 如何在服务器端处理新的刷新 token ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54569182/

相关文章:

c# - 为有问题的进程创建转储文件的最简单方法

c# - 不需要删除线程对象吗?

c# - 如何在MVC中写入文本文件

c# - conditional-middleware-in-aspnet-core 在 asp.net core 1.1 中不工作

asp.net-mvc-5 - ASP.NET MVC 4.5.2 连接到 IdentityServer4

c# - 为什么 ASP.NET Core 不能并行处理我的请求?

c# - 为什么我的复选框没有将它们的值传递给 ASP.NET Core 中的 Controller ?

c# - 找不到引用的组件 'EntityFramework'。

asp.net - Microsoft 终止支持后使用 .NET Framework 4.5 的后果是什么

c# - 授权回调端点不断重定向到用户交互登录页面 IdentityServer