Example #1
0
        public override async Task <string> CreateRefreshTokenAsync(RefreshTokenCreationRequest request)
        {
            Logger.LogDebug("Creating refresh token");

            int lifetime;

            if (request.Client.RefreshTokenExpiration == TokenExpiration.Absolute)
            {
                Logger.LogDebug("Setting an absolute lifetime: {absoluteLifetime}",
                                request.Client.AbsoluteRefreshTokenLifetime);
                lifetime = request.Client.AbsoluteRefreshTokenLifetime;
            }
            else
            {
                lifetime = request.Client.SlidingRefreshTokenLifetime;
                if (request.Client.AbsoluteRefreshTokenLifetime > 0 && lifetime > request.Client.AbsoluteRefreshTokenLifetime)
                {
                    Logger.LogWarning(
                        "Client {clientId}'s configured " + nameof(request.Client.SlidingRefreshTokenLifetime) +
                        " of {slidingLifetime} exceeds its " + nameof(request.Client.AbsoluteRefreshTokenLifetime) +
                        " of {absoluteLifetime}. The refresh_token's sliding lifetime will be capped to the absolute lifetime",
                        request.Client.ClientId, lifetime, request.Client.AbsoluteRefreshTokenLifetime);
                    lifetime = request.Client.AbsoluteRefreshTokenLifetime;
                }

                Logger.LogDebug("Setting a sliding lifetime: {slidingLifetime}", lifetime);
            }
            var formCollection = await _scopedHttpContextRequestForm.GetFormCollectionAsync();

            var originGrantType = formCollection["grant_type"];

            var refreshToken = new RefreshTokenExtra()
            {
                Subject                      = request.Subject,
                ClientId                     = request.Client.ClientId,
                Description                  = request.Description,
                AuthorizedScopes             = request.AuthorizedScopes,
                AuthorizedResourceIndicators = request.AuthorizedResourceIndicators,

                CreationTime    = Clock.UtcNow.UtcDateTime,
                Lifetime        = lifetime,
                OriginGrantType = originGrantType
            };

            refreshToken.SetAccessToken(request.AccessToken, request.RequestedResourceIndicator);

            var handle = await RefreshTokenStore.StoreRefreshTokenAsync(refreshToken);

            return(handle);
        }
    /// <summary>
    /// Creates the refresh token.
    /// </summary>
    /// <returns>
    /// The refresh token handle
    /// </returns>
    public virtual async Task <string> CreateRefreshTokenAsync(RefreshTokenCreationRequest request)
    {
        using var activity = Tracing.ServiceActivitySource.StartActivity("DefaultRefreshTokenService.CreateRefreshToken");

        Logger.LogDebug("Creating refresh token");

        int lifetime;

        if (request.Client.RefreshTokenExpiration == TokenExpiration.Absolute)
        {
            Logger.LogDebug("Setting an absolute lifetime: {absoluteLifetime}",
                            request.Client.AbsoluteRefreshTokenLifetime);
            lifetime = request.Client.AbsoluteRefreshTokenLifetime;
        }
        else
        {
            lifetime = request.Client.SlidingRefreshTokenLifetime;
            if (request.Client.AbsoluteRefreshTokenLifetime > 0 && lifetime > request.Client.AbsoluteRefreshTokenLifetime)
            {
                Logger.LogWarning(
                    "Client {clientId}'s configured " + nameof(request.Client.SlidingRefreshTokenLifetime) +
                    " of {slidingLifetime} exceeds its " + nameof(request.Client.AbsoluteRefreshTokenLifetime) +
                    " of {absoluteLifetime}. The refresh_token's sliding lifetime will be capped to the absolute lifetime",
                    request.Client.ClientId, lifetime, request.Client.AbsoluteRefreshTokenLifetime);
                lifetime = request.Client.AbsoluteRefreshTokenLifetime;
            }

            Logger.LogDebug("Setting a sliding lifetime: {slidingLifetime}", lifetime);
        }

        var refreshToken = new RefreshToken
        {
            Subject                      = request.Subject,
            SessionId                    = request.AccessToken.SessionId,
            ClientId                     = request.Client.ClientId,
            Description                  = request.Description,
            AuthorizedScopes             = request.AuthorizedScopes,
            AuthorizedResourceIndicators = request.AuthorizedResourceIndicators,

            CreationTime = Clock.UtcNow.UtcDateTime,
            Lifetime     = lifetime,
        };

        refreshToken.SetAccessToken(request.AccessToken, request.RequestedResourceIndicator);

        var handle = await RefreshTokenStore.StoreRefreshTokenAsync(refreshToken);

        return(handle);
    }
