diff --git a/samples/Mvc.Server/Controllers/AuthorizationController.cs b/samples/Mvc.Server/Controllers/AuthorizationController.cs index e86f0da6..464b9ada 100644 --- a/samples/Mvc.Server/Controllers/AuthorizationController.cs +++ b/samples/Mvc.Server/Controllers/AuthorizationController.cs @@ -112,7 +112,7 @@ namespace Mvc.Server { } #endregion - #region Password and refresh token flows + #region Password, authorization code and refresh token flows // Note: to support non-interactive flows like password, // you must provide your own token endpoint action: @@ -173,17 +173,17 @@ namespace Mvc.Server { return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme); } - else if (request.IsRefreshTokenGrantType()) { - // Retrieve the claims principal stored in the refresh token. + else if (request.IsAuthorizationCodeGrantType() || request.IsRefreshTokenGrantType()) { + // Retrieve the claims principal stored in the authorization code/refresh token. var info = await HttpContext.Authentication.GetAuthenticateInfoAsync( OpenIdConnectServerDefaults.AuthenticationScheme); - // Retrieve the user profile corresponding to the refresh token. + // Retrieve the user profile corresponding to the authorization code/refresh token. var user = await _userManager.GetUserAsync(info.Principal); if (user == null) { return BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidGrant, - ErrorDescription = "The refresh token is no longer valid." + ErrorDescription = "The token is no longer valid." }); } @@ -195,8 +195,8 @@ namespace Mvc.Server { }); } - // Create a new authentication ticket, but reuse the properties stored - // in the refresh token, including the scopes originally granted. + // Create a new authentication ticket, but reuse the properties stored in the + // authorization code/refresh token, including the scopes originally granted. var ticket = await CreateTicketAsync(request, user, info.Properties); return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme); @@ -232,7 +232,7 @@ namespace Mvc.Server { var ticket = new AuthenticationTicket(principal, properties, OpenIdConnectServerDefaults.AuthenticationScheme); - if (!request.IsRefreshTokenGrantType()) { + if (!request.IsAuthorizationCodeGrantType() && !request.IsRefreshTokenGrantType()) { // Set the list of scopes granted to the client application. // Note: the offline_access scope must be granted // to allow OpenIddict to return a refresh token. diff --git a/src/OpenIddict/OpenIddictProvider.Exchange.cs b/src/OpenIddict/OpenIddictProvider.Exchange.cs index 6d51b643..330c9282 100644 --- a/src/OpenIddict/OpenIddictProvider.Exchange.cs +++ b/src/OpenIddict/OpenIddictProvider.Exchange.cs @@ -207,10 +207,6 @@ namespace OpenIddict { // Revoke the authorization code to prevent token reuse. await tokens.RevokeAsync(token, context.HttpContext.RequestAborted); - - context.Validate(context.Ticket); - - return; } else if (context.Request.IsRefreshTokenGrantType()) { diff --git a/test/OpenIddict.Tests/OpenIddictProviderTests.Exchange.cs b/test/OpenIddict.Tests/OpenIddictProviderTests.Exchange.cs index cd4c8da9..975e9401 100644 --- a/test/OpenIddict.Tests/OpenIddictProviderTests.Exchange.cs +++ b/test/OpenIddict.Tests/OpenIddictProviderTests.Exchange.cs @@ -518,6 +518,7 @@ namespace OpenIddict.Tests { } [Theory] + [InlineData(OpenIdConnectConstants.GrantTypes.AuthorizationCode)] [InlineData(OpenIdConnectConstants.GrantTypes.ClientCredentials)] [InlineData(OpenIdConnectConstants.GrantTypes.Password)] [InlineData(OpenIdConnectConstants.GrantTypes.RefreshToken)] @@ -533,7 +534,17 @@ namespace OpenIddict.Tests { OpenIdConnectServerDefaults.AuthenticationScheme); ticket.SetTicketId("60FFF7EA-F98E-437B-937E-5073CC313103"); - ticket.SetUsage(OpenIdConnectConstants.Usages.RefreshToken); + + switch (flow) { + case OpenIdConnectConstants.GrantTypes.AuthorizationCode: + ticket.SetUsage(OpenIdConnectConstants.Usages.AuthorizationCode); + ticket.SetPresenters("Fabrikam"); + break; + + case OpenIdConnectConstants.GrantTypes.RefreshToken: + ticket.SetUsage(OpenIdConnectConstants.Usages.RefreshToken); + break; + } var format = new Mock>(); @@ -565,6 +576,7 @@ namespace OpenIddict.Tests { builder.Services.AddSingleton(manager); + builder.Configure(options => options.AuthorizationCodeFormat = format.Object); builder.Configure(options => options.RefreshTokenFormat = format.Object); }); @@ -574,6 +586,7 @@ namespace OpenIddict.Tests { var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest { ClientId = "Fabrikam", ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw", + Code = "8xLOxBtZp8", GrantType = flow, RefreshToken = "8xLOxBtZp8", Username = "johndoe",