// 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)); }
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); }
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); }