About Alex Soto

OAuth with Spring Security

From Wikipedia: OAuth (Open Authentication) is an open standard for authentication. It allows users to share their private resources (e.g. photos, videos, contact lists) stored on one site with another site without having to hand out their credentials, typically username and password.

There are a lot of posts talking about OAuth from Client Side, for example how to connect to service providers like Twitter or Facebook, but there are less posts about OAuth but from Server Side, more specificaly how to implement an authentication mechanism using OAuth for protecting resources, and not for accessing them (Client Side Part).

In this post I will talk about how to protect your resources, using Spring Security (Spring Security OAuth). The example will be simple enough to understand the basics for implementing an OAuth service provider.

I have found this post that explains with a simple example, what OAuth is and how it works. I think it is a good starting point with OAuth http://hueniverse.com/2007/10/beginners-guide-to-oauth-part-ii-protocol-workflow/

Now it is time to start writing our service provider. First of all I will explain what our Service Provider will offer.

Imagine you are developing a website (called CV) where users will register and after that they will be able to upload their Curriculum Vitae. Now we are going to transform this website to a Service Provider where OAuth will be used for protecting resources (Curriculm Vitae of registered users). Imagine again that some companies have agreed with CV people that when they publish job vacances, users will have the possibility of uploading their curriculum directly from CV site to HR department instead of sending by email or copy & paste from document. As you can see here is where OAuth starts managing security between CV website and Company RH site.

In summary we have a Curriculum Vitae Service Provider (CV) with protected resource (document itself). Companies that offer users the possibility of acquiring directly their Curriculum Vitae from CV are the Consumers. So when a user visits company job vacancies (in our example called fooCompany) and wants to apply for a job, he only has to authorize FooCompany “Job Vacancies” website with permissions to download its Curriculum Vitae from CV site.

Because we will use Spring Security for OAuth authentication, first of all we are going to configure Spring Security into SpringMVC CV application. Nothing special here:

In web.xml file we define Security Filter:

