I have set up an Authorization Server using OpenIddict 3.1.1 (porting over an existing one that was using the older ASOS package directly). I believe I am most of the way there, because when using the client application, I am able to log in, give consent, redirect back to the client, and exchange the authorization code for an access token.
However, when I try to do the same using Postman's OAuth 2.0 authentication support, I am able to log in (and give consent), but when it completes and returns the authorization code, I receive an HTTP 403 from the https://oauth.pstmn.io/v1/callback that I am redirected to:
403 ERROR The request could not be satisfied. This distribution is not configured to allow the HTTP request method that was used for this request. The distribution supports only cachable requests. We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner. If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation. Generated by cloudfront (CloudFront) Request ID: UAXpago6ISiqbgm9U_SVPwh96qz1qoveZWFd0Cra-2FximeWZiY2aQ==
From what I can tell, this is because OpenIddict is issuing a POST request back to the callback url. This works for my client application, but evidently is not supported by Postman.
What configuration tweak do I need to make to OpenIddict to support this in postman?
OpenIddict related config in Startup.ConfigureServices:
services.AddOpenIddict()
.AddCore(options => {
options.AddApplicationStore<ClientStore>();
options.UseEntityFramework()
.UseDbContext<OAuthServerDbContext>()
.ReplaceDefaultEntities<Client, Authorization, OAuthScope, Token, long>()
;
})
.AddServer(options => {
options.RegisterClaims();
options.RegisterScopes(OpenIddictConstants.Scopes.OpenId,
OpenIddictConstants.Scopes.Email,
OpenIddictConstants.Scopes.OfflineAccess,
OpenIddictConstants.Scopes.Profile,
"user");
// flows
options.AllowAuthorizationCodeFlow();
options.AllowRefreshTokenFlow();
options.AllowPasswordFlow();
options.AllowHybridFlow();
// implicit is used by postman
options.AllowImplicitFlow();
var serviceProvider = options.Services.BuildServiceProvider();
var oauthConstants = serviceProvider.GetRequiredService<IOptions<OAuthConstants>>().Value;
var tokenLifetimes = serviceProvider
.GetRequiredService<IOptions<OpenIdConnectServerTokenLifetimeSettings>>().Value;
// security
options.SetAccessTokenLifetime(tokenLifetimes.AccessTokenLifetime)
.SetAuthorizationCodeLifetime(tokenLifetimes.AuthorizationCodeLifetime)
.SetIdentityTokenLifetime(tokenLifetimes.IdentityTokenLifetime)
.SetRefreshTokenLifetime(tokenLifetimes.RefreshTokenLifetime);
options.SetIssuer(new Uri("https://localhost/oauth/"));
// custom handlers added here
options.AddEventHandlers();
// certificate details hidden
options.AddEncryptionCertificate(certificate);
// endpoints
options.SetAuthorizationEndpointUris("/OpenIdConnect/Authorize");
options.SetLogoutEndpointUris("/OpenIdConnect/Logout", "/Account/Logout");
options.SetRevocationEndpointUris("/OpenIdConnect/Revoke");
options.SetTokenEndpointUris("/OpenIdConnect/Token");
options.SetCryptographyEndpointUris("/OpenIdConnect/JWKDoc");
options.SetUserinfoEndpointUris("/OpenIdConnect/UserInfo");
options.UseAspNetCore()
.EnableStatusCodePagesIntegration()
.EnableAuthorizationEndpointPassthrough()
//.EnableTokenEndpointPassthrough()
.EnableLogoutEndpointPassthrough()
.EnableUserinfoEndpointPassthrough()
;
})
.AddValidation(options => {
options.UseLocalServer();
options.UseAspNetCore();
var serviceProvider = options.Services.BuildServiceProvider();
var config = serviceProvider.GetRequiredService<IConfiguration>();
options.SetClientId(config.GetValue<string>(nameof(Settings.OAuthClientId)));
options.SetClientSecret(config.GetValue<string>(nameof(Settings.ClientSecret)));
// certificate details hidden
options.AddEncryptionCertificate(certificate);
});
Postman details:
Authorization Token Name: Redacted Grant Type: Authorization Code Callback URL: disabled, https://oauth.pstmn.io/v1/callback Authorize using browser: checked Auth URL: https://localhost/oauth/OpenIdConnect/Authorize Access Token URL: https://localhost/oauth/OpenIdConnect/Token Client ID: redacted, but correct Client Secret: redacted, but correct Scope: openid offline_access State: Client Authentication: Send client credentials in body
edit: The response that it sends to the postman callback URI does include the authorization code in the body, but because of the 403 response, Postman doesn't parse that out and make the follow-up request to exchange the code for the token.
CodePudding user response:
There is an option that you can set to control if the authorization code is received in the URL as a query string or in the body as a post. The option is response_mode and you control that as a client.
I believe if it is not set to response_mode=form_post, then you will get the code in the URL instead.
See the details about this parameter here.