private async Task <(string ClientSecret, DateTimeOffset ExpiresAt)> GenerateNewSecretAsync( [NotNull] AppleGenerateClientSecretContext context) { var expiresAt = _clock.UtcNow.Add(context.Options.ClientSecretExpiresAfter).UtcDateTime; var subject = new Claim("sub", context.Options.ClientId); Log.GeneratingNewClientSecret(_logger, subject.Value, expiresAt); var tokenDescriptor = new SecurityTokenDescriptor() { Audience = context.Options.TokenAudience, Expires = expiresAt, Issuer = context.Options.TeamId, Subject = new ClaimsIdentity(new[] { subject }), }; var pem = await context.Options.PrivateKey !(context.Options.KeyId !, context.HttpContext.RequestAborted); string clientSecret; using (var algorithm = CreateAlgorithm(pem)) { tokenDescriptor.SigningCredentials = CreateSigningCredentials(context.Options.KeyId !, algorithm); clientSecret = context.Options.SecurityTokenHandler.CreateToken(tokenDescriptor); } Log.GeneratedNewClientSecret(_logger, clientSecret); return(clientSecret, expiresAt); }
private async Task <(string clientSecret, DateTimeOffset expiresAt)> GenerateNewSecretAsync( [NotNull] AppleGenerateClientSecretContext context) { var expiresAt = _clock.UtcNow.Add(context.Options.ClientSecretExpiresAfter).UtcDateTime; var subject = new Claim("sub", context.Options.ClientId); _logger.LogDebug( "Generating new client secret for subject {Subject} that will expire at {ExpiresAt}.", subject.Value, expiresAt); var tokenDescriptor = new SecurityTokenDescriptor() { Audience = context.Options.TokenAudience, Expires = expiresAt, Issuer = context.Options.TeamId, Subject = new ClaimsIdentity(new[] { subject }), }; byte[] keyBlob = await _keyStore.LoadPrivateKeyAsync(context); string clientSecret; using (var algorithm = CreateAlgorithm(keyBlob)) { tokenDescriptor.SigningCredentials = CreateSigningCredentials(context.Options.KeyId !, algorithm); clientSecret = _tokenHandler.CreateEncodedJwt(tokenDescriptor); } _logger.LogTrace("Generated new client secret with value {ClientSecret}.", clientSecret); return(clientSecret, expiresAt); }
/// <inheritdoc /> protected override async Task <OAuthTokenResponse> ExchangeCodeAsync([NotNull] OAuthCodeExchangeContext context) { if (Options.GenerateClientSecret) { var secretGenerationContext = new AppleGenerateClientSecretContext(Context, Scheme, Options); await Events.GenerateClientSecret(secretGenerationContext); } return(await base.ExchangeCodeAsync(context)); }
/// <inheritdoc /> public override async Task <byte[]> LoadPrivateKeyAsync([NotNull] AppleGenerateClientSecretContext context) { if (context.Options.PrivateKeyBytes == null) { throw new ArgumentException( $"The {nameof(AppleAuthenticationOptions.PrivateKeyBytes)} option must be set to be able to load the Sign in with Apple private key.", nameof(AppleAuthenticationOptions.PrivateKeyBytes)); } return(await context.Options.PrivateKeyBytes(context.Options.KeyId)); }
/// <inheritdoc /> public override async Task <string> GenerateAsync([NotNull] AppleGenerateClientSecretContext context) { if (_clientSecret == null || _clock.UtcNow >= _expiresAt) { try { (_clientSecret, _expiresAt) = await GenerateNewSecretAsync(context); } catch (Exception ex) { _logger.LogError(ex, $"Failed to generate new client secret for the {context.Scheme.Name} authentication scheme."); throw; } } return(_clientSecret); }
/// <inheritdoc /> public override async Task <string> GenerateAsync([NotNull] AppleGenerateClientSecretContext context) { string key = CreateCacheKey(context.Options); return(await _cache.GetOrCreateAsync(key, async (entry) => { try { (string clientSecret, DateTimeOffset expiresAt) = await GenerateNewSecretAsync(context); entry.AbsoluteExpiration = expiresAt; return clientSecret; } catch (Exception ex) { Log.ClientSecretGenerationFailed(_logger, ex, context.Scheme.Name); throw; } })); }
/// <inheritdoc /> public override async Task <string> GenerateAsync([NotNull] AppleGenerateClientSecretContext context) { string key = CreateCacheKey(context.Options); return(await _cache.GetOrCreateAsync(key, async (entry) => { try { (string clientSecret, DateTimeOffset expiresAt) = await GenerateNewSecretAsync(context); entry.AbsoluteExpiration = expiresAt; return clientSecret; } catch (Exception ex) { _logger.LogError( ex, "Failed to generate new client secret for the {SchemeName} authentication scheme.", context.Scheme.Name); throw; } })); }
/// <summary> /// Invoked whenever the client secret needs to be generated. /// </summary> /// <param name="context">Contains information about the current request.</param> /// <returns> /// A <see cref="Task"/> representing the completed operation. /// </returns> public virtual async Task GenerateClientSecret([NotNull] AppleGenerateClientSecretContext context) => await OnGenerateClientSecret(context);
/// <summary> /// Generates a client secret for Sign in with Apple as an asynchronous operation. /// </summary> /// <param name="context">The context.</param> /// <returns> /// A <see cref="Task{TResult}"/> representing the asynchronous operation /// to generate a client secret for Sign in with Apple. /// </returns> public abstract Task <string> GenerateAsync(AppleGenerateClientSecretContext context);