OAuth
1 Overview
OAuth allows to grant access to private resources on one site (which is called the
Service Provider), to another site (called
Consumer). OAuth is giving access to a resource without sharing your credential at all. More about oAuth at the site
http://oauth.net/. (OAuth protocol:
http://oauth.net/core/1.0/)
This article describes how to configure our implementation of oAuth service and client part. Both parts, service (Provider) and client (Consumer) are based on oAuth core, this code can be found here
http://oauth.googlecode.com/svn/code/java/core/.
Our implementation can be found here
http://svn.exoplatform.org/svnroot/exoplatform/projects/ws/trunk/security/oauth.
2 Provider
The provider consists of two parts
oauthprovider.war and
exo.ws.security.oauth.provider.service-trunk.jar.
The main part of the provider is
OAuthProviderService, currently there is one implementation of this interface
org.exoplatform.ws.security.oauth.impl.OAuthProviderServiceMD5Impl; this component has few required configuration parameters.
2.1 Configuration
The configuration is defined in the file configuration.xml.
<component>
<type>org.exoplatform.ws.security.oauth.impl.OAuthProviderServiceMD5Impl</type>
<init-params>
<properties-param>
<name>exo1</name>
<property name="secret" value="81d1b5d080d1" />
<property name="description" value="description" />
<property name="callbackURL" value="http://localhost:8080/ws-examples/callback" />
</properties-param>
</init-params>
</component>
Properties:
- name: the name of provider, the client will send the name of provider that it wants to use.
- secret: this property is used for subscribe requests, this property must be known to the provider and the consumer.
- description: any description of the provider. Optional.
- callbackURL: this is URL where the client will be redirected after successful authentication by the provider.
That is all what is needed for the configuration of the provider service. The next part of configuration is about web, such as servlets.
2.2 Servlets
The web part of the provider consists of 3 servlets:
- OAuthRequestTokenServlet,
- OAuthAccessTokenServlet, and
- OAuthAuthorizationServlet.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>oAuth provider</display-name>
<context-param>
<description>Login page name</description>
<param-name>login-page</param-name>
<param-value>login/jsp/login.jsp</param-value>
</context-param>
<servlet>
<servlet-name>OAuthAuthenticationServlet</servlet-name>
<servlet-class>org.exoplatform.ws.security.oauth.http.OAuthAuthenticationServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>OAuthRequestTokenServlet</servlet-name>
<servlet-class>org.exoplatform.ws.security.oauth.http.OAuthRequestTokenServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>OAuthAccessTokenServlet</servlet-name>
<servlet-class>org.exoplatform.ws.security.oauth.http.OAuthAccessTokenServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>OAuthAuthenticationServlet</servlet-name>
<url-pattern>/authorize/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>OAuthRequestTokenServlet</servlet-name>
<url-pattern>/request_token/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>OAuthAccessTokenServlet</servlet-name>
<url-pattern>/access_token/*</url-pattern>
</servlet-mapping>
</web-app>
3 Consumer
The consumer consists of
OAuthConsumerService and web part (
servlets and filters).
3.1 How it works
OAuthConsumerFilter checks cookies in client's request. The
cookie must have the name
_consumer_name_.oauth_token and
_consumer_name_.oauth_token_secret. Then this filter try to find the request/access token this at
OAuthConsumerService. If the token from the request is an access token then the client is already authenticated and gets access to requested resource.
Otherwise the client will be redirected to the provider for authentication (see below, property "
provider.authorizationURL"). This is the part of configuration.xml for the consumer:
<component>
<type>org.exoplatform.ws.security.oauth.impl.OAuthConsumerServiceImpl</type>
<init-params>
<value-param>
<!-- this parameter MUST be set in minutes -->
<name>tokenAliveTime</name>
<value>300</value>
</value-param>
<properties-param>
<name>exo1</name>
<property name="secret" value="81d1b5d080d1" />
<property name="description" value="description" />
<property name="provider.tokenRequestURL" value="http://localhost:8080/oauthprovider/request_token" />
<property name="provider.authorizationURL" value="http://localhost:8080/oauthprovider/authorize" />
<property name="provider.accessTokenURL" value="http://localhost:8080/oauthprovider/access_token" />
</properties-param>
</init-params>
</component>
<component>
<type>org.exoplatform.ws.security.oauth.impl.OAuthClientHttpImpl</type>
</component>
<component>
<type>org.exoplatform.ws.security.oauth.impl.OAuthTokenCleanerImpl</type>
<init-params>
<value-param>
<!-- this parameter MUST be set in minutes -->
<name>tokenCleanerTimeout</name>
<value>3</value>
</value-param>
</init-params>
</component>
The client is
redirected for authentication to the provider with the required
parameters (
request and secret token), before this token OAuthClient got from the provider (see configuration, property "provider.tokenRequestURL"). On the provider side, the user (if the authentication is successful and has valid request parameters) will be
redirected to the consumer again (see property "
callbackURL" in the provider configuration). Then the consumer (this is, the same as receiving request token, invisible for the client) receives the access token, and redirects the client to the original URL. Then the filter checks the token from the request and gives access to the requested resource.
3.2 web.xml
This is the file web.xml for consumer application, in this example the resource
http://localhost:8080/ws-examples/oauth/protected/ is under oAuth protect :
<filter>
<filter-name>OAuthConsumerFilter</filter-name>
<filter-class>org.exoplatform.ws.security.oauth.http.OAuthConsumerFilter</filter-class>
<init-param>
<param-name>consumer</param-name>
<param-value>exo1</param-value>
</init-param> </filter> <filter>
<filter-name>OAuthRequestWrapperFilter</filter-name>
<filter-class>org.exoplatform.ws.security.oauth.http.OAuthRequestWrapperFilter</filter-class> </filter>
<filter-mapping>
<filter-name>OAuthConsumerFilter</filter-name>
<url-pattern>/oauth/protected/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>OAuthRequestWrapperFilter</filter-name>
<url-pattern>/oauth/protected/*</url-pattern>
</filter-mapping>
Any resource can be protected by this mechanism under the condition that web.xml is configured to use OAuthConsumerFilter. Client must save the given access and the secret token in a cookie.
3.3 Stages
- continuous line - client's redirections
- fine dashed line - internal oAuth schema requests and responses.
Stages:
- green - stage 1 (receiving request token)
- yellow - stage 2 (authentication)
- blue - stage 3 (receiving access token)
- red - stage 4 (get protected resource)
3.4 Token Alive Time
Alive time for tokens can be set using the parameter
tokenAliveTime.
<value-param>
<!-- this parameter MUST be set in minutes -->
<name>tokenAliveTime</name>
<value>300</value>
</value-param>
3.5 Token Cleaner Timeout
There is special component cleaner on consumer side, it starts, by default, every 5 minutes and checks all tokens. If it finds token with expired time it removes it from the storage. Token cleaner timeout (how often it must run) can be also set in the configuration:
<component>
<type>org.exoplatform.ws.security.oauth.impl.OAuthTokenCleanerImpl</type>
<init-params>
<value-param>
<!-- this parameter MUST be set in minutes -->
<name>tokenCleanerTimeout</name>
<valueɯ</value>
</value-param>
</init-params>
</component>