Example #3
0
 /// <inheritdoc/>
 public Task <string> CreateRefreshTokenAsync(RefreshTokenCreationRequest request)
 {
     return(Inner.CreateRefreshTokenAsync(request));
 }
Example #4
0
        protected async override Task <(string accessToken, string refreshToken)> CreateAccessTokenAsync(ValidatedTokenRequest request)
        {
            var formCollection = _scopedHttpContextRequestForm.GetFormCollection();
            var grantType      = formCollection["grant_type"];

            var tokenRequest = new TokenCreationRequest
            {
                Subject            = request.Subject,
                ValidatedResources = request.ValidatedResources,
                ValidatedRequest   = request
            };

            bool createRefreshToken;
            var  authorizedScopes = Enumerable.Empty <string>();
            IEnumerable <string> authorizedResourceIndicators = null;

            if (request.AuthorizationCode != null)
            {
                createRefreshToken = request.ValidatedResources.Resources.OfflineAccess;

                //                createRefreshToken = request.AuthorizationCode.RequestedScopes.Contains(IdentityServerConstants.StandardScopes.OfflineAccess);

                // load the client that belongs to the authorization code
                Client client = null;
                if (request.AuthorizationCode.ClientId != null)
                {
                    // todo: do we need this check?
                    client = await Clients.FindEnabledClientByIdAsync(request.AuthorizationCode.ClientId);
                }
                if (client == null)
                {
                    throw new InvalidOperationException("Client does not exist anymore.");
                }

                tokenRequest.Subject     = request.AuthorizationCode.Subject;
                tokenRequest.Description = request.AuthorizationCode.Description;

                authorizedScopes             = request.AuthorizationCode.RequestedScopes;
                authorizedResourceIndicators = request.AuthorizationCode.RequestedResourceIndicators;
            }
            else if (request.DeviceCode != null)
            {
                createRefreshToken = request.DeviceCode.AuthorizedScopes.Contains(IdentityServerConstants.StandardScopes.OfflineAccess);

                Client client = null;
                if (request.DeviceCode.ClientId != null)
                {
                    // todo: do we need this check?
                    client = await Clients.FindEnabledClientByIdAsync(request.DeviceCode.ClientId);
                }
                if (client == null)
                {
                    throw new InvalidOperationException("Client does not exist anymore.");
                }

                tokenRequest.Subject     = request.DeviceCode.Subject;
                tokenRequest.Description = request.DeviceCode.Description;

                authorizedScopes = request.DeviceCode.AuthorizedScopes;
            }
            else
            {
                createRefreshToken = request.RequestedScopes.Contains(IdentityServerConstants.StandardScopes.OfflineAccess);
                authorizedScopes   = request.ValidatedResources.RawScopeValues;
            }


            var at = await TokenService.CreateAccessTokenAsync(tokenRequest);

            object obj;

            if (_scopedStorage.TryGetValue(Constants.ScopedRequestType.OverrideTokenIssuedAtTime, out obj))
            {
                DateTime issuedAtTime = obj is DateTime ? (DateTime)obj : default;
                at.CreationTime = issuedAtTime;
            }

            var finalScopes = at.Scopes.ToList();

            if (createRefreshToken)
            {
                if (!finalScopes.Contains(IdentityServerConstants.StandardScopes.OfflineAccess))
                {
                    finalScopes.Add(IdentityServerConstants.StandardScopes.OfflineAccess);
                }
            }
            else
            {
                if (finalScopes.Contains(IdentityServerConstants.StandardScopes.OfflineAccess))
                {
                    finalScopes.Remove(IdentityServerConstants.StandardScopes.OfflineAccess);
                }
            }

            var accessToken = await TokenService.CreateSecurityTokenAsync(at);

            string refreshToken = null;

            if (createRefreshToken)
            {
                var rtRequest = new RefreshTokenCreationRequest
                {
                    Client                       = request.Client,
                    Subject                      = tokenRequest.Subject,
                    Description                  = tokenRequest.Description,
                    AuthorizedScopes             = authorizedScopes,
                    AuthorizedResourceIndicators = authorizedResourceIndicators,
                    AccessToken                  = at,
                    RequestedResourceIndicator   = request.RequestedResourceIndicator,
                };


                refreshToken = await RefreshTokenService.CreateRefreshTokenAsync(rtRequest);
            }

            if (_scopedStorage.TryGetValue(Constants.ScopedRequestType.ExtensionGrantValidationContext, out obj))
            {
                var extensionGrantValidationContext = obj as ExtensionGrantValidationContext;
                if (extensionGrantValidationContext.Request.GrantType == FluffyBunny4.Constants.GrantType.TokenExchangeMutate)
                {
                    var refreshTokenStoreGrantStoreHashAccessor   = _refreshTokenStore as IGrantStoreHashAccessor;
                    var referenceTokenStoreGrantStoreHashAccessor = _referenceTokenStore as IGrantStoreHashAccessor;

                    _scopedStorage.TryGetValue(Constants.ScopedRequestType.PersistedGrantExtra, out obj);
                    var persistedGrantExtra =
                        _scopedStorage.Get <PersistedGrantExtra>(Constants.ScopedRequestType.PersistedGrantExtra);
                    var subjectToken =
                        _scopedStorage.Get <string>(Constants.ScopedRequestType.SubjectToken);
                    var fixedSubjectToken = subjectToken.Substring(2);
                    var newKey            = referenceTokenStoreGrantStoreHashAccessor.GetHashedKey(accessToken);
                    var originalKey       = referenceTokenStoreGrantStoreHashAccessor.GetHashedKey(fixedSubjectToken);

                    await _persistedGrantStore.CopyAsync(newKey, originalKey);

                    await _persistedGrantStore.RemoveAsync(newKey);

                    if (!createRefreshToken && !string.IsNullOrWhiteSpace(persistedGrantExtra.RefreshTokenKey))
                    {
                        // need to kill the old refresh token, as this mutate didn't ask for a new one.
                        await _persistedGrantStore.RemoveAsync(persistedGrantExtra.RefreshTokenKey);
                    }
                    else
                    {
                        newKey = refreshTokenStoreGrantStoreHashAccessor.GetHashedKey(refreshToken);
                        await _persistedGrantStore.CopyAsync(newKey, persistedGrantExtra.RefreshTokenKey);

                        await _persistedGrantStore.RemoveAsync(newKey);
                    }

                    // we need to point the old access_token and refresh_token to this new set;
                    return(subjectToken, null);   // mutate doesn't get to get the refresh_token back, the original holder of it is the only owner.
                }
            }


            switch (grantType)
            {
            case FluffyBunny4.Constants.GrantType.ArbitraryIdentity:
            case FluffyBunny4.Constants.GrantType.ArbitraryToken:
            case OidcConstants.GrantTypes.DeviceCode:
            case FluffyBunny4.Constants.GrantType.TokenExchange:
            case FluffyBunny4.Constants.GrantType.TokenExchangeMutate:
                if (!accessToken.Contains('.'))
                {
                    accessToken = $"1_{accessToken}";
                }

                if (!string.IsNullOrWhiteSpace(refreshToken))
                {
                    refreshToken = $"1_{refreshToken}";
                }

                break;

            default:
                if (!accessToken.Contains('.'))
                {
                    accessToken = $"0_{accessToken}";
                }
                if (!string.IsNullOrWhiteSpace(refreshToken))
                {
                    refreshToken = $"0_{refreshToken}";
                }

                break;
            }

            return(accessToken, refreshToken);

            //       return (accessToken, null);
        }
