/// <summary> /// Creates the refresh token. /// </summary> /// <param name="subject">The subject.</param> /// <param name="accessToken">The access token.</param> /// <param name="client">The client.</param> /// <returns> /// The refresh token handle /// </returns> public virtual async Task<string> CreateRefreshTokenAsync(ClaimsPrincipal subject, Token accessToken, Client client) { _logger.LogVerbose("Creating refresh token"); int lifetime; if (client.RefreshTokenExpiration == TokenExpiration.Absolute) { _logger.LogVerbose("Setting an absolute lifetime: " + client.AbsoluteRefreshTokenLifetime); lifetime = client.AbsoluteRefreshTokenLifetime; } else { _logger.LogVerbose("Setting a sliding lifetime: " + client.SlidingRefreshTokenLifetime); lifetime = client.SlidingRefreshTokenLifetime; } var handle = CryptoRandom.CreateUniqueId(); var refreshToken = new RefreshToken { CreationTime = DateTimeOffsetHelper.UtcNow, LifeTime = lifetime, AccessToken = accessToken, Subject = subject }; await _store.StoreAsync(handle, refreshToken); await RaiseRefreshTokenIssuedEventAsync(handle, refreshToken); return handle; }
public static Token CreateAccessTokenLong(Client client, string subjectId, int lifetime, int count, params string[] scopes) { var claims = new List<Claim> { new Claim("client_id", client.ClientId), new Claim("sub", subjectId) }; for (int i = 0; i < count; i++) { claims.Add(new Claim("junk", "x".Repeat(100))); } scopes.ToList().ForEach(s => claims.Add(new Claim("scope", s))); var token = new Token(Constants.TokenTypes.AccessToken) { Audience = "https://idsrv3.com/resources", Issuer = "https://idsrv3.com", Lifetime = lifetime, Claims = claims, Client = client }; return token; }
/// <summary> /// Creates the JWT header /// </summary> /// <param name="token">The token.</param> /// <param name="credential">The credentials.</param> /// <returns>The JWT header</returns> protected virtual Task<JwtHeader> CreateHeaderAsync(Token token, SecurityKey key) { JwtHeader header = null; header = new JwtHeader(new SigningCredentials(key, "RS256")); return Task.FromResult(header); }
/// <summary> /// Creates the json web token. /// </summary> /// <param name="token">The token.</param> /// <param name="credentials">The credentials.</param> /// <returns>The signed JWT</returns> protected virtual async Task<string> CreateJsonWebToken(Token token, AzureKeyVaultSigningCredentials credentials) { var header = await CreateHeaderAsync(token, credentials); var payload = await CreatePayloadAsync(token); return await SignAsync(new JwtSecurityToken(header, payload)); }
/// <summary> /// Signs the token. /// </summary> /// <param name="token">The token.</param> /// <returns> /// A protected and serialized security token /// </returns> public virtual async Task<string> SignTokenAsync(Token token) { var key = new X509SecurityKey(await _keyService.GetSigningKeyAsync()); var header = await CreateHeaderAsync(token, key); var payload = await CreatePayloadAsync(token); return await SignAsync(new JwtSecurityToken(header, payload)); }
/// <summary> /// Creates the JWT header /// </summary> /// <param name="token">The token.</param> /// <param name="credential">The credentials.</param> /// <returns>The JWT header</returns> protected virtual async Task<JwtHeader> CreateHeaderAsync(Token token, SecurityKey key) { JwtHeader header = null; #if DOTNET5_4 header = new JwtHeader(new SigningCredentials(key, SecurityAlgorithms.RsaSha256Signature)); #elif NET451 header = new JwtHeader(new SigningCredentials(key, SecurityAlgorithms.RsaSha256Signature, SecurityAlgorithms.Sha256Digest)); var x509key = key as X509SecurityKey; if (x509key != null) { header.Add("kid", await _keyService.GetKidAsync(x509key.Certificate)); header.Add("x5t", await _keyService.GetKidAsync(x509key.Certificate)); } #endif return header; }
public static Token CreateIdentityToken(string clientId, string subjectId) { var clients = Factory.CreateClientStore(); var claims = new List<Claim> { new Claim("sub", subjectId) }; var token = new Token(Constants.TokenTypes.IdentityToken) { Audience = clientId, Client = clients.FindClientByIdAsync(clientId).Result, Issuer = "https://idsrv3.com", Lifetime = 600, Claims = claims }; return token; }
public static Token CreateAccessToken(Client client, string subjectId, int lifetime, params string[] scopes) { var claims = new List<Claim> { new Claim("client_id", client.ClientId), new Claim("sub", subjectId) }; scopes.ToList().ForEach(s => claims.Add(new Claim("scope", s))); var token = new Token(OidcConstants.TokenTypes.AccessToken) { Audience = "https://idsrv3.com/resources", Issuer = "https://idsrv3.com", Lifetime = lifetime, Claims = claims, Client = client }; return token; }
/// <summary> /// Creates the JWT payload /// </summary> /// <param name="token">The token.</param> /// <returns>The JWT payload</returns> protected virtual Task<JwtPayload> CreatePayloadAsync(Token token) { var payload = new JwtPayload( token.Issuer, token.Audience, null, DateTimeHelper.UtcNow, DateTimeHelper.UtcNow.AddSeconds(token.Lifetime)); var amrClaims = token.Claims.Where(x => x.Type == Constants.ClaimTypes.AuthenticationMethod); var jsonClaims = token.Claims.Where(x => x.ValueType == Constants.ClaimValueTypes.Json); var normalClaims = token.Claims.Except(amrClaims).Except(jsonClaims); payload.AddClaims(normalClaims); // deal with amr var amrValues = amrClaims.Select(x => x.Value).Distinct().ToArray(); if (amrValues.Any()) { payload.Add(Constants.ClaimTypes.AuthenticationMethod, amrValues); } // deal with json types // calling ToArray() to trigger JSON parsing once and so later // collection identity comparisons work for the anonymous type var jsonTokens = jsonClaims.Select(x => new { x.Type, JsonValue = JRaw.Parse(x.Value) }).ToArray(); var jsonObjects = jsonTokens.Where(x => x.JsonValue.Type == JTokenType.Object).ToArray(); var jsonObjectGroups = jsonObjects.GroupBy(x => x.Type).ToArray(); foreach (var group in jsonObjectGroups) { if (payload.ContainsKey(group.Key)) { throw new Exception(String.Format("Can't add two claims where one is a JSON object and the other is not a JSON object ({0})", group.Key)); } if (group.Skip(1).Any()) { // add as array payload.Add(group.Key, group.Select(x => x.JsonValue).ToArray()); } else { // add just one payload.Add(group.Key, group.First().JsonValue); } } var jsonArrays = jsonTokens.Where(x => x.JsonValue.Type == JTokenType.Array).ToArray(); var jsonArrayGroups = jsonArrays.GroupBy(x => x.Type).ToArray(); foreach (var group in jsonArrayGroups) { if (payload.ContainsKey(group.Key)) { throw new Exception(String.Format("Can't add two claims where one is a JSON array and the other is not a JSON array ({0})", group.Key)); } List<JToken> newArr = new List<JToken>(); foreach (var arrays in group) { var arr = (JArray)arrays.JsonValue; newArr.AddRange(arr); } // add just one array for the group/key/claim type payload.Add(group.Key, newArr.ToArray()); } var unsupportedJsonTokens = jsonTokens.Except(jsonObjects).Except(jsonArrays); var unsupportedJsonClaimTypes = unsupportedJsonTokens.Select(x => x.Type).Distinct(); if (unsupportedJsonClaimTypes.Any()) { throw new Exception(String.Format("Unsupported JSON type for claim types: {0}", unsupportedJsonClaimTypes.Aggregate((x, y) => x + ", " + y))); } return Task.FromResult(payload); }
/// <summary> /// Creates a serialized and protected security token. /// </summary> /// <param name="token">The token.</param> /// <returns> /// A security token in serialized form /// </returns> /// <exception cref="System.InvalidOperationException">Invalid token type.</exception> public virtual async Task<string> CreateSecurityTokenAsync(Token token) { string tokenResult; if (token.Type == Constants.TokenTypes.AccessToken) { if (token.Client.AccessTokenType == AccessTokenType.Jwt) { _logger.LogVerbose("Creating JWT access token"); tokenResult = await _signingService.SignTokenAsync(token); } else { _logger.LogVerbose("Creating reference access token"); var handle = CryptoRandom.CreateUniqueId(); await _tokenHandles.StoreAsync(handle, token); tokenResult = handle; } } else if (token.Type == Constants.TokenTypes.IdentityToken) { _logger.LogVerbose("Creating JWT identity token"); tokenResult = await _signingService.SignTokenAsync(token); } else { throw new InvalidOperationException("Invalid token type."); } await _events.RaiseTokenIssuedEventAsync(token, tokenResult); return tokenResult; }
/// <summary> /// Creates an access token. /// </summary> /// <param name="request">The token creation request.</param> /// <returns> /// An access token /// </returns> public virtual async Task<Token> CreateAccessTokenAsync(TokenCreationRequest request) { _logger.LogVerbose("Creating access token"); request.Validate(); var claims = new List<Claim>(); claims.AddRange(await _claimsProvider.GetAccessTokenClaimsAsync( request.Subject, request.Client, request.Scopes, request.ValidatedRequest)); if (request.Client.IncludeJwtId) { claims.Add(new Claim(Constants.ClaimTypes.JwtId, CryptoRandom.CreateUniqueId())); } var issuer = _context.GetIssuerUri(); var token = new Token(Constants.TokenTypes.AccessToken) { Audience = string.Format(Constants.AccessTokenAudience, issuer.EnsureTrailingSlash()), Issuer = issuer, Lifetime = request.Client.AccessTokenLifetime, Claims = claims.Distinct(new ClaimComparer()).ToList(), Client = request.Client }; return token; }
/// <summary> /// Creates the JWT header /// </summary> /// <param name="token">The token.</param> /// <param name="keyVaultCredentials">The credentials.</param> /// <returns>The JWT header</returns> protected virtual Task<JwtHeader> CreateHeaderAsync(Token token, AzureKeyVaultSigningCredentials keyVaultCredentials) { var header = new JwtHeader(keyVaultCredentials); if (keyVaultCredentials != null) { header.Add("kid", _options.KeyIdentifier); header.Add("x5t", _options.KeyIdentifier); } return Task.FromResult(header); }
/// <summary> /// Signs the token. /// </summary> /// <param name="token">The token.</param> /// <returns> /// A protected and serialized security token /// </returns> public virtual async Task<string> SignTokenAsync(Token token) { var credentials = await GetSigningCredentialsAsync(); return await CreateJsonWebToken(token, credentials); }
/// <summary> /// Stores the data. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <returns></returns> public Task StoreAsync(string key, Token value) { _repository[key] = value; return Task.FromResult<object>(null); }
// todo ///// <summary> ///// Initializes a new instance of the <see cref="DefaultTokenService" /> class. ///// </summary> ///// <param name="options">The options.</param> ///// <param name="claimsProvider">The claims provider.</param> ///// <param name="tokenHandles">The token handles.</param> ///// <param name="signingService">The signing service.</param> ///// <param name="events">The OWIN environment service.</param> ///// <param name="owinEnvironmentService">The events service.</param> //public DefaultTokenService(IdentityServerOptions options, IClaimsProvider claimsProvider, ITokenHandleStore tokenHandles, ITokenSigningService signingService, IEventService events, OwinEnvironmentService owinEnvironmentService) //{ // _options = options; // _claimsProvider = claimsProvider; // _tokenHandles = tokenHandles; // _signingService = signingService; // _events = events; // _owinEnvironmentService = owinEnvironmentService; //} /// <summary> /// Creates an identity token. /// </summary> /// <param name="request">The token creation request.</param> /// <returns> /// An identity token /// </returns> public virtual async Task<Token> CreateIdentityTokenAsync(TokenCreationRequest request) { _logger.LogVerbose("Creating identity token"); request.Validate(); // host provided claims var claims = new List<Claim>(); // if nonce was sent, must be mirrored in id token if (request.Nonce.IsPresent()) { claims.Add(new Claim(Constants.ClaimTypes.Nonce, request.Nonce)); } // add iat claim claims.Add(new Claim(Constants.ClaimTypes.IssuedAt, DateTimeOffsetHelper.UtcNow.ToEpochTime().ToString(), ClaimValueTypes.Integer)); // add at_hash claim if (request.AccessTokenToHash.IsPresent()) { claims.Add(new Claim(Constants.ClaimTypes.AccessTokenHash, HashAdditionalData(request.AccessTokenToHash))); } // add c_hash claim if (request.AuthorizationCodeToHash.IsPresent()) { claims.Add(new Claim(Constants.ClaimTypes.AuthorizationCodeHash, HashAdditionalData(request.AuthorizationCodeToHash))); } // add sid if present if (request.ValidatedRequest.SessionId.IsPresent()) { claims.Add(new Claim(Constants.ClaimTypes.SessionId, request.ValidatedRequest.SessionId)); } claims.AddRange(await _claimsProvider.GetIdentityTokenClaimsAsync( request.Subject, request.Client, request.Scopes, request.IncludeAllIdentityClaims, request.ValidatedRequest)); var issuer = _context.GetIssuerUri(); var token = new Token(Constants.TokenTypes.IdentityToken) { Audience = request.Client.ClientId, Issuer = issuer, Lifetime = request.Client.IdentityTokenLifetime, Claims = claims.Distinct(new ClaimComparer()).ToList(), Client = request.Client }; return token; }
public static Token CreateIdentityTokenLong(string clientId, string subjectId, int count) { var clients = Factory.CreateClientStore(); var claims = new List<Claim> { new Claim("sub", subjectId) }; for (int i = 0; i < count; i++) { claims.Add(new Claim("junk", "x".Repeat(100))); } var token = new Token(Constants.TokenTypes.IdentityToken) { Audience = clientId, Client = clients.FindClientByIdAsync(clientId).Result, Issuer = "https://idsrv3.com", Lifetime = 600, Claims = claims }; return token; }
private IEnumerable<Claim> ReferenceTokenToClaims(Token token) { var claims = new List<Claim> { new Claim(Constants.ClaimTypes.Audience, token.Audience), new Claim(Constants.ClaimTypes.Issuer, token.Issuer), new Claim(Constants.ClaimTypes.NotBefore, token.CreationTime.ToEpochTime().ToString()), new Claim(Constants.ClaimTypes.Expiration, token.CreationTime.AddSeconds(token.Lifetime).ToEpochTime().ToString()) }; claims.AddRange(token.Claims); return claims; }