// Based on https://stackoverflow.com/a/44322425/1249506
        public async Task <IdentityServerToken> GetIdentityServerTokenForUserAsync(User user)
        {
            var request          = new TokenCreationRequest();
            var identityPricipal = await PrincipalFactory.CreateAsync(user);

            var identityUser =
                new IdentityServerUser(user.Id.ToString())
            {
                AdditionalClaims   = identityPricipal.Claims.ToArray(),
                DisplayName        = user.UserName,
                AuthenticationTime = DateTime.UtcNow,
                IdentityProvider   = IdentityServerConstants.LocalIdentityProvider
            };

            request.Subject = identityUser.CreatePrincipal();
            request.IncludeAllIdentityClaims = true;
            request.ValidatedRequest         = new ValidatedRequest
            {
                Subject = request.Subject,
            };

            var client = await ClientStore.FindClientByIdAsync(ClientId);

            request.ValidatedRequest.SetClient(client);
            request.Resources =
                new Resources(await ResourceStore.FindEnabledIdentityResourcesByScopeAsync(client.AllowedScopes),
                              await ResourceStore.FindApiResourcesByScopeAsync(client.AllowedScopes))
            {
                OfflineAccess = client.AllowOfflineAccess
            };

            request.ValidatedRequest.Options      = Options;
            request.ValidatedRequest.ClientClaims = identityUser.AdditionalClaims;

            var token = await TokenService.CreateAccessTokenAsync(request);

            var accessToken = await TokenService.CreateSecurityTokenAsync(token);

            var refreshToken = await RefreshTokenService.CreateRefreshTokenAsync(request.Subject, token, client);

            return(new IdentityServerToken(token, accessToken, refreshToken));
        }
예제 #2
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);
        }
예제 #3
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);
        }