Details

    • Type: New Feature New Feature
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 3.5.0 RC1, 3.5.0
    • Component/s: None
    • Labels:
      None

      Description

      Hello,

      As I did some testing with OAuth protocol, I extract my code to create a cas-server-module-oauth. I propose to use it as a starting point for real integration of OAuth protocol in CAS.

      + Overview of my code :
      I use the Scribe library (https://github.com/fernandezpablo85/scribe-java) to integrate with social networks. I only wrote an implementation for facebook, but other implementations should not be too hard.
      I create the notion of provider : a provider is Facebook for example, it is a way to authenticate outside the CAS server. I use a controller as a callback url for provider which is outside the webflow.

      + The classes in the module :
      org.jasig.cas.support.auth.web.OAuthController : it is the controller where the provider sends back the user after authentication in its own system
      org.jasig.cas.support.oauth.authentication.handler.support.OAuthAuthenticationHandler : it is an authentication handler for oauth credentials; in fact, it does nothing, it returns always true as credentials are created when the user is already authenticated
      org.jasig.cas.support.oauth.authentication.principal.OAuthCredentials : it is the credentials after the user authenticates in the social network (by the provider) : provider name + user identifier
      org.jasig.cas.support.oauth.authentication.principal.OAuthCredentialsToPrincipalResolver : it is a principal resolver : for oauth provider, it is the name of the provider, the character '#' and the user identifier
      org.jasig.cas.support.oauth.provider.OAuthIdentityProvider : it represents the contract of an oauth provider
      org.jasig.cas.support.oauth.provider.OAuthIdentityProvider : it is a common implementation of oauth provider (it uses the Scribe library)
      org.jasig.cas.support.oauth.provider.FacebookIdentityProviderImpl : it is the implementation dedicated to facebook

      + The configuration needed in CAS server :

      • in login page (casLoginView.jsp), add the link to facebook authentication and needed imports :
        <%
        ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(application);
        try { FacebookIdentityProviderImpl facebookProvider = (FacebookIdentityProviderImpl)applicationContext.getBean("facebookProvider"); %><a href="<%=facebookProvider.getAuthorizationUrl()%>">Authenticate with Facebook</a><% }

        catch (Exception e)

        { e.printStackTrace(); }

        %>

      • add a facebook provider to applicationContext.xml (the id and the secret are the information given by facebook when you create a facebook application) :
        <bean id="facebookProvider" class="org.jasig.cas.support.oauth.provider.FacebookIdentityProviderImpl">
        <property name="id" value="xxx" />
        <property name="secret" value="xxx" />
        <property name="callbackUrl" value="http://myserver/cas/facebook" />
        </bean>
      • add a facebook controller to cas-servlet.xml :
        <bean id="facebookController" class="org.jasig.cas.support.auth.web.OAuthController"
        p:centralAuthenticationService-ref="centralAuthenticationService"
        p:ticketGrantingTicketCookieGenerator-ref="ticketGrantingTicketCookieGenerator"
        p:provider-ref="facebookProvider" />
      • and the mapping needed in handlerMappingC bean :
        <prop
        key="/facebook">
        facebookController
        </prop>
      • and in web.xml :
        <servlet-mapping>
        <servlet-name>cas</servlet-name>
        <url-pattern>/facebook</url-pattern>
        </servlet-mapping>
      • add the cas-server-support-oauth dependency to cas-server-webapp pom.xml :
        <dependency>
        <groupId>org.jasig.cas</groupId>
        <artifactId>cas-server-support-oauth</artifactId>
        <version>$ {project.version}

        </version>
        </dependency>

      With this configuration, I have a link "Authenticate with Facebook" on the login page, I click on it, authenticate in facebook and come back to CAS and I am authenticated in CAS.

      + Problems :
      I think the main problem of my code is the controller which is the callback url of the provider : it is outside the CAS webflow and therefore, I have to create by myself the CAS identity and I don't have the service of the login page (maybe I could get it in the session but it is not a proper way).
      I think it would better to have this callback url integrated in the webflow CAS.
      Errors are not really handled in the controller and the code has to be tested fully.

      Don't hesitate to ask me questions.
      Regards,
      Jerome

      1. applicationContext.xml
        4 kB
        Naveen Phougat
      2. cas-server-support-oauth_with_scribeup.pdf
        175 kB
        Jérôme Leleu
      3. cas-server-support-oauth.pdf
        207 kB
        Jérôme Leleu
      4. catalina.2011-09-01.log
        409 kB
        Chathuranga Tennakoon
      5. catalina.out
        291 kB
        Chathuranga Tennakoon
      6. localhost.2011-09-01.log
        287 kB
        Chathuranga Tennakoon
      7. localhost.2011-09-01.log
        287 kB
        Chathuranga Tennakoon
      8. patch_module_oauth_2.txt
        16 kB
        Jérôme Leleu
      9. patch_module_oauth.txt
        17 kB
        Jérôme Leleu

        Activity

        Hide
        waynes added a comment -

        hi jerome:

        Thank you for the contribution you made on this module.

        We've already released your module into our production, just want to share good news with contributors, this is our site.

        http://www.acoolme.com

        Show
        waynes added a comment - hi jerome: Thank you for the contribution you made on this module. We've already released your module into our production, just want to share good news with contributors, this is our site. http://www.acoolme.com
        Hide
        Jérôme Leleu added a comment -

        Hi Waynes,

        It's nice to see a contribution in production.
        I logged in acoolme.com through Facebook and that's pretty cool.
        For your information, the cas-server-support-oauth module is based on ScribeUP 1.0.0 (https://github.com/leleuj/scribe-up).
        I'm developping ScribeUP 1.1.0 with more complete profiles and more easier profile objects available even in CAS applications. I plan to integrate this new version in CAS server in the future (post 3.5.0 release).
        If you have any suggestion, don't hesitate...
        Best regards,
        Jérôme

        Show
        Jérôme Leleu added a comment - Hi Waynes, It's nice to see a contribution in production. I logged in acoolme.com through Facebook and that's pretty cool. For your information, the cas-server-support-oauth module is based on ScribeUP 1.0.0 ( https://github.com/leleuj/scribe-up ). I'm developping ScribeUP 1.1.0 with more complete profiles and more easier profile objects available even in CAS applications. I plan to integrate this new version in CAS server in the future (post 3.5.0 release). If you have any suggestion, don't hesitate... Best regards, Jérôme
        Hide
        David Nyffenegger added a comment -

        Hi Jérôme

        I have another contribution to OAuthAuthenticationMetaDataPopulator. My use-case is to add additional attributes from a database to the principal e.g. using MultiRowJdbcPersonAttributeDao.
        With the current implementation, the OAuthAuthenticationMetaDataPopulator ignores the attributes of the existing principal.
        When creating the new principal, the attributes from the existing should also been taken into account:

        Map<String, Object> attributes = new HashMap<String, Object(oauthCredentials.getUserProfile().getAttributes());
        attributes.putAll(authentication.getPrincipal().getAttributes());
        final Principal simplePrincipal = new SimplePrincipal(authentication.getPrincipal().getId(),attributes);
        

        Maybe also the otherway around so that the OAuth attributes overwrites the existing attribs - just in case.
        What do you think?

        David

        Show
        David Nyffenegger added a comment - Hi Jérôme I have another contribution to OAuthAuthenticationMetaDataPopulator . My use-case is to add additional attributes from a database to the principal e.g. using MultiRowJdbcPersonAttributeDao . With the current implementation, the OAuthAuthenticationMetaDataPopulator ignores the attributes of the existing principal. When creating the new principal, the attributes from the existing should also been taken into account: Map< String , Object > attributes = new HashMap< String , Object (oauthCredentials.getUserProfile().getAttributes()); attributes.putAll(authentication.getPrincipal().getAttributes()); final Principal simplePrincipal = new SimplePrincipal(authentication.getPrincipal().getId(),attributes); Maybe also the otherway around so that the OAuth attributes overwrites the existing attribs - just in case. What do you think? David
        Hide
        Jérôme Leleu added a comment -

        Hi,

        Your use case makes sense. There are a lot of possible scenarios when it comes to connected identities : be sure that a local account references a delegated authentication for example.
        So far, I didn't spent enough time to propose a well-design architecture to address "links" between multiples identities/attributes. A custom implementation will fit well.
        Best regards,
        Jérôme

        Show
        Jérôme Leleu added a comment - Hi, Your use case makes sense. There are a lot of possible scenarios when it comes to connected identities : be sure that a local account references a delegated authentication for example. So far, I didn't spent enough time to propose a well-design architecture to address "links" between multiples identities/attributes. A custom implementation will fit well. Best regards, Jérôme
        Hide
        David Nyffenegger added a comment -

        Hi Jérôme,
        Thank you for your quick response. If my use-case isn't a standard scenario, then it really makes sense to write a custom metadata populator. I just wasn't sure...
        Regards,
        David

        Show
        David Nyffenegger added a comment - Hi Jérôme, Thank you for your quick response. If my use-case isn't a standard scenario, then it really makes sense to write a custom metadata populator. I just wasn't sure... Regards, David

          People

          • Assignee:
            Jérôme Leleu
            Reporter:
            Jérôme Leleu
          • Votes:
            1 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: