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 2.0 is all about Authorization
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 Actors
OAuth 2.0 protocol defines four Actors:
- Resource Server – an API provider used to access user's information (i.e., your application)
- Resource Owner – a user who is giving the access to their information to a Client
- Client – a third-party client application that utilizes the exposed API
- Authorization Server – Endpoint where users logs in and gives permission to a Client to access user's information hosted by a Resource Server.
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:
- Authorization code (aka: Web Application flow, aka: Server-Side Web Application Flow)
This grant type most often associated with OAuth. Client application must redirect user to the authorization server to authorize access to their data. After user has approved access, it's get redirected back to client application with authorization code as a parameter. The code then is exchanged for access token with a separate call from client application to Authorization server token endpoint. After access token is issued, it can be used by client application to access protected resources on Resource Server.
Best fits for: Web apps or native mobile apps with browser support
- Implicit grant (aka: Client-Side Web Applications Flow)
Simplified version of Authorization code grand type. Here instead of issuing the client an authorization code, the client is issued an access token directly.
Best fits for: Browser-based apps running entirely in the browser after loading the source code from a web page
- Resource Owner grant (aka: Password-based grant)
User (resource owner) has to give its credentials directly to the client application.
Best fits for: Highly trusted client apps, such as mobile apps written by API provider.
- Client Credentials grant
Used when the client app is requesting access to protected resources, such as storage service or database service, on behalf of itself rather than on behalf of a specific user.
Type: Client App Credentials
Spring as an OAuth provider
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:
- AuthorizationEndpoint – handles authorization requests. Default url: /oauth/authorize
- TokenEndpoint – handles requests for access tokens. Default url: /oauth/token
The authorization-server element is used to enable these two endpoints in your application, like this:
- Client Details Service – service to that retains OAuth client-specific information
- Token Service – service for managing issued tokens
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 – client id (aka api key)
- secret – client secret
- scope – scopes to which the client is limited
- resource-ids – resource ids to which this client can be granted access
- authorised-grant-types – supported grant types for that client
- authorities – client roles
- redirect-uri – callback url
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:
This filter needs to be added to the standard Spring Security filter chain at position before="PRE_AUTH_FILTER":
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:
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:
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.|