I recently installed IdentityServer v3 and it starts as a dream, however I am having problems with the OWIN middleware.
I would like to use a hybrid stream so that I can update the tokens in the backend without having to redirect the user back to IdentityServer in order to get a new access token every 5 minutes (which is also odd, since its set has a lifetime of 1 hour on the server).
I use the following configuration at startup, and I get the tokens in order, but never try to update the access token as soon as it expires. Do I need any special logic to update tokens?
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; } } } } });
I also use the following in my ApiClient (RestSharp) which talks to my api resource
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)); } }