Keycloak 刷新令牌未经授权 asp .net 核心
Keycloak Refresh Token Unauthorized asp .net core
运行应用程序需要来自 OIDC (keycloak) 的刷新令牌以获得访问资源的授权。但似乎返回的 RefreshToken 似乎已过期或泄漏。
问题是我能够登录到应用程序并调用 RefreshToken 并传递到我的同步网关方法,但响应始终是 401 无效。
不确定如何进一步调试。或者有什么方法可以尝试刷新 RefreshToken。
见下面的代码。 [startup.cs]
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "Cookies",
AutomaticAuthenticate = true,
ExpireTimeSpan = TimeSpan.FromMinutes(60)
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
var oidcOptions = new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = Configuration["keycloak:authority"],
RequireHttpsMetadata = bool.Parse(Configuration["keycloak:httpMetadata"]),
PostLogoutRedirectUri = Configuration["keycloak:logoutUri"],
ClientId = Configuration["keycloak:clientId"],
ClientSecret = Configuration["keycloak:clientSecret"],
ResponseType = OpenIdConnectResponseType.Code,
GetClaimsFromUserInfoEndpoint = true,
SaveTokens = true,
CallbackPath = "/signin-oidc",
};
oidcOptions.Scope.Clear();
oidcOptions.Scope.Add("openid");
app.UseOpenIdConnectAuthentication(oidcOptions);
方法调用 RefreshToken
[HttpGet("getRec/{id}")]
public async Task<object> GetFileById(string id)
{
var refreshToken = await HttpContext.Authentication.GetTokenAsync("refresh_token");
//var authenticateInfo = await HttpContext.Authentication.GetAuthenticateInfoAsync("oidc");
//var refreshToken = authenticateInfo.Properties.Items[".Token.refresh_token"];
var token = HttpContext.Authentication.GetAuthenticateInfoAsync("refresh_token");
var val = await AppBal.GetFileById(refreshToken, id);
return val.Properties["files"];
}
据我了解,没有自动方法可以通过 OIDC 触发请求令牌...
这里的这些人在使用 cookie 验证器实现方面有很好的突破:
How to store the token received in AcquireTokenAsync with Active Directory
基本上所有请求都可以验证 cookie 中的令牌。您可以检查过期的访问令牌,在这种情况下向 keycloak 发送刷新请求...将提供访问令牌,您可以使用更新的访问令牌和刷新令牌更新 cookie。
对于 keycloak,我会利用 Davids 的响应,而不是指向 Keycloak(与 Azure 相对:
public class KeycloakRefreshTokenService
{
private const string HostUrl = "http://localhost:8080/";
private const string Realm = "TestRealm";
private string TokenUrl = $"/auth/realms/{Realm}/protocol/openid-connect/token";
private const string ContentType = "application/x-www-form-urlencoded";
和
public class KeycloakTokenResponse
{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "token_type", Required = Required.Default)]
public string TokenType { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "expires_in", Required = Required.Default)]
public int ExpiresIn { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "refresh_expires_in", Required = Required.Default)]
public int RefreshExpiresIn { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "not-before-policy", Required = Required.Default)]
public string NotBeforePolicy { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "access_token", Required = Required.Default)]
public string AccessToken { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "refresh_token", Required = Required.Default)]
public string RefreshToken { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "id_token", Required = Required.Default)]
public string IdToken { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "session_state", Required = Required.Default)]
public string SessionState { get; set; }
}
否则代码应该可以正常工作(您可以查看错误响应 POCO
我还要注意设置过期的时候,使用的格式不正确(因为解析器不会在刷新一次后解析它。所以我将令牌过期的更新更改为:
context.Properties.Items[".Token.expires_at"] =
DateTime.Now.AddSeconds(response.ExpiresIn).ToString("s", System.Globalization.CultureInfo.InvariantCulture);
运行应用程序需要来自 OIDC (keycloak) 的刷新令牌以获得访问资源的授权。但似乎返回的 RefreshToken 似乎已过期或泄漏。
问题是我能够登录到应用程序并调用 RefreshToken 并传递到我的同步网关方法,但响应始终是 401 无效。
不确定如何进一步调试。或者有什么方法可以尝试刷新 RefreshToken。
见下面的代码。 [startup.cs]
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "Cookies",
AutomaticAuthenticate = true,
ExpireTimeSpan = TimeSpan.FromMinutes(60)
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
var oidcOptions = new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = Configuration["keycloak:authority"],
RequireHttpsMetadata = bool.Parse(Configuration["keycloak:httpMetadata"]),
PostLogoutRedirectUri = Configuration["keycloak:logoutUri"],
ClientId = Configuration["keycloak:clientId"],
ClientSecret = Configuration["keycloak:clientSecret"],
ResponseType = OpenIdConnectResponseType.Code,
GetClaimsFromUserInfoEndpoint = true,
SaveTokens = true,
CallbackPath = "/signin-oidc",
};
oidcOptions.Scope.Clear();
oidcOptions.Scope.Add("openid");
app.UseOpenIdConnectAuthentication(oidcOptions);
方法调用 RefreshToken
[HttpGet("getRec/{id}")]
public async Task<object> GetFileById(string id)
{
var refreshToken = await HttpContext.Authentication.GetTokenAsync("refresh_token");
//var authenticateInfo = await HttpContext.Authentication.GetAuthenticateInfoAsync("oidc");
//var refreshToken = authenticateInfo.Properties.Items[".Token.refresh_token"];
var token = HttpContext.Authentication.GetAuthenticateInfoAsync("refresh_token");
var val = await AppBal.GetFileById(refreshToken, id);
return val.Properties["files"];
}
据我了解,没有自动方法可以通过 OIDC 触发请求令牌...
这里的这些人在使用 cookie 验证器实现方面有很好的突破:
How to store the token received in AcquireTokenAsync with Active Directory
基本上所有请求都可以验证 cookie 中的令牌。您可以检查过期的访问令牌,在这种情况下向 keycloak 发送刷新请求...将提供访问令牌,您可以使用更新的访问令牌和刷新令牌更新 cookie。
对于 keycloak,我会利用 Davids 的响应,而不是指向 Keycloak(与 Azure 相对:
public class KeycloakRefreshTokenService
{
private const string HostUrl = "http://localhost:8080/";
private const string Realm = "TestRealm";
private string TokenUrl = $"/auth/realms/{Realm}/protocol/openid-connect/token";
private const string ContentType = "application/x-www-form-urlencoded";
和
public class KeycloakTokenResponse
{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "token_type", Required = Required.Default)]
public string TokenType { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "expires_in", Required = Required.Default)]
public int ExpiresIn { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "refresh_expires_in", Required = Required.Default)]
public int RefreshExpiresIn { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "not-before-policy", Required = Required.Default)]
public string NotBeforePolicy { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "access_token", Required = Required.Default)]
public string AccessToken { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "refresh_token", Required = Required.Default)]
public string RefreshToken { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "id_token", Required = Required.Default)]
public string IdToken { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "session_state", Required = Required.Default)]
public string SessionState { get; set; }
}
否则代码应该可以正常工作(您可以查看错误响应 POCO
我还要注意设置过期的时候,使用的格式不正确(因为解析器不会在刷新一次后解析它。所以我将令牌过期的更新更改为:
context.Properties.Items[".Token.expires_at"] =
DateTime.Now.AddSeconds(response.ExpiresIn).ToString("s", System.Globalization.CultureInfo.InvariantCulture);