private async Task <string> CreateRefreshTokenAsync( ClaimsPrincipal principal, AuthenticationProperties properties, OpenIdConnectMessage request, OpenIdConnectMessage response) { try { // properties.IssuedUtc and properties.ExpiresUtc // should always be preferred when explicitly set. if (properties.IssuedUtc == null) { properties.IssuedUtc = Options.SystemClock.UtcNow; } if (properties.ExpiresUtc == null) { properties.ExpiresUtc = properties.IssuedUtc + Options.RefreshTokenLifetime; } properties.SetUsage(OpenIdConnectConstants.Usages.RefreshToken); // Claims in refresh tokens are never filtered as they are supposed to be opaque: // CreateAccessTokenAsync and CreateIdentityTokenAsync are responsible of ensuring // that subsequent access and identity tokens are correctly filtered. var ticket = new AuthenticationTicket(principal, properties, Options.AuthenticationScheme); var notification = new CreateRefreshTokenContext(Context, Options, request, response, ticket) { DataFormat = Options.RefreshTokenFormat }; // Sets the default refresh token serializer. notification.Serializer = payload => { return(Task.FromResult(notification.DataFormat?.Protect(payload))); }; await Options.Provider.CreateRefreshToken(notification); // Treat a non-null refresh token like an implicit HandleResponse call. if (notification.HandledResponse || !string.IsNullOrEmpty(notification.RefreshToken)) { return(notification.RefreshToken); } else if (notification.Skipped) { return(null); } // Allow the application to change the authentication // ticket from the CreateRefreshTokenAsync event. ticket = notification.AuthenticationTicket; ticket.Properties.CopyTo(properties); return(await notification.SerializeTicketAsync()); } catch (Exception exception) { Logger.LogWarning("An exception occured when serializing a refresh token.", exception); return(null); } }