4 Replies Latest reply on Jul 21, 2011 7:07 AM by anilksharma.anilksharma.btinternet.com

    Seam and OAuth

    rtolsson

      Hi,


      I am trying to implement OAuth-based security for a set of Seam resources that are exposed via a RESTful interface. I am using Seam 2.2.0 for my resources and RESTEasy 1.2 for the REST related stuff.


      The OAuth token setup process has been implemented and even though it's not feature complete, one may get hold of a proper access token.


      My next task is to let the external application access the resources. If the resource call is accompanied with a valid access token, that call should be made as the user that is associated with that particular token.


      The problem is that I can't figure out how to set up the proper Seam Identity context for each resource call (web service request).


      The application's web.xml file


      <?xml version="1.0" encoding="UTF-8"?>
      <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
          <!-- Seam listener -->
          <listener>
              <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
          </listener>
      
          <!-- The OAuth Servlet handles token exchange -->
          <servlet>
            <servlet-name>OAuth</servlet-name>
            <servlet-class>org.jboss.resteasy.auth.oauth.OAuthServlet</servlet-class>
          </servlet>
      
          <!-- This will be the base for the token exchange endpoint URL -->
          <servlet-mapping>
            <servlet-name>OAuth</servlet-name>
            <url-pattern>/oauth/*</url-pattern>
          </servlet-mapping>
      
          <context-param>
              <param-name>oauth.provider.provider-class</param-name>
              <param-value>com.mydomain.oauth.OAuthProvider</param-value>
          </context-param>
      
          <context-param>
              <param-name>oauth.provider.tokens.request</param-name>
              <param-value>/request_token</param-value>
          </context-param>
      
          <context-param>
              <param-name>oauth.provider.tokens.access</param-name>
              <param-value>/access_token</param-value>
          </context-param>
      
          <!-- The OAuth Filter handles authentication for protected resources -->
          <filter>
              <filter-name>OAuth Filter</filter-name>
              <filter-class>org.jboss.resteasy.auth.oauth.OAuthFilter</filter-class>
          </filter>
      
          <!-- This defines the URLs which should require OAuth authentication for your protected resources -->
          <filter-mapping>
              <filter-name>OAuth Filter</filter-name>
              <url-pattern>/seam/resources/*</url-pattern>
          </filter-mapping>
      
          <servlet>
              <servlet-name>Seam Resource Servlet</servlet-name>
              <servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>
          </servlet>
      
          <servlet-mapping>
              <servlet-name>Seam Resource Servlet</servlet-name>
              <url-pattern>/seam/resources/*</url-pattern>
          </servlet-mapping>
      </web-app>



      Debugging a web service call, one can see that the RESTEasy OAuthFilter is executed and it:



      1. validates the access token

      2. gets all user info from the token (name and roles)

      3. modifies the HTTP request so that the getUserPrincipal() method returns the user associated with the token

      4. calls the next filter in the request filter chain



      This doesn't seem to be enough though. When the Seam resource servlet a bit later tries to dispatch the resource method, it fails because there is no user logged in. The resource method is annotated with @Restrict(#{identity.loggedIn}).


      Is there anyone out there that has any experience with the combination Seam, RESTEasy and OAuth? How should one think to make this identity/login handling work on a per request/token basis? Maybe I've missed something very basic or fundamental regarding Seam/REST integration?


      Thanks in advance for any information that can make me get a bit further implementing this.


      Regards


      Roland

        • 1. Re: Seam and OAuth
          dstockdill

          Seam has nicely integrated most of the RESTEasy functionality, but it doesn't integrate the RESTEasy OAuth module. I've implemented parts of the RESTEasy OAuth module for our Seam app.  You'll likely need to implement the following:


          1. A custom filter to set up the Seam identity. See OAuthFilter.java in the RESTEasy source for an example from the OAuth side of things, and either OpenId.java or AuthenticationFilter.java from the Seam source for examples of setting up the identity.  Here's an example of populating the Seam identity from a principle:



          identity.acceptExternallyAuthenticatedPrincipal(
            new org.jboss.seam.security.SimplePrincipal(username)
          ); 



          You might be able to get away with chaining the RESTEasy OAuthFilter together with your own filter which grabs the principle provided by RESTEasy and populates the Seam identity from it.  For my own use case I couldn't do this because I needed support for Open Social signed requests (a variation of OAuth). As a result I created a replacement for the RESTEasy OAuthFilter.


          Given that you are using REST, you are presumably stateless between OAuth requests so you'll probably want to close the HTTP session in the filter at the end of the request.


          2. Storage of the tokens and implementation of the /requestToken, /accessToken and /authorise endpoints. See RESTEasy authentication guide. You  might have done this already.


          • 2. Re: Seam and OAuth
            rtolsson

            Thanks a lot, it seems to work just fine. Like you I ended up implementing a replacement for the OAuthFilter class, because some additional identity setup was needed.


            Cheers
            Roland

            • 3. Re: Seam and OAuth
              anilksharma.anilksharma.btinternet.com

              Hi Roland and Duncan -


              I realise this thread ended some time ago, but I was hoping I could pick it up again and ask for some advice?


              I'm implementing OAuth for a project based on Seam 2.2.


              I've think I've implemented an OAuthProvider and now want to test it, but I don't seem to be able to easily. The app runs on my local machine and so isn't accessible by the online Oauth test clients that are available. I was just wondering how you went about testing your system. Did you write your own client? or is there some downloadable executable (similar to something like SoapUI) that I could run on my desktop which I could hit my oauth urls with?


              Sorry if this is a dumb question, I've had a look round the web and can see plenty of oauth client libraries, but my worry about this is that as I'm so new to OAuth that if there is a problem then I won't know whether the problem is with my server implementation or whether it's the client I've written - hence I'd like to use a client that someone else has written that I could rely on more!


              Sorry if it's a dumb question - as you may have gathered I'm not too clued up on this topic just yet.


              Many thanks in advance for your help anyway,
              Anil.



              • 4. Re: Seam and OAuth
                anilksharma.anilksharma.btinternet.com

                Hi -


                Just to update the thread for anyone else needing this information, I've created a basic OAuth client using the oauth signpost library, available from http://code.google.com/p/oauth-signpost/.


                The examples provide a basic client which hopefully I'll be able to customise in order to create a client to interact with my server.


                HTH
                Anil.