October 16, 2013

API Management – Securing APIs

REST-style APIs with either JSON or XML format have become a de-facto standard for enterprise software everywhere. However, the security of REST APIs is still often done in an ad-hoc manner, with most developers writing custom code for securing the services. Lately, OAuth has become a popular authentication choice because of its use by Google, Facebook, Twitter and so many more portals. In this article, we will explore the use of OAuth as a mechanism to secure your REST services without writing custom code.

What is OAuth?

In order to understand the motivation for securing APIs with OAuth, we should first understand the concept of OAuth. OAuth is a protocol which allows access to secure resources on behalf of resource owners to third-party applications without exposing their credentials. For example, on many sites today you can log in using Facebook, Twitter, or Gmail credentials. When you actually log in using Facebook, the client application is not privy to your Facebook credentials. So through OAuth, a client application can act on behalf of a user, but only with a user’s explicit permission. Later the user can revoke the permission if desired.

This makes OAuth an ideal choice for security because of the following reasons:

  1. Your application does not have to deal with the registration and authentication of users.
  2. Your users can continue to trust the providers they already have accounts with and simply have to authorize access to your application.
  3. This third-party authentication process makes it easier and faster for your users to start using your application, rather than going through the rigmarole of another standard registration process.
  4. The OAuth protocol has many variants, making it ideal for use with different platforms such as the web or mobile.

The current version of the protocol is OAuth2.0 and has the following flow:

OAuth 2.0

Using Spring Security OAuth

Spring Security is a framework which provides a declarative, highly customizable authentication and access-control. Spring also provides OAuth implementation over Spring Security. This project is called Spring Security OAuth. It has implementation for OAuth providers and OAuth customers.  The following sections describe how OAuth can be set up on the server (the OAuth provider) and then set up on the client side (the OAuth customer).

Step 1: Configure User Authentication source

There are different ways to authenticate and assign roles to the user. We are providing following options for this.

  • LDAP authentication: – If you want to authenticate the users through LDAP server then configure it in context file. Below is the snippet to configure embedded LDAP server in Spring.
<sec:ldap-server ldif="classpath:users.ldif" port="33389" />

<bean id="contextSource"
	class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
	<constructor-arg value="ldap://localhost:33389/dc=springframework,dc=org" />
</bean>

<bean id="ldapProvider"
	class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
	<constructor-arg>
		<bean
			class="org.springframework.security.ldap.authentication.BindAuthenticator">
			<constructor-arg ref="contextSource" />
			<property name="userDnPatterns">
				<list>
					<value>uid={0},ou=people</value>
				</list>
			</property>
		</bean>
	</constructor-arg>
	<constructor-arg>
		<bean
			class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
			<constructor-arg ref="contextSource" />
			<constructor-arg value="ou=groups" />
			<property name="groupSearchFilter" value="(member={0})" />
			<property name="rolePrefix" value="ROLE_" />
			<property name="searchSubtree" value="true" />
			<property name="convertToUpperCase" value="true" />
		</bean>
	</constructor-arg>
</bean>

<authentication-manager xmlns="http://www.springframework.org/schema/security">
	<authentication-provider ref='ldapProvider' />
</authentication-manager>
  • In-Memory authentication: – If you want a limited set of users, then you can use this approach.  You can configure a limited set of users as below:
<authentication-manager xmlns="http://www.springframework.org/schema/security">
	<authentication-provider>
		<user-service>
			<user name="tarun" password="tarun" authorities="ROLE_USER" />
		</user-service>
	</authentication-provider>
</authentication-manager>

Step 2: Configure Clients

Configure clients who will access secure resources from this server.

<oauth:client-details-service id="clientDetails">
	<oauth:client client-id="foo" resource-ids="restSample"
		authorized-grant-types="authorization_code,implicit" authorities="ROLE_CLIENT"
		scope="read,write" secret="secret" />
</oauth:client-details-service>

You can configure as many clients as you want. Description of configuration as given below:

  • Client-id:  The client id needs to be unique across all registered clients.
  • Secret:  In the event the secret is undefined, it would imply that the client does not require this option.
  • Resources-ids:  Individual resource ids can be granted access to resources with a comma-separated input. When resource id is not keyed in this would be an indication that all resources are accessible. This refers to the Resource-id as defined below in the step 5.
  • Scope:  This defines the scope to which the client is limited in a comma separated input. An empty or undefined scope implies that the client is not limited by scope.
  • Authorities:  This defines the Authorities that the client is provided in a comma separated format.

