public static async Task GenerateAsync_Caches_Jwt_Until_Expired() { // Arrange var options = new AppleAuthenticationOptions() { ClientId = "my-client-id", ClientSecretExpiresAfter = TimeSpan.FromSeconds(2), KeyId = "my-key-id", TeamId = "my-team-id", PrivateKeyBytes = (keyId) => TestKeys.GetPrivateKeyBytesAsync(), }; await GenerateTokenAsync(options, async (generator, context) => { // Act string token1 = await generator.GenerateAsync(context); string token2 = await generator.GenerateAsync(context); // Assert token2.ShouldBe(token1); // Act await Task.Delay(options.ClientSecretExpiresAfter.Add(options.ClientSecretExpiresAfter)); string token3 = await generator.GenerateAsync(context); // Assert token3.ShouldNotBe(token1); }); }
// Arrange static void Configure(AppleAuthenticationOptions options) { options.ClientId = "my-client-id"; options.ClientSecretExpiresAfter = TimeSpan.FromMinutes(1); options.KeyId = "my-key-id"; options.TeamId = "my-team-id"; options.PrivateKeyBytes = (_) => TestKeys.GetPrivateKeyBytesAsync(); }
public static void Validate_Throws_If_ClientSecret_Is_Null_With_No_Secret_Generation() { // Arrange var options = new AppleAuthenticationOptions() { ClientId = "my-client-id", ClientSecret = null, }; // Act and Assert Assert.Throws <ArgumentException>("ClientSecret", () => options.Validate()); }
public static void Validate_Throws_If_CallbackPath_Is_Null() { // Arrange var options = new AppleAuthenticationOptions() { ClientId = "my-client-id", GenerateClientSecret = true, CallbackPath = null, }; // Act and Assert Assert.Throws <ArgumentException>("CallbackPath", () => options.Validate()); }
public static void Validate_Throws_If_AuthorizationEndpoint_Is_Null() { // Arrange var options = new AppleAuthenticationOptions() { ClientId = "my-client-id", GenerateClientSecret = true, AuthorizationEndpoint = null, }; // Act and Assert Assert.Throws <ArgumentException>("AuthorizationEndpoint", () => options.Validate()); }
public static void Validate_Throws_If_PublicKeyEndpoint_Is_Null_With_Token_Validation() { // Arrange var options = new AppleAuthenticationOptions() { ClientId = "my-client-id", ClientSecret = "my-client-secret", PublicKeyEndpoint = null, }; // Act and Assert Assert.Throws <ArgumentException>("PublicKeyEndpoint", () => options.Validate()); }
public static void Validate_Throws_If_TeamId_Is_Null_With_Secret_Generation() { // Arrange var options = new AppleAuthenticationOptions() { ClientId = "my-client-id", GenerateClientSecret = true, KeyId = "my-key-id", TeamId = null, }; // Act and Assert Assert.Throws <ArgumentException>("TeamId", () => options.Validate()); }
public static void Validate_Throws_If_ClientSecretExpiresAfter_Is_Zero_With_Secret_Generation() { // Arrange var options = new AppleAuthenticationOptions() { ClientId = "my-client-id", GenerateClientSecret = true, KeyId = "my-key-id", TeamId = "my-team-id", ClientSecretExpiresAfter = TimeSpan.Zero, }; // Act and Assert Assert.Throws <ArgumentOutOfRangeException>("ClientSecretExpiresAfter", () => options.Validate()); }
public static async Task GenerateAsync_Generates_Valid_Signed_Jwt() { // Arrange var options = new AppleAuthenticationOptions() { ClientId = "my-client-id", ClientSecretExpiresAfter = TimeSpan.FromMinutes(1), KeyId = "my-key-id", TeamId = "my-team-id", PrivateKeyBytes = (keyId) => TestKeys.GetPrivateKeyBytesAsync(), }; await GenerateTokenAsync(options, async (generator, context) => { var utcNow = DateTimeOffset.UtcNow; // Act string token = await generator.GenerateAsync(context); // Assert token.ShouldNotBeNullOrWhiteSpace(); token.Count((c) => c == '.').ShouldBe(2); // Format: "{header}.{body}.{signature}" // Act var validator = new JwtSecurityTokenHandler(); var securityToken = validator.ReadJwtToken(token); // Assert - See https://developer.apple.com/documentation/signinwithapplerestapi/generate_and_validate_tokens securityToken.ShouldNotBeNull(); securityToken.Header.ShouldNotBeNull(); securityToken.Header.ShouldContainKeyAndValue("alg", "ES256"); securityToken.Header.ShouldContainKeyAndValue("kid", "my-key-id"); securityToken.Payload.ShouldNotBeNull(); securityToken.Payload.ShouldContainKey("exp"); securityToken.Payload.ShouldContainKey("iat"); securityToken.Payload.ShouldContainKeyAndValue("aud", "https://appleid.apple.com"); securityToken.Payload.ShouldContainKeyAndValue("iss", "my-team-id"); securityToken.Payload.ShouldContainKeyAndValue("sub", "my-client-id"); securityToken.Payload.Iat.HasValue.ShouldBeTrue(); securityToken.Payload.Exp.HasValue.ShouldBeTrue(); ((long)securityToken.Payload.Iat !.Value).ShouldBeGreaterThanOrEqualTo(utcNow.ToUnixTimeSeconds()); ((long)securityToken.Payload.Exp !.Value).ShouldBeGreaterThanOrEqualTo(utcNow.AddSeconds(60).ToUnixTimeSeconds()); ((long)securityToken.Payload.Exp.Value).ShouldBeLessThanOrEqualTo(utcNow.AddSeconds(70).ToUnixTimeSeconds()); }); }
private static async Task GenerateTokenAsync( AppleAuthenticationOptions options, Func <AppleClientSecretGenerator, AppleGenerateClientSecretContext, Task> actAndAssert) { // Arrange var builder = new WebHostBuilder() .Configure((app) => app.UseAuthentication()) .ConfigureServices((services) => { services.AddAuthentication() .AddApple(); }); using var host = builder.Build(); var httpContext = new DefaultHttpContext(); var scheme = new AuthenticationScheme("Apple", "Apple", typeof(AppleAuthenticationHandler)); var context = new AppleGenerateClientSecretContext(httpContext, scheme, options); var generator = host.Services.GetRequiredService <AppleClientSecretGenerator>(); await actAndAssert(generator, context); }
internal AppleEmailClaimAction(AppleAuthenticationOptions options) : base(ClaimTypes.Email, ClaimValueTypes.String) { _options = options; }