2015-07-28 18 views
6

Kısa bir süre önce IdentityServer v3'ü çalıştırıyorum ve bir rüya gibi çalışıyorum, ancak OWIN ara katman yazılımında sorun yaşıyorum.Owin middleware ve IdentityServer v3 kullanarak tokeni yenileyin

Hibrit akışını kullanmak isterim ki, kullanıcı her 5 dakikada bir yeni erişim belirteci almak için IdentityServer'a yeniden yönlendirmek zorunda kalmadan arka uçtaki tokenleri yenileyebilirim. sunucuda 1 saat kullanım ömrü).

Aşağıdaki yapılandırmayı başlangıçta kullanıyorum ve jetonları iyi alıyorum, ancak kullanım süresi dolduğunda erişim belirtecini denemeyi ve yenilemeyi asla denemiyor. Jetonlarımı yenilemek için bir yere özel bir mantığa ihtiyacım var mı? Ben de ApiClient benim kaynak API konuşur (RestSharp) aşağıdaki kullanıyorum

 app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
     { 
      ClientId = clientId, 
      ClientSecret = clientSecret, //Not sure what this does? 

      Authority = "https://auth.example.com", 

      RedirectUri = "http://website.example.com", 
      PostLogoutRedirectUri = "http://website.example.com", 

      ResponseType = "code id_token token", 
      Scope = "openid profile email write read offline_access", 

      SignInAsAuthenticationType = "Cookies", 

      Notifications = new OpenIdConnectAuthenticationNotifications 
      { 
       AuthorizationCodeReceived = async n => 
       { 
        // filter "protocol" claims 
        var claims = new List<Claim>(from c in n.AuthenticationTicket.Identity.Claims 
               where c.Type != "iss" && 
                 c.Type != "aud" && 
                 c.Type != "nbf" && 
                 c.Type != "exp" && 
                 c.Type != "iat" && 
                 c.Type != "nonce" && 
                 c.Type != "c_hash" && 
                 c.Type != "at_hash" 
               select c); 

        // get userinfo data 
        var userInfoClient = new UserInfoClient(
         new Uri(n.Options.Authority + "/connect/userinfo"), 
         n.ProtocolMessage.AccessToken); 

        var userInfo = await userInfoClient.GetAsync(); 
        userInfo.Claims.ToList().ForEach(ui => claims.Add(new Claim(ui.Item1, ui.Item2))); 

        // get access and refresh token 
        var tokenClient = new OAuth2Client(
         new Uri(n.Options.Authority + "/connect/token"), 
         clientId, 
         clientSecret); 

        var response = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri); 

        claims.Add(new Claim("access_token", response.AccessToken)); 
        claims.Add(new Claim("expires_at", DateTime.UtcNow.AddSeconds(response.ExpiresIn).ToLocalTime().ToString(CultureInfo.InvariantCulture))); 
        claims.Add(new Claim("refresh_token", response.RefreshToken)); 
        claims.Add(new Claim("id_token", n.ProtocolMessage.IdToken)); 

        //Does this help? 
        n.AuthenticationTicket.Properties.AllowRefresh = true; 

        n.AuthenticationTicket = new AuthenticationTicket(
         new ClaimsIdentity(
          claims.Distinct(new ClaimComparer()), 
          n.AuthenticationTicket.Identity.AuthenticationType), 
         n.AuthenticationTicket.Properties); 
       }, 

       RedirectToIdentityProvider = async n => 
       { 
        // if signing out, add the id_token_hint 
        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest) 
        { 
         var id = n.OwinContext.Authentication.User.FindFirst("id_token"); 

         if (id != null) 
         { 
          var idTokenHint = id.Value; 
          n.ProtocolMessage.IdTokenHint = idTokenHint; 
         } 
        } 
       } 
      } 
     }); 

public class MyTokenAuthenticator : IAuthenticator 
{ 
    public void Authenticate(IRestClient client, IRestRequest request) 
    { 
     var tokenClaim = ClaimsPrincipal.Current.Claims.FirstOrDefault(c => c.Type.Equals("access_token")); 

     if (tokenClaim != null && !String.IsNullOrWhiteSpace(tokenClaim.Value)) 
      request.AddHeader("Authorization", String.Format("Bearer {0}", tokenClaim.Value)); 
    } 
} 

cevap

1

Ben komik bir yenileme almak ve sonra yeni bir erişim elde için kullanabilirsiniz başardı jeton: Belirteç almak için sizinkiyle benzer mantığı izledim. Ben bir belirteç gerekli her zaman denilen aşağıdaki yöntemi oluşturuldu: yerel saat kadar beklemek Bence

private static async Task CheckAndPossiblyRefreshToken(ClaimsIdentity id) 
    { 
     var clientName = "Myhybridclient"; 
     // check if the access token hasn't expired. 
     if (DateTime.Now.ToLocalTime() >= 
      (DateTime.Parse(id.FindFirst("expires_at").Value))) 
     { 
      // expired. Get a new one. 
      var tokenEndpointClient = new OAuth2Client(
       new Uri(Constants.TokenEndpoint), 
       clientName, 
       "secret"); 

      var tokenEndpointResponse = 
       await tokenEndpointClient 
       .RequestRefreshTokenAsync(id.FindFirst("refresh_token").Value); 

      if (!tokenEndpointResponse.IsError) 
      { 
       // replace the claims with the new values - this means creating a 
       // new identity!        
       var result = from claim in id.Claims 
          where claim.Type != "access_token" && claim.Type != "refresh_token" && 
            claim.Type != "expires_at" 
          select claim; 

       var claims = result.ToList(); 

       claims.Add(new Claim("access_token", tokenEndpointResponse.AccessToken)); 
       claims.Add(new Claim("expires_at", 
          DateTime.Now.AddSeconds(tokenEndpointResponse.ExpiresIn) 
          .ToLocalTime().ToString())); 
       claims.Add(new Claim("refresh_token", tokenEndpointResponse.RefreshToken)); 

       var newIdentity = new ClaimsIdentity(claims, "Cookies"); 
       var wrapper = new HttpRequestWrapper(HttpContext.Current.Request); 
       wrapper.GetOwinContext().Authentication.SignIn(newIdentity); 
      } 
      else 
      { 
       // log, ... 
       throw new Exception("An error has occurred"); 
      } 
     } 
    } 
+1

büyük veya eşit erişim belirteci sona erme zamanı iyi bir fikir değildir. Bu durumun, AccessToken’in son kullanma tarihinden önce yalnızca birkaç milisaniye kadar geçerli olacağını düşündüğü bir durum düşünün. Böyle bir AccessToken'i başka bir hizmete gönderecekseniz, o zamanın süresi dolduğundan reddedilebilir. "Expires_at" iddiasını eklediğinizde, "refresh_at" iddiası ile şu an "expires_at" değeri arasında bir yarı zaman dilimi gibi bir şey ekleyebilirsiniz. Böyle bir çözüm, kullanabilmeniz için önce Erişim Simgesinin süresinin dolmadığından emin olmanızı sağlar. – Gilmor

+0

Genellikle yapılandırmaya izin veririm, belirtimin süresi dolup dolmadığını kontrol etmek için I dakika veririm: örneğin, belirtecin 1 dakikadan daha kısa bir sürede sona ermesi durumunda, devam edip yenileyeceğim. – jahansha

İlgili konular