As the web evolves, more and more businesses are shifting their applications and data from internally hosted to the cloud. They provide publicly available APIs to expose valuable data (resources) and business functionality. To provide controlled access to exposed resources, API should be secured somehow, and that is where OAuth comes into play.
OAuth 2.0 is the most widely adopted standard for API security. Google, Facebook, Salesforce, PayPal uses the OAuth 2.0 to authorize calls to user resources on their behalf without sharing user passwords with third-party applications. |
OAuth stands for "Open Authorization" (user roles) not "Authentication" (user identity). Once again: it's not an authentication protocol. The specification leaves it up to Authorization Server provider to decide how Authentication is implemented.
OAuth 2.0 protocol defines four Actors:
In contrast with the first version of OAuth, which was designed to delegate access for browser-based web applications, OAuth 2.0 introduced support for non-browser based applications - like native mobile apps or desktop apps - by extending number of supported Grand Types.
Grand Type defines how client application obtains a grant from the users to access user's data on their behalf. The specification defines four core Grand Types:
In order to embed OAuth 2.0 provider mechanism into your application there are a variety of libraries and tools available for developers. Being a Java developer and primarily using Spring framework, I'll use Spring OAuth 2.0 library in this example. It demonstrates Spring configuration of OAuth provider for the Authorization code grant type.
And here's how it works:
The concept of OAuth provider revolves around Resource Server and Authorization Server implementation. These can be two separate application, but in our example both reside in a same application.
Authorization server in Spring Security is implemented by two framework endpoints:
The authorization-server element is used to enable these two endpoints in your application, like this:
client-details-service-ref="clientDetails"
token-services-ref="tokenService"
user-approval-page="forward:/oauth/custom_confirm_access">
Here:
Property <oauth2:authorization-code /> defines support of grant type "Authorization code"; and the next step is to define Client Details Service and specify your API client applications, like so:
client-id="rest-api-client"
secret="client-secret"
scope="read,trust"
resource-ids="rest-data"
authorized-grant-types="authorization_code"
authorities="ROLE_CLIENT"
redirect-uri="${redirect-url-to-client-app}"/>
Here:
As the next step we need to define Token Service to be able load associated with access token authentication. We will use a default implementation and in-memory token store:
Once we are done with Authorization Server configuration we can continue with Resource Server. In Spring Security, it is implemented by means of OAuth2AuthenticationProcessingFilter. It extracts an OAuth2 token from the incoming request and uses it to load authentication from token service:
resource-id="rest-data"
token-services-ref="tokenService" />
This filter needs to be added to the standard Spring Security filter chain at position before="PRE_AUTH_FILTER":
create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
use-expressions="true"
entry-point-ref="clientAuthenticationEntryPoint">
access="#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER'))" />
This security configuration allows to define API urls and access roles for both client app and user. TokenEndpoint ("/oauth/token") also needs to be secured by a filter – ClientCredentialsTokenEndpointFilter:
create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
use-expressions="true"
entry-point-ref="clientAuthenticationEntryPoint">
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
As Resource Server and Authorization Server reside in one application we need to configure two application managers; one for client application authentication:
We utilise as authorisation provider previously configured Client Details Service with in-memory client store:
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
And another for users authentication:
For simplicity's sake, we will use in-memory user service with just one user:
This is a basic example on how to enable protection of API exposed to third party applications, but there may be way more complex setups, of course. Need assistance with securing your public APIs? Give us a hint, we can help!
About the author: Aleksandrs Kuripka has been with Idea Port Riga since March 2011, working with Java technologies and custom development in general for almost 10 years since the beginning of his career. Being a keen supporter of lean, agile and clean code principles, he tends to keep the code base habitable and focus on things that bring real value to the customer. |