/* * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) * See https://github.com/openiddict/openiddict-core for more information concerning * the license and the contributors participating to this project. */ using System; using System.Security.Claims; using System.Threading; using System.Threading.Tasks; using AspNet.Security.OpenIdConnect.Client; using AspNet.Security.OpenIdConnect.Extensions; using AspNet.Security.OpenIdConnect.Primitives; using AspNet.Security.OpenIdConnect.Server; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Authentication; using Microsoft.Extensions.DependencyInjection; using Moq; using OpenIddict.Core; using OpenIddict.Models; using Xunit; namespace OpenIddict.Tests { public partial class OpenIddictProviderTests { [Fact] public async Task DeserializeAccessToken_ReturnsNullForMalformedReferenceToken() { // Arrange var format = new Mock>(); var manager = CreateTokenManager(); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); builder.Configure(options => options.AccessTokenFormat = format.Object); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "2YotnFZFEjr1zCsicMWpAA", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.AccessToken }); // Assert Assert.Single(response.GetParameters()); Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]); format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Never()); Mock.Get(manager).Verify(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny()), Times.Never()); } [Fact] public async Task DeserializeAccessToken_AccessTokenIsNotRetrievedFromDatabaseWhenReferenceTokensAreDisabled() { // 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("3E228451-1555-46F7-A471-951EFBA23A56"); ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.RefreshToken); var format = new Mock>(); format.Setup(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA")) .Returns(ticket); var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.IsValidAsync(token, It.IsAny())) .ReturnsAsync(true); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.Configure(options => options.RefreshTokenFormat = format.Object); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "2YotnFZFEjr1zCsicMWpAA", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.AccessToken }); // Assert Assert.True((bool) response[OpenIdConnectConstants.Claims.Active]); format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once()); Mock.Get(manager).Verify(mock => mock.FindByHashAsync(It.IsAny(), It.IsAny()), Times.Never()); } [Fact] public async Task DeserializeAccessToken_ReturnsNullForMissingTokenIdentifier() { // Arrange var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync(value: null); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.AccessToken }); // Assert Assert.Single(response.GetParameters()); Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]); Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce()); } [Fact] public async Task DeserializeAccessToken_ReturnsNullForMissingTokenCiphertext() { // Arrange var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny())) .ReturnsAsync(value: null); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.AccessToken }); // Assert Assert.Single(response.GetParameters()); Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]); Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce()); } [Fact] public async Task DeserializeAccessToken_ReturnsNullForInvalidTokenCiphertext() { // Arrange var format = new Mock>(); format.Setup(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA")) .Returns(value: null); var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny())) .ReturnsAsync("2YotnFZFEjr1zCsicMWpAA"); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); builder.Configure(options => options.AccessTokenFormat = format.Object); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.AccessToken }); // Assert Assert.Single(response.GetParameters()); Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]); Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce()); format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once()); } [Fact] public async Task DeserializeAccessToken_ReturnsExpectedToken() { // 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("3E228451-1555-46F7-A471-951EFBA23A56"); ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.RefreshToken); var format = new Mock>(); format.Setup(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA")) .Returns(ticket); var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny())) .ReturnsAsync("2YotnFZFEjr1zCsicMWpAA"); instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.IsValidAsync(token, It.IsAny())) .ReturnsAsync(true); instance.Setup(mock => mock.GetCreationDateAsync(token, It.IsAny())) .ReturnsAsync(new DateTimeOffset(2017, 01, 01, 00, 00, 00, TimeSpan.Zero)); instance.Setup(mock => mock.GetExpirationDateAsync(token, It.IsAny())) .ReturnsAsync(new DateTimeOffset(2017, 01, 10, 00, 00, 00, TimeSpan.Zero)); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); builder.Configure(options => { options.SystemClock = Mock.Of(mock => mock.UtcNow == new DateTimeOffset(2017, 01, 05, 00, 00, 00, TimeSpan.Zero)); options.AccessTokenFormat = format.Object; }); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.AccessToken }); // Assert Assert.True((bool) response[OpenIdConnectConstants.Claims.Active]); Assert.Equal("3E228451-1555-46F7-A471-951EFBA23A56", response[OpenIdConnectConstants.Claims.JwtId]); Assert.Equal(1483228800, (long) response[OpenIdConnectConstants.Claims.IssuedAt]); Assert.Equal(1484006400, (long) response[OpenIdConnectConstants.Claims.ExpiresAt]); Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.Once()); Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.Once()); format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once()); } [Fact] public async Task DeserializeAuthorizationCode_ReturnsNullForMalformedReferenceToken() { // Arrange var format = new Mock>(); var manager = CreateTokenManager(); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); builder.Configure(options => options.AuthorizationCodeFormat = format.Object); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "2YotnFZFEjr1zCsicMWpAA", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.AuthorizationCode }); // Assert Assert.Single(response.GetParameters()); Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]); format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Never()); Mock.Get(manager).Verify(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny()), Times.Never()); } [Fact] public async Task DeserializeAuthorizationCode_AuthorizationCodeIsNotRetrievedFromDatabaseWhenReferenceTokensAreDisabled() { // 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("3E228451-1555-46F7-A471-951EFBA23A56"); ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.RefreshToken); var format = new Mock>(); format.Setup(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA")) .Returns(ticket); var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.IsValidAsync(token, It.IsAny())) .ReturnsAsync(true); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.Configure(options => options.RefreshTokenFormat = format.Object); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "2YotnFZFEjr1zCsicMWpAA", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.AuthorizationCode }); // Assert Assert.True((bool) response[OpenIdConnectConstants.Claims.Active]); format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once()); Mock.Get(manager).Verify(mock => mock.FindByHashAsync(It.IsAny(), It.IsAny()), Times.Never()); } [Fact] public async Task DeserializeAuthorizationCode_ReturnsNullForMissingTokenIdentifier() { // Arrange var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync(value: null); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.AuthorizationCode }); // Assert Assert.Single(response.GetParameters()); Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]); Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce()); } [Fact] public async Task DeserializeAuthorizationCode_ReturnsNullForMissingTokenCiphertext() { // Arrange var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny())) .ReturnsAsync(value: null); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.AuthorizationCode }); // Assert Assert.Single(response.GetParameters()); Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]); Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce()); } [Fact] public async Task DeserializeAuthorizationCode_ReturnsNullForInvalidTokenCiphertext() { // Arrange var format = new Mock>(); format.Setup(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA")) .Returns(value: null); var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny())) .ReturnsAsync("2YotnFZFEjr1zCsicMWpAA"); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); builder.Configure(options => options.AuthorizationCodeFormat = format.Object); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.AuthorizationCode }); // Assert Assert.Single(response.GetParameters()); Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]); Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce()); format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once()); } [Fact] public async Task DeserializeAuthorizationCode_ReturnsExpectedToken() { // 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("3E228451-1555-46F7-A471-951EFBA23A56"); ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.RefreshToken); var format = new Mock>(); format.Setup(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA")) .Returns(ticket); var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny())) .ReturnsAsync("2YotnFZFEjr1zCsicMWpAA"); instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.IsValidAsync(token, It.IsAny())) .ReturnsAsync(true); instance.Setup(mock => mock.GetCreationDateAsync(token, It.IsAny())) .ReturnsAsync(new DateTimeOffset(2017, 01, 01, 00, 00, 00, TimeSpan.Zero)); instance.Setup(mock => mock.GetExpirationDateAsync(token, It.IsAny())) .ReturnsAsync(new DateTimeOffset(2017, 01, 10, 00, 00, 00, TimeSpan.Zero)); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); builder.Configure(options => { options.SystemClock = Mock.Of(mock => mock.UtcNow == new DateTimeOffset(2017, 01, 05, 00, 00, 00, TimeSpan.Zero)); options.AuthorizationCodeFormat = format.Object; }); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.AuthorizationCode }); // Assert Assert.True((bool) response[OpenIdConnectConstants.Claims.Active]); Assert.Equal("3E228451-1555-46F7-A471-951EFBA23A56", response[OpenIdConnectConstants.Claims.JwtId]); Assert.Equal(1483228800, (long) response[OpenIdConnectConstants.Claims.IssuedAt]); Assert.Equal(1484006400, (long) response[OpenIdConnectConstants.Claims.ExpiresAt]); Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.Once()); Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.Once()); format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once()); } [Fact] public async Task DeserializeRefreshToken_ReturnsNullForMalformedReferenceToken() { // Arrange var format = new Mock>(); var manager = CreateTokenManager(); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); builder.Configure(options => options.RefreshTokenFormat = format.Object); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "2YotnFZFEjr1zCsicMWpAA", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.RefreshToken }); // Assert Assert.Single(response.GetParameters()); Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]); format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Never()); Mock.Get(manager).Verify(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny()), Times.Never()); } [Fact] public async Task DeserializeRefreshToken_RefreshTokenIsNotRetrievedFromDatabaseWhenReferenceTokensAreDisabled() { // 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("3E228451-1555-46F7-A471-951EFBA23A56"); ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.RefreshToken); var format = new Mock>(); format.Setup(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA")) .Returns(ticket); var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.IsValidAsync(token, It.IsAny())) .ReturnsAsync(true); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.Configure(options => options.RefreshTokenFormat = format.Object); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "2YotnFZFEjr1zCsicMWpAA", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.RefreshToken }); // Assert Assert.True((bool) response[OpenIdConnectConstants.Claims.Active]); format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once()); Mock.Get(manager).Verify(mock => mock.FindByHashAsync(It.IsAny(), It.IsAny()), Times.Never()); } [Fact] public async Task DeserializeRefreshToken_ReturnsNullForMissingTokenIdentifier() { // Arrange var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync(value: null); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.RefreshToken }); // Assert Assert.Single(response.GetParameters()); Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]); Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce()); } [Fact] public async Task DeserializeRefreshToken_ReturnsNullForMissingTokenCiphertext() { // Arrange var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny())) .ReturnsAsync(value: null); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.RefreshToken }); // Assert Assert.Single(response.GetParameters()); Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]); Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce()); } [Fact] public async Task DeserializeRefreshToken_ReturnsNullForInvalidTokenCiphertext() { // Arrange var format = new Mock>(); format.Setup(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA")) .Returns(value: null); var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny())) .ReturnsAsync("2YotnFZFEjr1zCsicMWpAA"); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); builder.Configure(options => options.RefreshTokenFormat = format.Object); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.RefreshToken }); // Assert Assert.Single(response.GetParameters()); Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]); Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce()); format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once()); } [Fact] public async Task DeserializeRefreshToken_ReturnsExpectedToken() { // 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("3E228451-1555-46F7-A471-951EFBA23A56"); ticket.SetTokenUsage(OpenIdConnectConstants.TokenUsages.RefreshToken); var format = new Mock>(); format.Setup(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA")) .Returns(ticket); var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny())) .ReturnsAsync("2YotnFZFEjr1zCsicMWpAA"); instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.IsValidAsync(token, It.IsAny())) .ReturnsAsync(true); instance.Setup(mock => mock.GetCreationDateAsync(token, It.IsAny())) .ReturnsAsync(new DateTimeOffset(2017, 01, 01, 00, 00, 00, TimeSpan.Zero)); instance.Setup(mock => mock.GetExpirationDateAsync(token, It.IsAny())) .ReturnsAsync(new DateTimeOffset(2017, 01, 10, 00, 00, 00, TimeSpan.Zero)); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Confidential); instance.Setup(mock => mock.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); builder.Configure(options => { options.SystemClock = Mock.Of(mock => mock.UtcNow == new DateTimeOffset(2017, 01, 05, 00, 00, 00, TimeSpan.Zero)); options.RefreshTokenFormat = format.Object; }); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", Token = "HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.RefreshToken }); // Assert Assert.True((bool) response[OpenIdConnectConstants.Claims.Active]); Assert.Equal("3E228451-1555-46F7-A471-951EFBA23A56", response[OpenIdConnectConstants.Claims.JwtId]); Assert.Equal(1483228800, (long) response[OpenIdConnectConstants.Claims.IssuedAt]); Assert.Equal(1484006400, (long) response[OpenIdConnectConstants.Claims.ExpiresAt]); Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.Once()); Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.Once()); format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once()); } [Fact] public async Task SerializeAccessToken_AccessTokenIsNotPersistedWhenReferenceTokensAreDisabled() { // Arrange var manager = CreateTokenManager(); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(manager); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest { GrantType = OpenIdConnectConstants.GrantTypes.Password, Username = "johndoe", Password = "A3ddj3w", Scope = OpenIdConnectConstants.Scopes.OfflineAccess }); // Assert Assert.NotNull(response.AccessToken); Mock.Get(manager).Verify(mock => mock.CreateAsync( It.Is(descriptor => descriptor.Subject == "Bob le Magnifique" && descriptor.Type == OpenIdConnectConstants.TokenTypeHints.AccessToken), It.IsAny()), Times.Never()); } [Fact] public async Task SerializeAccessToken_ReferenceAccessTokenIsCorrectlyPersisted() { // Arrange var token = new OpenIddictToken { CreationDate = new DateTimeOffset(2017, 01, 02, 00, 00, 00, TimeSpan.Zero), ExpirationDate = new DateTimeOffset(2017, 01, 01, 00, 00, 00, TimeSpan.Zero) }; var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.CreateAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); builder.Configure(options => { options.SystemClock = Mock.Of(mock => mock.UtcNow == token.CreationDate.Value); options.AccessTokenLifetime = token.ExpirationDate.Value - token.CreationDate.Value; }); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest { GrantType = OpenIdConnectConstants.GrantTypes.Password, Username = "johndoe", Password = "A3ddj3w", Scope = OpenIdConnectConstants.Scopes.OfflineAccess }); // Assert Assert.NotNull(response.AccessToken); Mock.Get(manager).Verify(mock => mock.CreateAsync( It.Is(descriptor => descriptor.Ciphertext != null && descriptor.Hash != null && descriptor.ExpirationDate == token.ExpirationDate && descriptor.CreationDate == token.CreationDate && descriptor.Subject == "Bob le Magnifique" && descriptor.Type == OpenIdConnectConstants.TokenTypeHints.AccessToken), It.IsAny()), Times.Once()); } [Fact] public async Task SerializeAccessToken_ClientApplicationIsAutomaticallyAttached() { // Arrange var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.CreateAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Public); instance.Setup(mock => mock.GetIdAsync(application, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", GrantType = OpenIdConnectConstants.GrantTypes.Password, Username = "johndoe", Password = "A3ddj3w", Scope = OpenIdConnectConstants.Scopes.OfflineAccess }); // Assert Assert.NotNull(response.AccessToken); Mock.Get(manager).Verify(mock => mock.CreateAsync( It.Is(descriptor => descriptor.ApplicationId == "3E228451-1555-46F7-A471-951EFBA23A56" && descriptor.Subject == "Bob le Magnifique" && descriptor.Type == OpenIdConnectConstants.TokenTypeHints.AccessToken), It.IsAny()), Times.Once()); } [Fact] public async Task SerializeAccessToken_AuthorizationIsAutomaticallyAttached() { // Arrange var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.CreateAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateAuthorizationManager(instance => { instance.Setup(mock => mock.FindByIdAsync("1AF06AB2-A0FC-4E3D-86AF-E04DA8C7BE70", It.IsAny())) .ReturnsAsync(new OpenIddictAuthorization()); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest { GrantType = OpenIdConnectConstants.GrantTypes.Password, Username = "johndoe", Password = "A3ddj3w", Scope = OpenIdConnectConstants.Scopes.OfflineAccess, ["attach-authorization"] = true }); // Assert Assert.NotNull(response.AccessToken); Mock.Get(manager).Verify(mock => mock.CreateAsync( It.Is(descriptor => descriptor.AuthorizationId == "1AF06AB2-A0FC-4E3D-86AF-E04DA8C7BE70" && descriptor.Subject == "Bob le Magnifique" && descriptor.Type == OpenIdConnectConstants.TokenTypeHints.AccessToken), It.IsAny()), Times.Once()); } [Fact] public async Task SerializeAuthorizationCode_AuthorizationCodeIsNotPersistedWhenRevocationIsDisabled() { // Arrange var manager = CreateTokenManager(); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny())) .ReturnsAsync(true); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Public); })); builder.Services.AddSingleton(manager); builder.Configure(options => options.RevocationEndpointPath = PathString.Empty); builder.DisableTokenRevocation(); builder.DisableSlidingExpiration(); }); 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.IsAny(), It.IsAny()), Times.Never()); } [Fact] public async Task SerializeAuthorizationCode_AuthorizationCodeIsCorrectlyPersisted() { // Arrange var token = new OpenIddictToken { CreationDate = new DateTimeOffset(2017, 01, 01, 00, 00, 00, TimeSpan.Zero), ExpirationDate = new DateTimeOffset(2017, 01, 02, 00, 00, 00, TimeSpan.Zero) }; var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.CreateAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny())) .ReturnsAsync(true); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Public); instance.Setup(mock => mock.GetIdAsync(application, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); })); builder.Services.AddSingleton(manager); builder.Configure(options => { options.SystemClock = Mock.Of(mock => mock.UtcNow == token.CreationDate.Value); options.AuthorizationCodeLifetime = token.ExpirationDate.Value - token.CreationDate.Value; }); }); 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(descriptor => descriptor.Ciphertext == null && descriptor.Hash == null && descriptor.ExpirationDate == token.ExpirationDate && descriptor.CreationDate == token.CreationDate && descriptor.Subject == "Bob le Magnifique" && descriptor.Type == OpenIdConnectConstants.TokenTypeHints.AuthorizationCode), It.IsAny()), Times.Once()); } [Fact] public async Task SerializeAuthorizationCode_ReferenceAuthorizationCodeIsCorrectlyPersisted() { // Arrange var token = new OpenIddictToken { CreationDate = new DateTimeOffset(2017, 01, 01, 00, 00, 00, TimeSpan.Zero), ExpirationDate = new DateTimeOffset(2017, 01, 02, 00, 00, 00, TimeSpan.Zero) }; var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.CreateAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny())) .ReturnsAsync(true); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Public); instance.Setup(mock => mock.GetIdAsync(application, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); })); builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); builder.Configure(options => { options.SystemClock = Mock.Of(mock => mock.UtcNow == token.CreationDate.Value); options.AuthorizationCodeLifetime = token.ExpirationDate.Value - token.CreationDate.Value; }); }); 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(descriptor => descriptor.Ciphertext != null && descriptor.Hash != null && descriptor.ExpirationDate == token.ExpirationDate && descriptor.CreationDate == token.CreationDate && descriptor.Subject == "Bob le Magnifique" && descriptor.Type == OpenIdConnectConstants.TokenTypeHints.AuthorizationCode), It.IsAny()), Times.Once()); } [Fact] public async Task SerializeAuthorizationCode_ClientApplicationIsAutomaticallyAttached() { // Arrange var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.CreateAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny())) .ReturnsAsync(true); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Public); instance.Setup(mock => mock.GetIdAsync(application, It.IsAny())) .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(descriptor => descriptor.ApplicationId == "3E228451-1555-46F7-A471-951EFBA23A56" && descriptor.Subject == "Bob le Magnifique" && descriptor.Type == OpenIdConnectConstants.TokenTypeHints.AuthorizationCode), It.IsAny()), Times.Once()); } [Fact] public async Task SerializeAuthorizationCode_AuthorizationIsAutomaticallyAttached() { // Arrange var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.CreateAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny())) .ReturnsAsync(true); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Public); instance.Setup(mock => mock.GetIdAsync(application, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); })); builder.Services.AddSingleton(CreateAuthorizationManager(instance => { instance.Setup(mock => mock.FindByIdAsync("1AF06AB2-A0FC-4E3D-86AF-E04DA8C7BE70", It.IsAny())) .ReturnsAsync(new OpenIddictAuthorization()); })); 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, ["attach-authorization"] = true }); // Assert Assert.NotNull(response.Code); Mock.Get(manager).Verify(mock => mock.CreateAsync( It.Is(descriptor => descriptor.ApplicationId == "3E228451-1555-46F7-A471-951EFBA23A56" && descriptor.AuthorizationId == "1AF06AB2-A0FC-4E3D-86AF-E04DA8C7BE70" && descriptor.Subject == "Bob le Magnifique" && descriptor.Type == OpenIdConnectConstants.TokenTypeHints.AuthorizationCode), It.IsAny()), Times.Once()); } [Fact] public async Task SerializeRefreshToken_ExpirationDateIsFixedWhenSlidingExpirationIsDisabled() { // 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>(); format.Setup(mock => mock.Protect(It.IsAny())) .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())) .ReturnsAsync(token); instance.Setup(mock => mock.IsRedeemedAsync(token, It.IsAny())) .ReturnsAsync(false); instance.Setup(mock => mock.IsValidAsync(token, It.IsAny())) .ReturnsAsync(true); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(manager); builder.DisableSlidingExpiration(); builder.UseRollingTokens(); builder.Configure(options => { options.SystemClock = Mock.Of(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.NotNull(response.RefreshToken); Mock.Get(manager).Verify(mock => mock.ExtendAsync(token, new DateTimeOffset(2017, 01, 10, 00, 00, 00, TimeSpan.Zero), It.IsAny()), Times.Never()); } [Fact] public async Task SerializeRefreshToken_RefreshTokenIsNotPersistedWhenRevocationIsDisabled() { // Arrange var manager = CreateTokenManager(); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(manager); builder.Configure(options => options.RevocationEndpointPath = PathString.Empty); builder.DisableTokenRevocation(); builder.DisableSlidingExpiration(); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest { GrantType = OpenIdConnectConstants.GrantTypes.Password, Username = "johndoe", Password = "A3ddj3w", Scope = OpenIdConnectConstants.Scopes.OfflineAccess }); // Assert Assert.NotNull(response.RefreshToken); Mock.Get(manager).Verify(mock => mock.CreateAsync( It.IsAny(), It.IsAny()), Times.Never()); } [Fact] public async Task SerializeRefreshToken_RefreshTokenIsCorrectlyPersisted() { // Arrange var token = new OpenIddictToken { CreationDate = new DateTimeOffset(2017, 01, 01, 00, 00, 00, TimeSpan.Zero), ExpirationDate = new DateTimeOffset(2017, 01, 02, 00, 00, 00, TimeSpan.Zero) }; var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.CreateAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(manager); builder.Configure(options => { options.SystemClock = Mock.Of(mock => mock.UtcNow == token.CreationDate.Value); options.RefreshTokenLifetime = token.ExpirationDate.Value - token.CreationDate.Value; }); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest { GrantType = OpenIdConnectConstants.GrantTypes.Password, Username = "johndoe", Password = "A3ddj3w", Scope = OpenIdConnectConstants.Scopes.OfflineAccess }); // Assert Assert.NotNull(response.RefreshToken); Mock.Get(manager).Verify(mock => mock.CreateAsync( It.Is(descriptor => descriptor.Ciphertext == null && descriptor.Hash == null && descriptor.ExpirationDate == token.ExpirationDate && descriptor.CreationDate == token.CreationDate && descriptor.Subject == "Bob le Magnifique" && descriptor.Type == OpenIdConnectConstants.TokenTypeHints.RefreshToken), It.IsAny()), Times.Once()); } [Fact] public async Task SerializeRefreshToken_ReferenceRefreshTokenIsCorrectlyPersisted() { // Arrange var token = new OpenIddictToken { CreationDate = new DateTimeOffset(2017, 01, 01, 00, 00, 00, TimeSpan.Zero), ExpirationDate = new DateTimeOffset(2017, 01, 02, 00, 00, 00, TimeSpan.Zero) }; var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.CreateAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(manager); builder.UseReferenceTokens(); builder.Configure(options => { options.SystemClock = Mock.Of(mock => mock.UtcNow == token.CreationDate.Value); options.RefreshTokenLifetime = token.ExpirationDate.Value - token.CreationDate.Value; }); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest { GrantType = OpenIdConnectConstants.GrantTypes.Password, Username = "johndoe", Password = "A3ddj3w", Scope = OpenIdConnectConstants.Scopes.OfflineAccess }); // Assert Assert.NotNull(response.RefreshToken); Mock.Get(manager).Verify(mock => mock.CreateAsync( It.Is(descriptor => descriptor.Ciphertext != null && descriptor.Hash != null && descriptor.ExpirationDate == token.ExpirationDate && descriptor.CreationDate == token.CreationDate && descriptor.Subject == "Bob le Magnifique" && descriptor.Type == OpenIdConnectConstants.TokenTypeHints.RefreshToken), It.IsAny()), Times.Once()); } [Fact] public async Task SerializeRefreshToken_ClientApplicationIsAutomaticallyAttached() { // Arrange var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.CreateAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { var application = new OpenIddictApplication(); instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny())) .ReturnsAsync(application); instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny())) .ReturnsAsync(OpenIddictConstants.ClientTypes.Public); instance.Setup(mock => mock.GetIdAsync(application, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); })); builder.Services.AddSingleton(manager); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", GrantType = OpenIdConnectConstants.GrantTypes.Password, Username = "johndoe", Password = "A3ddj3w", Scope = OpenIdConnectConstants.Scopes.OfflineAccess }); // Assert Assert.NotNull(response.RefreshToken); Mock.Get(manager).Verify(mock => mock.CreateAsync( It.Is(descriptor => descriptor.ApplicationId == "3E228451-1555-46F7-A471-951EFBA23A56" && descriptor.Subject == "Bob le Magnifique" && descriptor.Type == OpenIdConnectConstants.TokenTypeHints.RefreshToken), It.IsAny()), Times.Once()); } [Fact] public async Task SerializeRefreshToken_AuthorizationIsAutomaticallyAttached() { // Arrange var token = new OpenIddictToken(); var manager = CreateTokenManager(instance => { instance.Setup(mock => mock.CreateAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(token); instance.Setup(mock => mock.GetIdAsync(token, It.IsAny())) .ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56"); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateAuthorizationManager(instance => { instance.Setup(mock => mock.FindByIdAsync("1AF06AB2-A0FC-4E3D-86AF-E04DA8C7BE70", It.IsAny())) .ReturnsAsync(new OpenIddictAuthorization()); })); builder.Services.AddSingleton(manager); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest { GrantType = OpenIdConnectConstants.GrantTypes.Password, Username = "johndoe", Password = "A3ddj3w", Scope = OpenIdConnectConstants.Scopes.OfflineAccess, ["attach-authorization"] = true }); // Assert Assert.NotNull(response.RefreshToken); Mock.Get(manager).Verify(mock => mock.CreateAsync( It.Is(descriptor => descriptor.AuthorizationId == "1AF06AB2-A0FC-4E3D-86AF-E04DA8C7BE70" && descriptor.Subject == "Bob le Magnifique" && descriptor.Type == OpenIdConnectConstants.TokenTypeHints.RefreshToken), It.IsAny()), Times.Once()); } } }