Step 3: Resource Server Configuration

It specifies that there are OAuth 2 protected resources in the application context. You need to supply the <resource-server/> element with following attributes configuration:

  • Id: this is the bean id for a servlet filter that can be added to the standard Spring Security chain.
  • Resource-id:  The resource id that is protected by this filter. This attribute value will be used in step 2 as given above while setting client.
<oauth:resource-server id="resourceServerFilter"
	resource-id="restSample" token-services-ref="tokenServices" />

Step 4: Secure Required Resources

<http pattern="/restSample/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint"
	access-decision-manager-ref="accessDecisionManager" xmlns="http://www.springframework.org/schema/security">
	<anonymous enabled="false" />
	<intercept-url pattern="/restSample/**" access="ROLE_USER,SCOPE_READ" />
	<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
	<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

You have to set up the following configuration:

·         Pattern: pattern defines the URL path of secure resource. User will use this path to access the resources.

·         Intercept-urlpattern: The pattern which defines the URL path.

·         Access: You can specify the user role to access the configured path.

·         Custom-filter: this is used to incorporate filter in to the security filter chain. Refer the name of filter defined in the step3. This specifies that this pattern is protected through OAuth2.

Configure OAuth2 client using Spring Security

Step 1:  Configure OAuth server authentication endpoints and client-id and client-secret. Suppose we are configuring it in oauth.properties file.

userAuthorizationUri=http://localhost/restServer/oauth/authorize
accessTokenUri=http://localhost/restServer/oauth/token
client_id=foo
client_secret=secret
restProductURL=http://localhost/restServer/restSample/searchProducts.do

Step 2: Configure this file on context.xml file

<context:property-placeholder location="classpath:/oauth.properties" />

Step 3: Configure OAuth resource

<oauth:resource id="fooClient" type="authorization_code"
	client-id=" ${client_id}" client-secret=" ${client_secret}"
	access-token-uri="${accessTokenUri}" user-authorization-uri="${userAuthorizationUri}"
	scope="read" />

But this configuration will ask for client side authentication first, and after that it will redirect the user to the OAuth server for authorization. If you want to redirect the user to the OAuth server without authentication on client side then you have to do the following:

Access token cannot be accessed by anonymous users because of spring security. If you want to enable it for your application then you can do so by extending org.springframework.com.security.oauth2.client.token.grant.code. AuthorizationCodeResourceDetails class and override isClientOnly() method.

package com.threepillar.labs.service;

import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;

public class ExtendedBaseOAuth2ProtectedResourceDetails extends
		AuthorizationCodeResourceDetails {

	@Override
	public boolean isClientOnly() {
		return true;
	}
}

This method is designed to return false by default. If you want to override it to return true you will have to alter the root context.xml file by defining the OAuth2 resource as follows:

<bean id="resourceFoo" class="com.threepillar.labs.service.ExtendedBaseOAuth2ProtectedResourceDetails">
	<property name="clientId" value="${client_id}"></property>
	<property name="clientSecret" value="${client_secret}"></property>
	<property name="accessTokenUri" value="${accessTokenUri}"></property>
	<property name="userAuthorizationUri" value="${userAuthorizationUri}"></property>
	<property name="scope" value="#{{'read','write'}}"></property>
</bean>

Step 4: Configure the service which will use REST Template to make the OAuth call:

<bean id="restService" class="com.threepillar.labs.service.RESTServiceImpl">
	<property name="serverURL" value="${restProductURL}"></property>
	<property name="restTemplate">
		<oauth:rest-template resource="resourceFoo" />
	</property>
</bean>

Here you will have to pass OAuth resource configured in Step 2.

Conclusion

The Spring Security OAuth makes it simple to add OAuth2 authentication flow to your existing web applications without invasive code changes.  If you are currently working with tenancy based web applications which multiple client applications (on the mobile or web platforms), you should actively consider OAuth authentication as mentioned in this article; and if you have a Java based web-application, Spring Security OAuth is a very good bet!