Calling spring authorization server OAuth2 REST endpoints
First, in your case you don't need the Authorization
header in your request for token since you explicitly allowed all requests to pass through via authorizeRequests.anyRequest().permitAll()
.
Second, in your curl
request you didn't specify at least a desired grant type and its parameters.
For example, for the password
grant type the request might look something like this:
curl -L -X POST 'example-host:9000/oauth2/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=client' \
--data-urlencode 'client_secret=client-secret' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=user' \
--data-urlencode 'password=password'
UPDATE:
Spring authorization server 0.3.0 doesn't support the
password
grant type, exactly as it shows in thegrant_types_supported
section of the.well-known/oauth-authorization-server
endpoint output. There's just no such authentication provider in theorg.springframework.security.oauth2.server.authorization.authentication
package.To make at least the
client_credentials
token request work, add
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
and (in case you'd like to pass the client_id
and client_secret
inside the POST body)
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
to your RegisteredClient
in the registeredClientRepository
.
Then this can be tested with
curl -L -X POST 'http://example-host:9000/oauth2/token' -H 'Content-Type: application/x-www-form-urlencoded' -d 'grant_type=client_credentials&client_id=client&client_secret=client-secret'
(be sure to pass the actual client_id
and client_secret
of a RegisteredClient
)
Also, if you import OAuth2AuthorizationServerConfiguration
a default SecurityFilterChain
for the auth server endpoints is created and there's no need to define it manually. On the other hand a SecurityFilterChain
for your app authentication is likely still needed.
- To debug the OAuth authentication process and see the exact exceptions, if any, set some breakpoints in the
org.springframework.security.authentication.ProviderManager#authenticate()
method
Configure the authorization server endpoint
EDIT (01/28/2021): AspNet.Security.OpenIdConnect.Server has been merged into OpenIddict as part of the 3.0 update. To get started with OpenIddict, visit documentation.openiddict.com.
Okay, let's recap the different OAuth2 middleware (and their respective IAppBuilder
extensions) that were offered by OWIN/Katana 3 and the ones that will be ported to ASP.NET Core:
app.UseOAuthBearerAuthentication
/OAuthBearerAuthenticationMiddleware
: its name was not terribly obvious, but it was (and still is, as it has been ported to ASP.NET Core) responsible for validating access tokens issued by the OAuth2 server middleware. It's basically the token counterpart of the cookies middleware and is used to protect your APIs. In ASP.NET Core, it has been enriched with optional OpenID Connect features (it is now able to automatically retrieve the signing certificate from the OpenID Connect server that issued the tokens).
Note: starting with ASP.NET Core beta8, it is now namedapp.UseJwtBearerAuthentication
/JwtBearerAuthenticationMiddleware
.
app.UseOAuthAuthorizationServer
/OAuthAuthorizationServerMiddleware
: as the name suggests,OAuthAuthorizationServerMiddleware
was an OAuth2 authorization server middleware and was used to create and issue access tokens. This middleware won't be ported to ASP.NET Core: OAuth Authorization Service in ASP.NET Core.app.UseOAuthBearerTokens
: this extension didn't really correspond to a middleware and was simply a wrapper aroundapp.UseOAuthAuthorizationServer
andapp.UseOAuthBearerAuthentication
. It was part of the ASP.NET Identity package and was just a convenient way to configure both the OAuth2 authorization server and the OAuth2 bearer middleware used to validate access tokens in a single call. It won't be ported to ASP.NET Core.
ASP.NET Core will offer a whole new middleware (and I'm proud to say I designed it):
app.UseOAuthAuthentication
/OAuthAuthenticationMiddleware
: this new middleware is a generic OAuth2 interactive client that behaves exactly likeapp.UseFacebookAuthentication
orapp.UseGoogleAuthentication
but that supports virtually any standard OAuth2 provider, including yours. Google, Facebook and Microsoft providers have all been updated to inherit from this new base middleware.
So, the middleware you're actually looking for is the OAuth2 authorization server middleware, aka OAuthAuthorizationServerMiddleware
.
Though it is considered as an essential component by a large part of the community, it won't be ported to ASP.NET Core.
Luckily, there's already a direct replacement: AspNet.Security.OpenIdConnect.Server (https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server)
This middleware is an advanced fork of the OAuth2 authorization server middleware that comes with Katana 3 but that targets OpenID Connect (which is itself based on OAuth2). It uses the same low-level approach that offers a fine-grained control (via various notifications) and allows you to use your own framework (Nancy, ASP.NET Core MVC) to serve your authorization pages like you could with the OAuth2 server middleware. Configuring it is easy:
ASP.NET Core 1.x:
// Add a new middleware validating access tokens issued by the server.
app.UseOAuthValidation();
// Add a new middleware issuing tokens.
app.UseOpenIdConnectServer(options =>
{
options.TokenEndpointPath = "/connect/token";
// Create your own `OpenIdConnectServerProvider` and override
// ValidateTokenRequest/HandleTokenRequest to support the resource
// owner password flow exactly like you did with the OAuth2 middleware.
options.Provider = new AuthorizationProvider();
});
ASP.NET Core 2.x:
// Add a new middleware validating access tokens issued by the server.
services.AddAuthentication()
.AddOAuthValidation()
// Add a new middleware issuing tokens.
.AddOpenIdConnectServer(options =>
{
options.TokenEndpointPath = "/connect/token";
// Create your own `OpenIdConnectServerProvider` and override
// ValidateTokenRequest/HandleTokenRequest to support the resource
// owner password flow exactly like you did with the OAuth2 middleware.
options.Provider = new AuthorizationProvider();
});
There's an OWIN/Katana 3 version, and an ASP.NET Core version that supports both .NET Desktop and .NET Core.
Don't hesitate to give the Postman sample a try to understand how it works. I'd recommend reading the associated blog post, that explains how you can implement the resource owner password flow.
Feel free to ping me if you still need help.
Good luck!
Spring OAuth2 explain Authorization server configuration
AuthorizationServerConfigurer
's javadoc is more informative than the linked documentation. AuthorizationServerSecurityConfigurer
, as its name suggests, configures the security of the Authorization Server itself. For example you can override the OAuth endpoints security such as /oauth/token
, provide an access denied handler or restrict to SSL access. Here are what the documentation says about it:
Configure the security of the Authorization Server, which means in
practical terms the/oauth/token
endpoint. The/oauth/authorize
endpoint also needs to be secure, but that is a normal user-facing
endpoint and should be secured the same way as the rest of your UI, so
is not covered here. The default settings cover the most common
requirements, following recommendations from the OAuth2 spec, so you
don't need to do anything here to get a basic server up and running.
As for AuthorizationServerEndpointsConfigurer
:
Configure the non-security features of the Authorization Server
endpoints, like token store, token customizations, user approvals and
grant types. You shouldn't need to do anything by default, unless you
need password grants, in which case you need to provide an
AuthenticationManager
.
Here is a sample from one of my projects:
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.tokenStore(jwtTokenStore())
.tokenEnhancer(tokenEnhancer());
}
Here I provided a JwtTokenStore
as my TokenStore
and a AuthenticationManager
since I was using Password Grants.
Related Topics
What Is the Equivalent of the Java Bigdecimal Class in C#
How to Call an Async Method in Main
Observeon and Subscribeon - Where the Work Is Being Done
Should I Call Close() or Dispose() for Stream Objects
How to Return Multiple Result Sets with SQLcommand
When Is It Appropriate to Use C# Partial Classes
Difference Between Convert.Tostring() and .Tostring()
SQL Query Slow in .Net Application But Instantaneous in SQL Server Management Studio
How to Avoid a Win32 Exception When Accessing Process.Mainmodule.Filename in C#
How to Pass Parameters by Reference in Java
How to Get the Computer Name in .Net
C# "Parameter Is Not Valid." Creating New Bitmap
How to Do Appbar Docking (To Screen Edge, Like Winamp) in Wpf
What Does the Tilde Before a Function Name Mean in C#