<filter>
 <filter-name>springSecurityFilterChain</filter-name>
 <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
 <filter-name>springSecurityFilterChain</filter-name>
 <url-pattern>/*</url-pattern>
</filter-mapping>

And in root-context.xml we define protected resources and authentication manager. In this case In memory apporoach is used:

<http auto-config='true'>
 <intercept-url pattern="/**" access="ROLE_USER" />
</http>

<authentication-manager>
 <authentication-provider>
  <user-service>
   <user name="leonard" password="nimoy" authorities="ROLE_USER" />
  </user-service>
 </authentication-provider>
</authentication-manager>

Next step, create an Spring Controller that returns the Curriculum Vitae of logged user:

@RequestMapping(value="/cvs", method=RequestMethod.GET)
@ResponseBody
public String loadCV() {
 StringBuilder cv = new StringBuilder();
 cv.append("Curriculum Vitae -- Name: ").append(getUserName()).append(" Experience: Java, Spring Security, ...");
 return cv.toString();
}

private String getUserName() {
 Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
 String username;
 if (principal instanceof UserDetails) {
   username = ((UserDetails)principal).getUsername();
 } else {
   username = principal.toString();
 }
 return username;
}

This controller returns directly a String, instead a ModelView object. This String is sent directly as HttpServletResponse.

Now we have got a simple website that returns the Curriculum Vitae of logged user. If you try to access to /cvs resource, if you are not authenticated, Spring Security will show you a login page, and if you are already logged, your job experience will be returned. Works as any other website that are using Spring Security.

Next step is modifing this project for allowing external sites can access to protected resources using OAuth 2 authentication protocol.

In root-context.xml:

<beans:bean id="tokenServices"
  class="org.springframework.security.oauth2.provider.token.InMemoryOAuth2ProviderTokenServices">
 <beans:property name="supportRefreshToken" value="true" />
</beans:bean>

<oauth:provider client-details-service-ref="clientDetails"
 token-services-ref="tokenServices">
 <oauth:verification-code user-approval-page="/oauth/confirm_access" />
</oauth:provider>

<oauth:client-details-service id="clientDetails">
 <oauth:client clientId="foo" authorizedGrantTypes="authorization_code" />
</oauth:client-details-service>

First bean, is an OAuth2ProviderTokenServices interface implementation with id tokenServices. The OAuth2ProviderTokenServices interface defines operations that are necessary to manage OAuth 2.0 tokens. These tokens should be stored for subsequent access token can reference it. For this example InMemory store is enough.

Next bean is <oauth:provider>. This tag is used to configure the OAuth 2.0 provider mechanism. And in this case three parameters are configured; the first one is a reference to a bean that defines the client details service, explained in next paragraph. The second one is token service for providing tokens, explained in previous paragraph, and the last one is the URL at which a request for authorization token will be serviced. This is the typically Authorize/Denny page where service provider asks to user if it permits the Consumer (in our case fooCompany) accessing to protected resources (its Curriculum Vitae).

Last bean is <oauth:client-details-service>. In this tag you define which clients you authorize to access to protected resources with previous authentication. In this case because CV company has agreed with foo company that they can connect to its Curriculum Vitae Service, a client is defined with id foo.

Now we have our application configured with OAuth. Last step is creating a controller for taking requests from /oauth/confirm_access URL.

private ClientAuthenticationCache authenticationCache = new DefaultClientAuthenticationCache();
private ClientDetailsService clientDetailsService;

@RequestMapping(value="/oauth/confirm_access")
public ModelAndView accessConfirmation(HttpServletRequest request, HttpServletResponse response) {
 ClientAuthenticationToken clientAuth = getAuthenticationCache().getAuthentication(request, response);
    if (clientAuth == null) {
      throw new IllegalStateException("No client authentication request to authorize.");
    }

    ClientDetails client = getClientDetailsService().loadClientByClientId(clientAuth.getClientId());
    TreeMap<String, Object> model = new TreeMap<String, Object>();
    model.put("auth_request", clientAuth);
    model.put("client", client);
    return new ModelAndView("access_confirmation", model);
}

This controller returns a ModelAndView object with client information and which page should be shown for granting permission to protected resources. This JSP page is called access_confirmation.jsp and the most important part is:

<div id="content">

    <% if (session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION) != null && !(session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION) instanceof UnapprovedClientAuthenticationException)) { %>
      <div class="error">
        <p>Access could not be granted. (<%= ((AuthenticationException) session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION)).getMessage() %>)</p>
      </div>
    <% } %>
    <c:remove scope="session" var="SPRING_SECURITY_LAST_EXCEPTION"/>

    <authz:authorize ifAllGranted="ROLE_USER">
      <h2>Please Confirm</h2>

      <p>You hereby authorize <c:out value="${client.clientId}"/> to access your protected resources.</p>

      <form id="confirmationForm" name="confirmationForm" action="<%=request.getContextPath() + VerificationCodeFilter.DEFAULT_PROCESSING_URL%>" method="post">
        <input name="<%=BasicUserApprovalFilter.DEFAULT_APPROVAL_REQUEST_PARAMETER%>" value="<%=BasicUserApprovalFilter.DEFAULT_APPROVAL_PARAMETER_VALUE%>" type="hidden"/>
        <label><input name="authorize" value="Authorize" type="submit"/></label>
      </form>
      <form id="denialForm" name="denialForm" action="<%=request.getContextPath() + VerificationCodeFilter.DEFAULT_PROCESSING_URL%>" method="post">
        <input name="<%=BasicUserApprovalFilter.DEFAULT_APPROVAL_REQUEST_PARAMETER%>" value="not_<%=BasicUserApprovalFilter.DEFAULT_APPROVAL_PARAMETER_VALUE%>" type="hidden"/>
        <label><input name="deny" value="Deny" type="submit"/></label>
      </form>
    </authz:authorize>
  </div>

As you can see Spring Security OAuth provides helper classes for creating confirmation form and deny form. When the result is submitted, URL /cv/oauth/user/authorize (internally managed) is called, there OAuth decides if returns protected resource (String returned by loadCV() method) to caller or not depending on what option user has chosen.

And that’s all about creating an OAuth 2 system using Spring Security OAuth. But I suppose you are wondering how to test it, so for the same price I will explain how to write the client part (Consumer) using Spring Security OAuth too.

Client application (called fooCompany) is also a SpringMVC web application with Spring Security.

Spring Security part will be ignored here.

The client application contains a home page (home.jsp) that has a link to Spring Controller that will be responsible to download Curriculum Vitae from CV site, and redirecting content to a view (show.jsp).

@RequestMapping(value="/cv")
public ModelAndView getCV() {
 String cv = cvService.getCVContent();
 Map<String, String> params = new HashMap<String, String>();
 params.put("cv", cv);
 ModelAndView modelAndView = new ModelAndView("show", params);
 return modelAndView;

}

As you can see is a simple Controller that calls a Curriculum Vitae service. This service will be responsible to connect to CV website, and download required Curriculum Vitae. Of course it deals with OAuth communication protocol too.

Service looks:

public String getCVContent() {
 byte[] content = (getCvRestTemplate().getForObject(URI.create(cvURL), byte[].class));
 return new String(content);
}

The suggested method for accessing those resources is by using Rest. For this porpose Spring Security OAuth provides an extension of RestTemplate for dealing with OAuth protocol. This class (OAuth2RestTemplate) manages connection to required resources and also manages tokens, OAuth authorization protocol, …

OAuth2RestTemplate is injected into CVService, and it is configured into root-context.xml:

<oauth:client token-services-ref="oauth2TokenServices" />

<beans:bean id="oauth2TokenServices"
 class="org.springframework.security.oauth2.consumer.token.InMemoryOAuth2ClientTokenServices" />

<oauth:resource id="cv" type="authorization_code"
 clientId="foo" accessTokenUri="http://localhost:8080/cv/oauth/authorize"
 userAuthorizationUri="http://localhost:8080/cv/oauth/user/authorize" />

 <beans:bean id="cvService" class="org.springsource.oauth.CVServiceImpl">
  <beans:property name="cvURL" value="http://localhost:8080/cv/cvs"></beans:property>
  <beans:property name="cvRestTemplate">
   <beans:bean class="org.springframework.security.oauth2.consumer.OAuth2RestTemplate">
         <beans:constructor-arg ref="cv"/>
 </beans:bean>
</beans:property>
<beans:property name="tokenServices" ref="oauth2TokenServices"></beans:property>
</beans:bean>

See that OAuth2RestTemplate is created using an OAuth resource that contains all information about where to connect for authorizing access to protected resource, and in this case is CV website, see that we are referencing an external website, although in this example we are using localhost. Also service provider URL (http://localhost:8080/cvs/cv) is set, so RestTemplate can establish a connection to content provider, and in case that authorization process ends successful, retrieving requested information.

<oauth:resource> defines OAuth resources, in this case, the name of the client (remember that this value was configured in server side client details tag for granting access to OAuth protocol). Also userAuthorizationUri is defined. This is the URI to which the user will be redirected if the user is ever needed to authorize access to the resource (this is an internal URI managed by Spring Security OAuth). And finally accessTokenUri, the URI OAuth provider endpoint that provides the access token (internal URI too).

Also creating a consumer using Spring Security OAuth is simple enough.

Now I will explain the sequence of events that happens when a user wants to give access to foo company for retrieving its Curriculum Vitae.

First of all user connects to foo website, and click on post curriculum vitae link. Then getCV method from controller is called. This method calls cvService, that at the same time creates a connection to resource URI (CV) using OAuth2RestTemplate. And this class acts as a black box, from client side, you don’t know exactly what this class will do but it returns your Curriculum Vitae stored in CV website. As you can imagine this class manages all workflow related to OAuth, like managing tokens, executing required URL redirections to get permissions, … and if all steps are performed successful, stored Curriculum Vitae in CV site will be sent to foo company site.

And that’s all steps required to allow your site to act as Service Provider using OAuth2 authorization protocol. Thanks of Spring Security folks, it is much easier that you may think at first.

Hope you find it useful.

Download ServerSide (CV)
Download ClientSide (fooCompany)

Reference: OAuth with Spring Security from our JCG partner Alex Soto at the One Jar To Rule Them All blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

16 Responses to "OAuth with Spring Security"

  1. siru vivasayee says:

    Hi Eleftheria,

    I created war file of both client and server part and deployed in a tomcat server.
    Getting the following error … what could be the possible reason 

    ERROR: org.springframework.web.context.ContextLoader – Context initialization failed
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘org.springframework.security.web.context.HttpSessionSecurityContextRepository#0′: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.security.web.context.HttpSessionSecurityContextRepository]: Constructor threw exception; nested exception is java.lang.ExceptionInInitializerError

    • siru vivasayee says:

      Changing the tomcat server resolved the issue but any how I need to check the root cause for this issue …

      Thanks

  2. Tito George says:

    I tried to run your examples. I am getting the following errors.
    cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element ‘oauth:provider’.
    and
    Multiple annotations found at this line: – cvc-complex-type.3.2.2: Attribute ‘clientId’ is not allowed to appear in element ‘oauth:client’. – cvc-complex-type.3.2.2: Attribute ‘authorizedGrantTypes’ is not allowed to appear in element ‘oauth:client’.
    I tried lot to get correct xsd version, but could not find. Could you please help?

  3. Bhaskar says:

    Hi,

    Requesting you to please upload screenshots of flow of functionalities !!

  4. Bhaskar says:

    Hi,

    Thanks A Lot for your tutorial !! it is simply AWESOME!!!!

    But i just stuck up at the last point , please look on this :::::

    When i clicked on “Authorize” i did not receive “CV” rather my console get populate with following warnings::

    WARN : org.springframework.security.oauth2.provider.verification.DefaultClientAuthenticationCache – Unable to save client authentication because the request doesn’t have a session!

    WARN : org.springframework.web.servlet.PageNotFound – No mapping found for HTTP request with URI [/cv/style.css] in DispatcherServlet with name ‘appServlet’

    WARN : org.springframework.web.client.RestTemplate – POST request for “http://localhost:8080/cv/oauth/authorize” resulted in 404 (Not found); invoking error handler

    And on browser i received following messages:

    HTTP Status 403 – Error requesting access token.

    description Access to the specified resource (Error requesting access token.) has been forbidden.

  5. Bhaskar says:

    Thanks A TON!! Its working…… :)

    • OAuthUser says:

      Can you let know how you get around this problem

      No mapping found for HTTP request with URI [/cv/] in DispatcherServlet with name ‘appServlet’

      • Anandan Rajendran says:

        Hello Friends,
        I am also getting the following error:

        org.springframework.web.servlet.PageNotFound – No mapping found for HTTP request with URI [/cv/cvs/] in DispatcherServlet with name ‘appServlet’

        Plz help me, how I can fix this issue.

        Thanks.

    • Anandan Rajendran says:

      How you fixed the problem. can you please explain me the fix.

      Thanks

  6. Himalaya says:

    Hi, Alex Soto

    The following tutorial was very much useful.
    Can you please provide a REST version of the above tutorial.

    thanks in advance

  7. Is it oauth2 implementation? If not please provide oauth2 + spring code.

  8. Maximiliano says:

    Hi Alex, I know this is an old post, but I hope you could give me a hand. I’m new to OAuth and I need to create a simple web application for track expenses, with some basic actions (user must be able to create an account and log in, list expenses, edit them, etc) with a REST API for each one, and the trick is that I need to be able to pass credentials to both the webpage and the API. So, after some research I’ve found some examples using Digest Authentication and HMAC Authentication but lot of posts also mentioned OAuth as an alternative approach, so my question is, given this scenario, would be proper to use OAuth? I mean, as far as I understand OAuth is suitable when you try to access some other application resources, but in this case if I try to login my application it would be the same application, not a different one, does it make sense..?
    Kind regards, Maximiliano

Leave a Reply


four × = 12



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close