2017-09-05 160 views
2

運行應用程序需要使用來自OIDC的刷新令牌(keycloak)來獲取訪問資源的授權。但似乎返回的RefreshToken似乎已過期或泄漏。Keycloak刷新令牌未授權的asp.net內核

問題是我可以登錄到應用程序並調用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"]; 
    } 

回答

3

從我的理解沒有自動的方式來襯托OIDC請求令牌...... 這裏這些人有一個好裂紋在實施利用一個cookie驗證: How to handle expired access token in asp.net core using refresh token with OpenId Connect

How to store the token received in AcquireTokenAsync with Active Directory

本質上可以驗證所有請求中的令牌。您可以檢查過期的訪問令牌,並在這種情況下向keycloak發送刷新請求...將提供訪問令牌,您可以使用更新的訪問令牌和刷新令牌更新Cookie。

對於keycloak我將利用戴維斯的反應,而是指向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

我還會注意到,當設置過期時,使用的格式不正確(因爲解析器在刷新一次後不會解析它,所以我想d將令牌更新期限更改爲:

context.Properties.Items[".Token.expires_at"] = 
        DateTime.Now.AddSeconds(response.ExpiresIn).ToString("s", System.Globalization.CultureInfo.InvariantCulture);