public async Task ProcessSigninResponse_AdHocAuthorizationIsAutomaticallyCreated() { // Arrange var token = new OpenIddictToken(); var manager = CreateAuthorizationManager(instance => { instance.Setup(mock => mock.FindByIdAsync("1AF06AB2-A0FC-4E3D-86AF-E04DA8C7BE70", It.IsAny <CancellationToken>())) .ReturnsAsync(new OpenIddictAuthorization()); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny <CancellationToken>())) .ReturnsAsync(application); instance.Setup(mock => mock.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny <CancellationToken>())) .ReturnsAsync(true); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny <CancellationToken>())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Public); instance.Setup(mock => mock.GetIdAsync(application, It.IsAny <CancellationToken>())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); })); builder.Services.AddSingleton(CreateTokenManager(instance => { instance.Setup(mock => mock.CreateAsync(It.IsAny <OpenIddictTokenDescriptor>(), It.IsAny <CancellationToken>())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny <CancellationToken>())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); })); builder.Services.AddSingleton(manager); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(AuthorizationEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", RedirectUri = "http://www.fabrikam.com/path", ResponseType = OpenIdConnectConstants.ResponseTypes.Code, }); // Assert Assert.NotNull(response.Code); Mock.Get(manager).Verify(mock => mock.CreateAsync( It.Is <OpenIddictAuthorizationDescriptor>(descriptor => descriptor.ApplicationId == "3E228451-1555-46F7-A471-951EFBA23A56" && descriptor.Subject == "Bob le Magnifique" && descriptor.Type == OpenIddictConstants.AuthorizationTypes.AdHoc), It.IsAny <CancellationToken>()), Times.Once()); }
public async Task HandleTokenRequest_AuthorizationCodeIsAutomaticallyRevoked() { // Arrange var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme); identity.AddClaim(OpenIdConnectConstants.Claims.Subject, "Bob le Bricoleur"); var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); ticket.SetPresenters("Fabrikam"); ticket.SetTicketId("3E228451-1555-46F7-A471-951EFBA23A56"); ticket.SetUsage(OpenIdConnectConstants.Usages.AuthorizationCode); var format = new Mock <ISecureDataFormat <AuthenticationTicket> >(); format.Setup(mock => mock.Unprotect("SplxlOBeZQQYbYS6WxSbIA")) .Returns(ticket); var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny <CancellationToken>())) .ReturnsAsync(token); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny <CancellationToken>())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny <CancellationToken>())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Public); })); builder.Services.AddSingleton(manager); builder.Configure(options => options.AuthorizationCodeFormat = format.Object); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", Code = "SplxlOBeZQQYbYS6WxSbIA", GrantType = OpenIdConnectConstants.GrantTypes.AuthorizationCode, RedirectUri = "http://www.fabrikam.com/path" }); // Assert Mock.Get(manager).Verify(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny <CancellationToken>()), Times.Once()); Mock.Get(manager).Verify(mock => mock.RevokeAsync(token, It.IsAny <CancellationToken>()), Times.Once()); }
public async Task ProcessSigninResponse_ReturnsErrorResponseWhenExtendingLifetimeOfExistingTokenFailed() { // Arrange var ticket = new AuthenticationTicket( new ClaimsPrincipal(), new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); ticket.SetTokenId("60FFF7EA-F98E-437B-937E-5073CC313103"); ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.RefreshToken); ticket.SetScopes(OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.OfflineAccess); var format = new Mock <ISecureDataFormat <AuthenticationTicket> >(); format.Setup(mock => mock.Protect(It.IsAny <AuthenticationTicket>())) .Returns("8xLOxBtZp8"); format.Setup(mock => mock.Unprotect("8xLOxBtZp8")) .Returns(ticket); var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByIdAsync("60FFF7EA-F98E-437B-937E-5073CC313103", It.IsAny <CancellationToken>())) .ReturnsAsync(token); instance.Setup(mock => mock.IsRedeemedAsync(token, It.IsAny <CancellationToken>())) .ReturnsAsync(false); instance.Setup(mock => mock.IsValidAsync(token, It.IsAny <CancellationToken>())) .ReturnsAsync(true); instance.Setup(mock => mock.ExtendAsync(token, It.IsAny <DateTimeOffset?>(), It.IsAny <CancellationToken>())) .ThrowsAsync(new Exception()); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(manager); builder.Configure(options => { options.SystemClock = Mock.Of <ISystemClock>(mock => mock.UtcNow == new DateTimeOffset(2017, 01, 05, 00, 00, 00, TimeSpan.Zero)); options.RefreshTokenLifetime = TimeSpan.FromDays(10); options.RefreshTokenFormat = format.Object; }); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest { GrantType = OpenIdConnectConstants.GrantTypes.RefreshToken, RefreshToken = "8xLOxBtZp8" }); // Assert Assert.Equal(OpenIdConnectConstants.Errors.InvalidGrant, response.Error); Assert.Equal("The specified refresh token is no longer valid.", response.ErrorDescription); Mock.Get(manager).Verify(mock => mock.ExtendAsync(token, new DateTimeOffset(2017, 01, 15, 00, 00, 00, TimeSpan.Zero), It.IsAny <CancellationToken>()), Times.Once()); }
public async Task ProcessSigninResponse_ReturnsErrorResponseWhenRedeemingRefreshTokenFails() { // Arrange var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme); identity.AddClaim(OpenIdConnectConstants.Claims.Subject, "Bob le Bricoleur"); var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); ticket.SetTokenId("60FFF7EA-F98E-437B-937E-5073CC313103"); ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.RefreshToken); ticket.SetScopes(OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.OfflineAccess); var format = new Mock <ISecureDataFormat <AuthenticationTicket> >(); format.Setup(mock => mock.Protect(It.IsAny <AuthenticationTicket>())) .Returns("8xLOxBtZp8"); format.Setup(mock => mock.Unprotect("8xLOxBtZp8")) .Returns(ticket); var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByIdAsync("60FFF7EA-F98E-437B-937E-5073CC313103", It.IsAny <CancellationToken>())) .ReturnsAsync(token); instance.Setup(mock => mock.IsRedeemedAsync(token, It.IsAny <CancellationToken>())) .ReturnsAsync(false); instance.Setup(mock => mock.IsValidAsync(token, It.IsAny <CancellationToken>())) .ReturnsAsync(true); instance.Setup(mock => mock.RedeemAsync(token, It.IsAny <CancellationToken>())) .ThrowsAsync(new Exception()); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(manager); builder.UseRollingTokens(); builder.Configure(options => options.RefreshTokenFormat = format.Object); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest { GrantType = OpenIdConnectConstants.GrantTypes.RefreshToken, RefreshToken = "8xLOxBtZp8" }); // Assert Assert.Equal(OpenIdConnectConstants.Errors.InvalidGrant, response.Error); Assert.Equal("The specified authorization code is no longer valid.", response.ErrorDescription); Mock.Get(manager).Verify(mock => mock.FindByIdAsync("60FFF7EA-F98E-437B-937E-5073CC313103", It.IsAny <CancellationToken>()), Times.Exactly(2)); Mock.Get(manager).Verify(mock => mock.RedeemAsync(token, It.IsAny <CancellationToken>()), Times.Once()); }
public async Task ProcessSigninResponse_AuthenticationPropertiesAreAutomaticallyRestored() { // Arrange var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme); identity.AddClaim(OpenIdConnectConstants.Claims.Subject, "Bob le Bricoleur"); var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); ticket.SetTokenId("60FFF7EA-F98E-437B-937E-5073CC313103"); ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.RefreshToken); ticket.SetScopes(OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.OfflineAccess); ticket.SetProperty("custom_property_in_original_ticket", "original_value"); var format = new Mock <ISecureDataFormat <AuthenticationTicket> >(); format.Setup(mock => mock.Protect(It.IsAny <AuthenticationTicket>())) .Returns("8xLOxBtZp8"); format.Setup(mock => mock.Unprotect("8xLOxBtZp8")) .Returns(ticket); var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByIdAsync("60FFF7EA-F98E-437B-937E-5073CC313103", It.IsAny <CancellationToken>())) .ReturnsAsync(token); instance.Setup(mock => mock.IsRedeemedAsync(token, It.IsAny <CancellationToken>())) .ReturnsAsync(false); instance.Setup(mock => mock.IsValidAsync(token, It.IsAny <CancellationToken>())) .ReturnsAsync(true); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(manager); builder.UseRollingTokens(); builder.Configure(options => options.RefreshTokenFormat = format.Object); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest { GrantType = OpenIdConnectConstants.GrantTypes.RefreshToken, RefreshToken = "8xLOxBtZp8", ["do-not-flow-original-properties"] = true }); // Assert Assert.NotNull(response.IdToken); Assert.NotNull(response.RefreshToken); format.Verify(mock => mock.Protect( It.Is <AuthenticationTicket>(value => value.Properties.Items["custom_property_in_original_ticket"] == "original_value" && value.Properties.Items["custom_property_in_new_ticket"] == "new_value"))); }
public async Task DecryptToken_ReturnsValidResultForValidReferenceToken() { // Arrange var token = new OpenIddictToken(); var format = new Mock <ISecureDataFormat <AuthenticationTicket> >(); format.Setup(mock => mock.Unprotect("valid-reference-token-payload")) .Returns(delegate { var identity = new ClaimsIdentity(OpenIddictValidationDefaults.AuthenticationScheme); identity.AddClaim(new Claim(OAuthValidationConstants.Claims.Subject, "Fabrikam")); return(new AuthenticationTicket( new ClaimsPrincipal(identity), OpenIddictValidationDefaults.AuthenticationScheme)); }); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByReferenceIdAsync("valid-reference-token-id", It.IsAny <CancellationToken>())) .ReturnsAsync(token); instance.Setup(mock => mock.GetPayloadAsync(token, It.IsAny <CancellationToken>())) .Returns(new ValueTask <string>("valid-reference-token-payload")); instance.Setup(mock => mock.GetCreationDateAsync(token, It.IsAny <CancellationToken>())) .Returns(new ValueTask <DateTimeOffset?>(new DateTimeOffset(2018, 01, 01, 00, 00, 00, TimeSpan.Zero))); instance.Setup(mock => mock.GetExpirationDateAsync(token, It.IsAny <CancellationToken>())) .Returns(new ValueTask <DateTimeOffset?>(new DateTimeOffset(2918, 01, 01, 00, 00, 00, TimeSpan.Zero))); }); var server = CreateResourceServer(builder => { builder.Services.AddSingleton(manager); builder.Configure(options => options.AccessTokenFormat = format.Object); }); var client = server.CreateClient(); var request = new HttpRequestMessage(HttpMethod.Get, "/ticket"); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "valid-reference-token-id"); // Act var response = await client.SendAsync(request); var ticket = JObject.Parse(await response.Content.ReadAsStringAsync()); var properties = (from property in ticket.Value <JArray>("Properties") select new { Name = property.Value <string>("Name"), Value = property.Value <string>("Value") }).ToDictionary(property => property.Name, property => property.Value); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal( new DateTimeOffset(2018, 01, 01, 00, 00, 00, TimeSpan.Zero), DateTimeOffset.Parse(properties[".issued"], CultureInfo.InvariantCulture)); Assert.Equal( new DateTimeOffset(2918, 01, 01, 00, 00, 00, TimeSpan.Zero), DateTimeOffset.Parse(properties[".expires"], CultureInfo.InvariantCulture)); Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("valid-reference-token-id", It.IsAny <CancellationToken>()), Times.Once()); Mock.Get(manager).Verify(mock => mock.GetPayloadAsync(token, It.IsAny <CancellationToken>()), Times.Once()); Mock.Get(manager).Verify(mock => mock.GetCreationDateAsync(token, It.IsAny <CancellationToken>()), Times.Once()); Mock.Get(manager).Verify(mock => mock.GetExpirationDateAsync(token, It.IsAny <CancellationToken>()), Times.Once()); format.Verify(mock => mock.Unprotect("valid-reference-token-payload"), Times.Once()); }
public async Task HandleIntrospectionRequest_RequestIsRejectedWhenReferenceTokenIsInvalid() { // Arrange var identity = new ClaimsIdentity(OpenIddictServerDefaults.AuthenticationScheme); identity.AddClaim(OpenIdConnectConstants.Claims.Subject, "Bob le Bricoleur"); var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), OpenIddictServerDefaults.AuthenticationScheme); ticket.SetAudiences("Fabrikam"); ticket.SetProperty(OpenIddictConstants.Properties.InternalTokenId, "3E228451-1555-46F7-A471-951EFBA23A56"); ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.AccessToken); var format = new Mock <ISecureDataFormat <AuthenticationTicket> >(); format.Setup(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA")) .Returns(ticket); var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByReferenceIdAsync("QaTk2f6UPe9trKismGBJr0OIs0KqpvNrqRsJqGuJAAI", It.IsAny <CancellationToken>())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny <CancellationToken>())) .Returns(new ValueTask <string>("3E228451-1555-46F7-A471-951EFBA23A56")); instance.Setup(mock => mock.GetPayloadAsync(token, It.IsAny <CancellationToken>())) .Returns(new ValueTask <string>("2YotnFZFEjr1zCsicMWpAA")); instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny <CancellationToken>())) .ReturnsAsync(token); instance.Setup(mock => mock.IsValidAsync(token, It.IsAny <CancellationToken>())) .ReturnsAsync(false); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny <CancellationToken>())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny <CancellationToken>())) .Returns(new ValueTask <string>(OpenIddictConstants.ClientTypes.Confidential)); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny <CancellationToken>())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.Configure(options => options.AccessTokenFormat = format.Object); builder.UseReferenceTokens(); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "QaTk2f6UPe9trKismGBJr0OIs0KqpvNrqRsJqGuJAAI" }); // Assert Assert.Single(response.GetParameters()); Assert.False((bool)response[OpenIdConnectConstants.Claims.Active]); Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("QaTk2f6UPe9trKismGBJr0OIs0KqpvNrqRsJqGuJAAI", It.IsAny <CancellationToken>()), Times.Once()); Mock.Get(manager).Verify(mock => mock.IsValidAsync(token, It.IsAny <CancellationToken>()), Times.Once()); }