Example #5
0
        private async Task <TokenResponse> ProcessArbitraryTokenTokenResponse(TokenRequestValidationResult validationResult)
        {
            var subject =
                validationResult.ValidatedRequest.Subject.Claims.FirstOrDefault(x =>
                                                                                x.Type == JwtClaimTypes.Subject);


            var form         = validationResult.ValidatedRequest.Raw;
            var resultClaims = new List <Claim>()
            {
                subject
            };

            resultClaims.AddRange(_scopedOptionalClaims.Claims);
            var issuer = validationResult.ValidatedRequest.Raw.Get("issuer");

            if (string.IsNullOrEmpty(issuer))
            {
                issuer = _contextAccessor.HttpContext.GetIdentityServerIssuerUri();
            }

            var atClaims = resultClaims.Distinct(new ClaimComparer()).ToList();

            bool createRefreshToken;

            var offlineAccessClaim =
                atClaims.FirstOrDefault(x =>
                                        x.Type == JwtClaimTypes.Scope && x.Value == IdentityServerConstants.StandardScopes.OfflineAccess);

            createRefreshToken = offlineAccessClaim != null;

            var authorizedScopes = (from c in atClaims
                                    where c.Type == JwtClaimTypes.Scope
                                    select c.Value).ToList();

            var accessTokenLifetimeOverride = form.Get(Constants.AccessTokenLifetime);

            int accessTokenLifetime = validationResult.ValidatedRequest.AccessTokenLifetime;

            if (!string.IsNullOrWhiteSpace(accessTokenLifetimeOverride))
            {
                int.TryParse(accessTokenLifetimeOverride, out accessTokenLifetime);
            }



            var at = new Token(OidcConstants.TokenTypes.AccessToken)
            {
                CreationTime = Clock.UtcNow.UtcDateTime,
                Issuer       = issuer,
                Lifetime     = accessTokenLifetime,
                Claims       = atClaims,
                ClientId     = validationResult.ValidatedRequest.ClientId,
                //    Description = request.Description,
                AccessTokenType          = validationResult.ValidatedRequest.AccessTokenType,
                AllowedSigningAlgorithms = validationResult.ValidatedRequest.Client.AllowedIdentityTokenSigningAlgorithms,
            };
            var accessToken = await TokenService.CreateSecurityTokenAsync(at);

            string refreshToken = null;

            if (createRefreshToken)
            {
                var refreshTokenCreationRequest = new RefreshTokenCreationRequest
                {
                    Subject          = validationResult.ValidatedRequest.Subject,
                    AccessToken      = at,
                    Client           = validationResult.ValidatedRequest.Client,
                    AuthorizedScopes = authorizedScopes
                };
                refreshToken = await RefreshTokenService.CreateRefreshTokenAsync(refreshTokenCreationRequest);
            }

            var tokenResonse = new TokenResponse
            {
                AccessToken         = accessToken,
                IdentityToken       = null,
                RefreshToken        = $"1_{refreshToken}",
                AccessTokenLifetime = accessTokenLifetime
            };

            return(tokenResonse);
        }
        /// <summary>
        /// Creates the access/refresh token.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns></returns>
        /// <exception cref="System.InvalidOperationException">Client does not exist anymore.</exception>
        protected virtual async Task <(string accessToken, string refreshToken)> CreateAccessTokenAsync(ValidatedTokenRequest request)
        {
            var tokenRequest = new TokenCreationRequest
            {
                Subject            = request.Subject,
                ValidatedResources = request.ValidatedResources,
                ValidatedRequest   = request
            };

            bool createRefreshToken = request.ValidatedResources.Resources.OfflineAccess;
            var  authorizedScopes   = Enumerable.Empty <string>();
            IEnumerable <string> authorizedResourceIndicators = null;

            if (request.AuthorizationCode != null)
            {
                // load the client that belongs to the authorization code
                Client client = null;
                if (request.AuthorizationCode.ClientId != null)
                {
                    // todo: do we need this check?
                    client = await Clients.FindEnabledClientByIdAsync(request.AuthorizationCode.ClientId);
                }
                if (client == null)
                {
                    throw new InvalidOperationException("Client does not exist anymore.");
                }

                tokenRequest.Subject     = request.AuthorizationCode.Subject;
                tokenRequest.Description = request.AuthorizationCode.Description;

                authorizedScopes             = request.AuthorizationCode.RequestedScopes;
                authorizedResourceIndicators = request.AuthorizationCode.RequestedResourceIndicators;
            }
            else if (request.DeviceCode != null)
            {
                Client client = null;
                if (request.DeviceCode.ClientId != null)
                {
                    // todo: do we need this check?
                    client = await Clients.FindEnabledClientByIdAsync(request.DeviceCode.ClientId);
                }
                if (client == null)
                {
                    throw new InvalidOperationException("Client does not exist anymore.");
                }

                tokenRequest.Subject     = request.DeviceCode.Subject;
                tokenRequest.Description = request.DeviceCode.Description;

                authorizedScopes = request.DeviceCode.AuthorizedScopes;
            }
            else
            {
                authorizedScopes = request.ValidatedResources.RawScopeValues;
            }

            var at = await TokenService.CreateAccessTokenAsync(tokenRequest);

            var accessToken = await TokenService.CreateSecurityTokenAsync(at);

            if (createRefreshToken)
            {
                var rtRequest = new RefreshTokenCreationRequest
                {
                    Client                       = request.Client,
                    Subject                      = tokenRequest.Subject,
                    Description                  = tokenRequest.Description,
                    AuthorizedScopes             = authorizedScopes,
                    AuthorizedResourceIndicators = authorizedResourceIndicators,
                    AccessToken                  = at,
                    RequestedResourceIndicator   = request.RequestedResourceIndicator,
                };
                var refreshToken = await RefreshTokenService.CreateRefreshTokenAsync(rtRequest);

                return(accessToken, refreshToken);
            }

            return(accessToken, null);
        }