【问题标题】:How to handle new refresh token on server side?如何在服务器端处理新的刷新令牌?
【发布时间】:2019-07-01 07:47:16
【问题描述】:

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

我尝试修改身份声明,但不起作用。我试图在我自己的 cookie 中存储访问令牌和刷新令牌,但我遇到了麻烦,因为当我刷新令牌时,我只能在下一个请求时使用它们(我没有实现仅修改 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 核心身份验证存储(或替换实际访问令牌)的好做法是什么。我确定我的做法不对。最后,我想正确处理我的令牌和刷新令牌,以便不要求用户再次登录。现在使用我的解决方案,我的项目将在需要刷新令牌时拒绝访问,并且将授予下一个请求(因为需要从用户重新发送 cookie)。

【问题讨论】:

  • 这里的问题和我的回答可能会对你有所帮助:stackoverflow.com/questions/54498454/…
  • 非常感谢。它工作正常!
  • 你是对的。我会这样做的!
  • 请不要在问题中插入您的答案 - 这就是答案部分的用途。
  • 对不起,当我必须发布正确答案时,我不知道如何处理。感谢您的编辑。

标签: c# model-view-controller identityserver4


【解决方案1】:

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

// 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);

【讨论】:

    猜你喜欢
    • 2012-04-18
    • 2019-04-21
    • 2016-09-16
    • 1970-01-01
    • 2016-03-22
    • 2014-08-01
    • 1970-01-01
    • 2022-11-09
    • 2018-10-17
    相关资源
    最近更新 更多