Java Spring OAuth2 and Basic Auth Support
The goal of the post is to share an idea of how can we provide the basic authentication and OAuth 2 authentication for the APIs.
Join the DZone community and get the full member experience.
Join For FreeThe goal of the post is to share an idea how can we provide the basic authentication and OAuth 2 authentication for the APIs, meaning with new technologies we need to support the OAuth2 for new clients, but at the same time we still need to support the basic authentication way of securing the APIs maybe for time for existing API Users.
Basic Auth
In general, in basic auth clients call API keeping username:password
in the Authorization header for the APIs. By standard basic auth annotation, the username:password
will be Base 64 encoded string.
xxxxxxxxxx
GET /book/{id} HTTP/1.1
Host: mybooks.com
Content-Type: application/json
Authorization: Basic MzMzOjQ0NA==
OAuth 2.0
Now for the new clients, you would want to keep the API the same and change the authorization part of the API, maybe the OAuth2 token in the authorization header instead of the basic auth header, something like.
xxxxxxxxxx
GET /book/{id} HTTP/1.1
Host: mybooks.com
Content-Type: application/json
Authorization: Bearer eyJraWQiOiJRWk1WZ01sUGJzVkhuYk9pOGVXMWlDazVES1VGT...
With this you want your Spring Java Rest APIs to have support both authentication, depending on the client header type let the application decide the route to take for authentication.
For this to work, we will have to understand the Spring security a bit. In the Spring security, you will find the filter chain the gets executed upon any request from the client, which could be requested from web browsers, mobile clients, or Rest clients.
For the request handling, we need to configure the WebSecurityConfigureAdapter in the Spring configuration, like
x
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**/book/**")
.authorizeRequests()
.antMatchers("/**/book/**").authenticated();
}
The above code tells the Spring that any request for book APIs should be authenticated, internally it's going to check for SecurityContext information when serving these requests.
Now, for Spring basic authentication we generally configure the daoAuthentication provider with an overridden method. So whenever the spring security chain executed the Springs basic auth filter will be called and internally it calls the dao provider for authentication. It's a lengthy topic to cover in one post, I will cover that up in a separate post. but, bottom line is that you need to have the dao provider along with the basic authentication filter.
x
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**/book/**")
.authorizeRequests()
.antMatchers("/**/book/**").authenticated()
.and().authenticationProvider(bookDaoAuthenticationProvider)
.httpBasic().realmName("MyBooks.Com")
.csrf().disable();
}
So for our example we have bookDaoAuthenticationProvider, with HTTP basic on it. All basic auth requests will be served from Spring's BasicAuthenticationFilter if they have the Basic keyword starts in the Authorization header, that's Spring's internal logic.
For OAuth2 requests, we can use the AbstractPreAuthenticatedProcessingFilter, as the tokens would be pre-validated by the OAuth2 token servers and it's just needed the verification from the Spring application now. Tokens are generally JWT tokens.
We can configure the security to handle requests like
xxxxxxxxxx
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**/book/**")
.authorizeRequests()
.antMatchers("/**/book/**").authenticated()
.and().authenticationProvider(booksDaoAuthenticationProvider)
.httpBasic().realmName("MyBooks.Com")
.and()
.addFilter(booksJwtPreAuthFilter)
.csrf().disable();
}
The booksJwtPreAuthFilter can be configured like —
xxxxxxxxxx
public class BookJwtPreAuthFilter extends AbstractPreAuthenticatedProcessingFilter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
//Validate Accees Tokens
chain.doFilter(request, response);
}
}
Keep in mind the API request Authorization header is important here. If it has a Basic keyword it would be served by BasicAuthFilter in the chain and SecurityContext would be created. Now AbstractPreAuthenticatedProcessingFilter filters would be only invoked if the security context has not been created yet, that's the whole point of this logic.
Hope this gives a good idea about the Spring Rest API authentication for Basic Auth and For OAuth2 for that matter any other security protocol as well.
Opinions expressed by DZone contributors are their own.
Comments