Niedawno skonfigurowałem IdentityServer v3 i jego działanie było jak sen, jednak mam problemy z oprogramowaniem pośredniczącym OWIN.Odświeżanie tokenów przy użyciu owin middleware i IdentityServer v3
Chciałbym użyć przepływu hybrydowego, aby odświeżać tokeny w backendach, bez konieczności przekierowania użytkownika z powrotem do serwera tożsamości, aby uzyskać nowy token dostępu co 5 minut (co również jest nieparzyste, ponieważ jego zestaw ma mieć czas życia 1 godziny na serwerze).
Używam następującej konfiguracji podczas uruchamiania i otrzymuję tokeny dobrze, ale nigdy nie wydaje się, aby spróbować odświeżyć token dostępu, gdy wygasł. Czy potrzebuję jakiejś niestandardowej logiki, aby odświeżyć moje tokeny?
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;
}
}
}
}
});
Jestem również za pomocą następujących w moim ApiClient (RestSharp), który mówi do mojego API zasobów
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));
}
}
Moim zdaniem czeka do czasu lokalnego jest większy lub równy dostęp czas ważności tokenu nie jest najlepszym pomysłem. Wyobraźmy sobie sytuację, w której warunek ten będzie uważał za ważny tylko kilka milisekund przed wygaśnięciem. Jeśli wyślesz taki AccessToken do innej usługi, może on zostać odrzucony, ponieważ wygasł w międzyczasie. Podczas dodawania roszczenia "expires_at" możesz również dodać roszczenie typu "refresh_at" jako połowę okresu między teraz a wartością "expires_at". Takie rozwiązanie pozwoli upewnić się, że token dostępu nie wygaśnie, zanim będzie można z niego korzystać. – Gilmor
Zwykle zezwalam, poprzez konfigurację, na minutę sprawdzam, czy wygasł token: na przykład, jeśli token wygaśnie za mniej niż 1 minutę, przejdę dalej i odświeżę go. – jahansha