// 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 virtual async Task <Token> CreateIdentityTokenAsync(ClaimsPrincipal subject, Client client, IEnumerable <Scope> scopes, bool includeAllIdentityClaims, NameValueCollection request, string accessTokenToHash = null)
        {
            Logger.Debug("Creating identity token");

            // host provided claims
            var claims = new List <Claim>();

            // if nonce was sent, must be mirrored in id token
            var nonce = request.Get(Constants.AuthorizeRequest.Nonce);

            if (nonce.IsPresent())
            {
                claims.Add(new Claim(Constants.ClaimTypes.Nonce, nonce));
            }

            // add iat claim
            claims.Add(new Claim(Constants.ClaimTypes.IssuedAt, DateTime.UtcNow.ToEpochTime().ToString(), ClaimValueTypes.Integer));

            // add at_hash claim
            if (accessTokenToHash.IsPresent())
            {
                claims.Add(new Claim(Constants.ClaimTypes.AccessTokenHash, HashAccessToken(accessTokenToHash)));
            }

            claims.AddRange(await _claimsProvider.GetIdentityTokenClaimsAsync(
                                subject,
                                client,
                                scopes,
                                _settings,
                                includeAllIdentityClaims,
                                _users,
                                request));

            var token = new Token(Constants.TokenTypes.IdentityToken)
            {
                Audience = client.ClientId,
                Issuer   = _settings.IssuerUri,
                Lifetime = client.IdentityTokenLifetime,
                Claims   = claims.Distinct(new ClaimComparer()).ToList(),
                Client   = client
            };

            return(token);
        }