Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add suport for Janrain Engage #62

Closed
wants to merge 6 commits into from

4 participants

@epierce

JIRA issue: CAS-1110

Added module to support authentication to social networking sites using Janrain Engage

epierce added some commits
@epierce epierce Support for authentication using Janrain engage
Adds support for the Janrain Engage
(http://www.janrain.com/products/engage) service for social logins.
b625888
@epierce epierce Enhance attribute data
Added friends list and mailing address data to the attributes extracted
from the social network profile.
2a7413b
@epierce epierce Documentation 649d878
@epierce epierce Documentation update 39b8d25
@epierce epierce Documentation update d731953
@epierce epierce Pom update 5cbeee7
@serac
Owner

Looks interesting, but at first glance this doesn't look like a good fit for including with core. There's no precedent for an integration module that supports a single product. I'm happy to consider rationale for inclusion, but that should happen on cas-dev.

@dima767

Perhaps could live here: https://github.com/Unicon/cas-addons :-)

Cheers,
D.

@serac
Owner

Works for me. I'd love to have some place to put together code that's not a good fit for core, yet somewhere that's both convenient and actively maintained.

@dima767

That was my thought - I I had to re-invent the wheel so to speak doing multiple customizations for different clients. I want cas-addons to be as open as possible, with common helpful and re-usable CAS components not currently available in CAS core with the more pragmatic approach of "less friction" of getting stuff in and releasing it as an open source lib. available in Maven central.

At the same time it could serve as a 'laboratory' for good ideas that some day might end up in the CAS core.

Cheers,
D.

@epierce

I agree that it's not something that should really be in core, but I'd like to put it someplace that people who are looking for the functionality will be able to find it easily. This is a CAS steering committee question, but any possibility of creating something like Jasig/cas-addons? Since this was written for USF, I (and USF GC) would feel more comfortable putting the code there than into a company's repo.

@battags
Owner

Anyone know what the popularity of Janrain is? There is precedent to pull in outside extensions with limited marketshare (i.e. ClearPass).

@epierce

Their customer list is pretty extensive: http://www.janrain.com/customers They claim to have deployed Engage on 350,000 websites in their marketing material.

@battags
Owner

It seems like a few universities made the list.

@serac
Owner

Let's move this discussion to cas-dev, where hopefully more folks can follow the conversation. Eric, can you start the thread?

@epierce epierce closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 28, 2012
  1. @epierce

    Support for authentication using Janrain engage

    epierce authored
    Adds support for the Janrain Engage
    (http://www.janrain.com/products/engage) service for social logins.
  2. @epierce

    Enhance attribute data

    epierce authored
    Added friends list and mailing address data to the attributes extracted
    from the social network profile.
Commits on Mar 30, 2012
  1. @epierce

    Documentation

    epierce authored
Commits on Apr 1, 2012
  1. @epierce

    Documentation update

    epierce authored
  2. @epierce

    Documentation update

    epierce authored
  3. @epierce

    Pom update

    epierce authored
This page is out of date. Refresh to see the latest.
View
159 cas-server-support-janrain/README.md
@@ -0,0 +1,159 @@
+# Janrain Engage Authentication support
+
+## What is Janrain Engage?
+> A turnkey social login and social sharing solution. Janrain Engage lets a website's visitors register or login with
+> their existing social network accounts from Facebook, Google, Twitter, Yahoo, LinkedIn or other networks, and share
+> content or their site activities with friends on multiple social networks. Additional functionality lets users
+> import their social network profile data and invite their friends to visit a website. [_wikipedia_](http://en.wikipedia.org/wiki/Janrain)
+
+__Janrain Engage is a commercial service, but the free "Basic" level allows upto 2,500 unique users per year. Please see [Janrain's website](http://www.janrain.com/) for details on account features and pricing.__
+
+
+## What features are included with this module?
+* User authentication to any social network or OpenID provider supported by Janrain Engage using [janrain4j](http://code.google.com/p/janrain4j/)
+* Profile data from the social network login are exposed as CAS user attributes
+
+## What is the difference between this module and the OAuth module?
+This module is based on the client portion of the OAuth CAS module written by Jérôme Leleu (cas-server-support-oauth), so the configuration is very similar. The main advantage of using Janrain Engage over configuring OAuth authentication directly are:
+
+* Janrain Engage integrates with over [20 identity providers](http://documentation.janrain.com/providerguide) using multiple protocols including OAuth and OpenID.
+* The list of identity providers you allow users to select is held at Janrain and can be changed on the fly without modifying any CAS configuration.
+* Profile data from the identity providers is provided in a single, consistent format.
+* Multiple social network logins can be mapped to a local account using the [account mapping API](http://documentation.janrain.com/engage/api/account-mapping-integration-guide)
+
+## Attributes provided by this module
+* ProviderName
+* PrimaryKey - for use with the [mapping API](http://documentation.janrain.com/engage/api/account-mapping-integration-guide)
+* DisplayName
+* FamilyName
+* GivenName
+* Email
+* Birthday
+* Gender
+* PhoneNumber
+* PreferredUsername
+* PhotoURL
+* Url
+* StreetAddress
+* Locality
+* PostalCode
+* Country
+* FriendList
+
+See the [Janrain provider list](https://rpxnow.com/docs/providers) for details on which attributes are released by specific social networks and Engage pricing levels
+
+## Adding Janrain Engage support to CAS
+
+1. ### Register a Janrain "social sign-in" application
+Follow Janrain's [application](http://documentation.janrain.com/application-quick-start-guide) and [social sign-in](http://documentation.janrain.com/quick-start-guide) quickstart guides. **Important: You must add the domain of your cas server to the domain whitelist in the Janrain dashboard**
+
+2. ### Add the Maven dependency
+Add the following block to `$CAS_HOME/cas-server-webapp/pom.xml`:
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>cas-server-support-janrain</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <module>cas-server-support-ldap</module>
+3. ### Configure Janrain4j
+Add this bean to `$CAS_HOME/cas-server-webapp/src/main/webapp/WEB-INF/deployerConfigContext.xml`:
+
+ <bean class="com.googlecode.janrain4j.springframework.Janrain4jConfigurer"
+ p:apiKey="JanrainAPIKey"
+ p:applicationID="JanrainApplicationID"
+ p:applicationDomain="https://example.rpxnow.com/"
+ p:tokenUrl="https://cas.example.edu:8443/cas/login" />
+Configure `p:apiKey`, `p:applicationID` and `p:applicationDomain` with the values provided in the Janrain account dashboard and `tokenUrl` is the URL for your CAS login page. See the Janrain4j [documentation](http://janrain4j.googlecode.com/svn/docs/current/apidocs/com/googlecode/janrain4j/springframework/Janrain4jConfigurer.html) for all of the available configuration options.
+
+4. ### Configure Authentication
+To authenticate using Janrain Engage, add the `JanrainAuthenticationHandler` bean to the list of authentication handlers in `$CAS_HOME/cas-server-webapp/src/main/webapp/WEB-INF/deployerConfigContext.xml`:
+
+ <property name="authenticationHandlers">
+ <list>
+ <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
+ p:httpClient-ref="httpClient" />
+ <bean class="org.jasig.cas.support.janrain.authentication.handler.support.JanrainAuthenticationHandler" />
+ </list>
+ </property>
+ </bean>
+ </list>
+ </property>
+You'll also need to add `JanrainCredentialsToPrincipalResolver` to the list of principal resolvers:
+
+ <property name="credentialsToPrincipalResolvers">
+ <list>
+ <bean class="org.jasig.cas.support.janrain.authentication.principal.JanrainCredentialsToPrincipalResolver" />
+ <bean class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" />
+ </list>
+ </property>
+
+5. ### Configure Attribute Population and Repository
+To convert the profile data received from Janrain, configure the `authenticationMetaDataPopulators` property on the `authenticationManager` bean:
+
+ <property name="authenticationMetaDataPopulators">
+ <list>
+ <bean
+ class="org.jasig.cas.support.janrain.authentication.JanrainAuthenticationMetaDataPopulator" />
+ </list>
+ </property>
+You'll also need to configure the `attributeRepository` bean:
+
+ <bean id="attributeRepository" class="org.jasig.services.persondir.support.StubPersonAttributeDao">
+ <property name="backingMap">
+ <map>
+ <entry key="DisplayName" value="DisplayName" />
+ <entry key="ProviderName" value="ProviderName" />
+ <entry key="PrimaryKey" value="PrimaryKey" />
+ <entry key="FamilyName" value="FamilyName" />
+ <entry key="GivenName" value="GivenName" />
+ <entry key="Email" value="Email" />
+ <entry key="Url" value="Url" />
+ <entry key="PhotoURL" value="PhotoURL" />
+ <entry key="PhoneNumber" value="PhoneNumber" />
+ <entry key="Gender" value="Gender" />
+ <entry key="Birthday" value="Birthday" />
+ <entry key="UTCoffset" value="UTSoffset" />
+ <entry key="StreetAddress" value="StreetAddress" />
+ <entry key="Locality" value="Locality" />
+ <entry key="PostalCode" value="PostalCode" />
+ <entry key="Country" value="Country" />
+ <entry key="PreferredUsername" value="PreferredUsername" />
+ <entry key="FriendList" value="FriendList" />
+ </map>
+ </property>
+ </bean>
+To release the attributes to CAS clients, you'll need to configure the [Service Manager](https://wiki.jasig.org/display/CASUM/Services+Management)
+6. ### Add `janrainAuthAction` to the CAS webflow
+Add `janrainAuthAction` to `$CAS_HOME/cas-server-webapp/src/main/webapp/WEB-INF/login-webflow.xml`. It should be placed at the top of the file, just before the `ticketGratingTicketExistsCheck` decision-state:
+
+ <action-state id="janrainAuthAction">
+ <evaluate expression="janrainAuthAction" />
+ <transition on="success" to="sendTicketGrantingTicket" />
+ <transition on="error" to="ticketGrantingTicketExistsCheck" />
+ </action-state>
+To define the `janrainAuthAction` bean, add it to `$CAS_HOME/cas-server-webapp/src/main/webapp/WEB-INF/cas-servlet.xml`:
+
+ <bean id="janrainAuthAction" class="org.jasig.cas.support.janrain.web.flow.JanrainAuthAction">
+ <property name="centralAuthenticationService" ref="centralAuthenticationService" />
+ </bean>
+7. ### Modify the login page
+First, add the janrain4j taglib to the top of `$CAS_HOME/cas-server-webapp/src/main/webapp/WEB-INF/view/jsp/default/ui/casLoginView.jsp`:
+
+ <%@ taglib prefix="janrain" uri="http://janrain4j.googlecode.com/tags" %>
+Next, you'll need to replace the username and password for with this tag:
+
+ <janrain:signInEmbedded />
+ Here is a simple `casLoginView.jsp`:
+
+ <%@ taglib prefix="janrain" uri="http://janrain4j.googlecode.com/tags" %>
+
+ <%@ page contentType="text/html; charset=UTF-8" %>
+ <jsp:directive.include file="includes/top.jsp" />
+ <janrain:signInEmbedded />
+ <p class="fl-panel fl-note fl-bevel-white fl-font-size-80">
+ <spring:message code="screen.welcome.security" />
+ </p>
+ <jsp:directive.include file="includes/bottom.jsp" />
+
View
40 cas-server-support-janrain/pom.xml
@@ -0,0 +1,40 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>org.jasig.cas</groupId>
+ <artifactId>cas-server</artifactId>
+ <version>3.5.0-RC1-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.jasig.cas</groupId>
+ <artifactId>cas-server-support-janrain</artifactId>
+ <packaging>jar</packaging>
+ <name>JA-SIG CAS Janrain Support</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jasig.cas</groupId>
+ <artifactId>cas-server-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.webflow</groupId>
+ <artifactId>spring-webflow</artifactId>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.googlecode.janrain4j</groupId>
+ <artifactId>janrain4j</artifactId>
+ <version>1.1.0</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+
+ </plugins>
+ </build>
+
+</project>
View
47 ...n/src/main/java/org/jasig/cas/support/janrain/authentication/JanrainAuthenticationMetaDataPopulator.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012 The JA-SIG Collaborative
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jasig.cas.support.janrain.authentication;
+
+import org.jasig.cas.authentication.Authentication;
+import org.jasig.cas.authentication.AuthenticationMetaDataPopulator;
+import org.jasig.cas.authentication.MutableAuthentication;
+import org.jasig.cas.authentication.principal.Credentials;
+import org.jasig.cas.authentication.principal.Principal;
+import org.jasig.cas.authentication.principal.SimplePrincipal;
+import org.jasig.cas.support.janrain.authentication.principal.JanrainCredentials;
+
+/**
+ * This class is a meta data populator for authentication using Janrain Engage.
+ *
+ * @author Eric Pierce
+ * @since 3.5.0
+ */
+public final class JanrainAuthenticationMetaDataPopulator implements AuthenticationMetaDataPopulator {
+
+ public Authentication populateAttributes(Authentication authentication, Credentials credentials) {
+ if (credentials instanceof JanrainCredentials) {
+ JanrainCredentials janrainCredentials = (JanrainCredentials) credentials;
+ final Principal simplePrincipal = new SimplePrincipal(authentication.getPrincipal().getId(),
+ janrainCredentials.getUserAttributes());
+ final MutableAuthentication mutableAuthentication = new MutableAuthentication(simplePrincipal,
+ authentication
+ .getAuthenticatedDate());
+ mutableAuthentication.getAttributes().putAll(authentication.getAttributes());
+ return mutableAuthentication;
+ }
+ return authentication;
+ }
+}
View
78 ...main/java/org/jasig/cas/support/janrain/authentication/handler/support/JanrainAuthenticationHandler.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2012 The JA-SIG Collaborative
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jasig.cas.support.janrain.authentication.handler.support;
+
+import com.googlecode.janrain4j.api.engage.EngageFailureException;
+import com.googlecode.janrain4j.api.engage.ErrorResponeException;
+import com.googlecode.janrain4j.api.engage.EngageService;
+import com.googlecode.janrain4j.api.engage.EngageServiceFactory;
+import com.googlecode.janrain4j.api.engage.response.UserDataResponse;
+
+import org.jasig.cas.authentication.handler.AuthenticationException;
+import org.jasig.cas.authentication.handler.support.AbstractPreAndPostProcessingAuthenticationHandler;
+import org.jasig.cas.authentication.principal.Credentials;
+import org.jasig.cas.support.janrain.authentication.principal.JanrainCredentials;
+import org.springframework.webflow.context.ExternalContextHolder;
+
+/**
+ * This handler authenticates Janrain credentials : it submits the token to the Janrain auth_info webservice
+ * using the janrain4j library.
+ *
+ * @author Eric Pierce
+ * @since 3.5.0
+ */
+public final class JanrainAuthenticationHandler extends AbstractPreAndPostProcessingAuthenticationHandler {
+
+ private EngageService engageService = EngageServiceFactory.getEngageService();
+
+ public boolean supports(Credentials credentials) {
+ return credentials != null && (JanrainCredentials.class.isAssignableFrom(credentials.getClass()));
+ }
+
+ @Override
+ protected boolean doAuthentication(Credentials credentials) throws AuthenticationException {
+ JanrainCredentials credential = (JanrainCredentials) credentials;
+ log.debug("Got Credential : {}", credential);
+
+ try {
+ UserDataResponse userDataResponse = engageService.authInfo(credential.getToken(), true);
+
+ if (userDataResponse.getProfile() != null ) {
+ log.debug("userDataResponse : {}", userDataResponse.getResponseAsJSON());
+ credential.setIdentifier(userDataResponse.getProfile().getIdentifier());
+ if(userDataResponse.getProfile() != null) {
+ if(userDataResponse.getFriends() != null) {
+ credential.setUserAttributes(userDataResponse.getProfile(), userDataResponse.getFriends());
+ } else {
+ credential.setUserAttributes(userDataResponse.getProfile());
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+ catch (EngageFailureException e) {
+ log.warn(e.getMessage());
+ return false;
+ }
+ catch (ErrorResponeException e) {
+ log.warn(e.getMessage());
+ return false;
+ }
+ }
+
+}
View
161 ...ort-janrain/src/main/java/org/jasig/cas/support/janrain/authentication/principal/JanrainCredentials.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2012 The JA-SIG Collaborative
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jasig.cas.support.janrain.authentication.principal;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+
+import org.springframework.util.Assert;
+
+import org.apache.commons.lang.StringUtils;
+
+import org.jasig.cas.authentication.principal.Credentials;
+import com.googlecode.janrain4j.api.engage.response.profile.Profile;
+
+/**
+ * This class creates a CAS-compatible credential using data from Janrain Engage
+ *
+ * @author Eric Pierce
+ * @since 3.5.0
+ */
+public final class JanrainCredentials implements Credentials {
+
+ private static final long serialVersionUID = 2749515040385101768L;
+
+ /** The token that will sent to the Janrain user_info service */
+ private String token;
+
+ private String identifier;
+
+ private Map<String, Object> userAttributes;
+
+ public JanrainCredentials(final String token) {
+ Assert.notNull(token, "token cannot be null");
+ this.token = token;
+ }
+
+ public final void setToken(final String token) {
+ this.token = token;
+ }
+
+ public final String getToken() {
+ return this.token;
+ }
+
+ public final void setIdentifier(final String identifier) {
+ this.identifier = identifier;
+ }
+
+ public final String getIdentifier() {
+ return this.identifier;
+ }
+
+ /**
+ * Create a map of the User's Attributes from a janrain4j Profile object
+ *
+ * @param userProfile
+ * @param friendList
+ */
+ public void setUserAttributes(Profile userProfile, List<String> friendList) {
+
+ Map<String,Object> userAttributes = new HashMap<String,Object>();
+
+ if(userProfile.getProviderName() != null){
+ userAttributes.put("ProviderName", userProfile.getProviderName());
+ }
+ if(userProfile.getPrimaryKey() != null){
+ userAttributes.put("PrimaryKey", userProfile.getPrimaryKey());
+ }
+ if(userProfile.getDisplayName() != null){
+ userAttributes.put("DisplayName", userProfile.getDisplayName());
+ }
+ if(userProfile.getName() != null) {
+ if(userProfile.getName().getFamilyName() != null){
+ userAttributes.put("FamilyName", userProfile.getName().getFamilyName());
+ }
+ if(userProfile.getName().getGivenName() != null){
+ userAttributes.put("GivenName", userProfile.getName().getGivenName());
+ }
+ }
+ if(userProfile.getBirthday() != null){
+ userAttributes.put("Birthday", userProfile.getBirthday());
+ }
+ if(userProfile.getVerifiedEmail() != null){
+ userAttributes.put("Email", userProfile.getVerifiedEmail());
+ }
+ if(userProfile.getProviderName() != null){
+ userAttributes.put("PhoneNumber", userProfile.getPhoneNumber());
+ }
+ if(userProfile.getPreferredUsername() != null){
+ userAttributes.put("PreferredUsername", userProfile.getPreferredUsername());
+ }
+ if(userProfile.getPhoto() != null){
+ userAttributes.put("PhotoURL", userProfile.getPhoto());
+ }
+ if(userProfile.getUrl() != null){
+ userAttributes.put("Url", userProfile.getUrl());
+ }
+ if(userProfile.getUtcOffset() != null){
+ userAttributes.put("UTCoffset", userProfile.getUtcOffset());
+ }
+ if(userProfile.getGender() != null){
+ userAttributes.put("Gender", userProfile.getGender());
+ }
+ if(userProfile.getAddress() != null) {
+ if(userProfile.getAddress().getCountry() != null){
+ userAttributes.put("Country", userProfile.getAddress().getCountry());
+ }
+ if(userProfile.getAddress().getLocality() != null){
+ userAttributes.put("Locality", userProfile.getAddress().getLocality());
+ }
+ if(userProfile.getAddress().getPostalCode() != null){
+ userAttributes.put("PostalCode", userProfile.getAddress().getPostalCode());
+ }
+ if(userProfile.getAddress().getStreetAddress() != null){
+ userAttributes.put("StreetAddress", userProfile.getAddress().getStreetAddress());
+ }
+ }
+ if(friendList.size() > 0){
+ userAttributes.put("FriendList", friendList);
+ }
+ this.userAttributes = userAttributes;
+ }
+
+ /**
+ * Alternate method used when the friend list is not available.
+ *
+ * @param userProfile
+ *
+ */
+ public void setUserAttributes(Profile userProfile) {
+ setUserAttributes(userProfile, new ArrayList<String>());
+ }
+
+
+ public final Map<String, Object> getUserAttributes() {
+ return this.userAttributes;
+ }
+
+ public String toString() {
+ if (StringUtils.isNotBlank(this.identifier)){
+ return this.identifier;
+ } else {
+ return "[janrain token: " + this.token + "]";
+ }
+ }
+}
View
41 ...n/java/org/jasig/cas/support/janrain/authentication/principal/JanrainCredentialsToPrincipalResolver.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012 The JA-SIG Collaborative
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jasig.cas.support.janrain.authentication.principal;
+
+import org.jasig.cas.authentication.principal.AbstractPersonDirectoryCredentialsToPrincipalResolver;
+import org.jasig.cas.authentication.principal.Credentials;
+import org.jasig.cas.authentication.principal.CredentialsToPrincipalResolver;
+
+/**
+ * This class resolves the principal (OpenID URL) from the Janrain credential (token that is passed to the auth_info webservice)
+ *
+ * @author Eric Pierce
+ * @since 3.5.0
+ */
+public final class JanrainCredentialsToPrincipalResolver extends AbstractPersonDirectoryCredentialsToPrincipalResolver
+ implements CredentialsToPrincipalResolver {
+
+ @Override
+ protected String extractPrincipalId(final Credentials credentials) {
+ JanrainCredentials janrainCredentials = (JanrainCredentials) credentials;
+ String principal = janrainCredentials.getIdentifier();
+ return principal;
+ }
+
+ public boolean supports(final Credentials credentials) {
+ return credentials != null && (JanrainCredentials.class.isAssignableFrom(credentials.getClass()));
+ }
+}
View
87 cas-server-support-janrain/src/main/java/org/jasig/cas/support/janrain/web/flow/JanrainAuthAction.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012 The JA-SIG Collaborative
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jasig.cas.support.janrain.web.flow;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import javax.validation.constraints.NotNull;
+
+import org.apache.commons.lang.StringUtils;
+import org.jasig.cas.CentralAuthenticationService;
+import org.jasig.cas.authentication.principal.Service;
+import org.jasig.cas.ticket.TicketException;
+import org.jasig.cas.web.support.WebUtils;
+
+import org.jasig.cas.support.janrain.authentication.principal.JanrainCredentials;
+
+import org.springframework.webflow.action.AbstractAction;
+import org.springframework.webflow.execution.Event;
+import org.springframework.webflow.execution.RequestContext;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * This class represents an action in the webflow to retrieve user information from the Janrain Engage service. If the token
+ * parameter exists in the web request, it is used to create a new JanrainCredential.
+ *
+ * @author Eric Pierce
+ * @since 3.5.0
+ */
+public final class JanrainAuthAction extends AbstractAction {
+
+ private static final String TOKEN_PARAMETER = "token";
+
+ @NotNull
+ private CentralAuthenticationService centralAuthenticationService;
+
+ @Override
+ protected Event doExecute(RequestContext context) throws Exception {
+ HttpServletRequest request = WebUtils.getHttpServletRequest(context);
+ HttpSession session = request.getSession();
+
+ // get token value
+ String tokenValue = request.getParameter(TOKEN_PARAMETER);
+
+ // Token exists, authenticate it with Janrain
+ if (StringUtils.isNotBlank(tokenValue)) {
+
+ // get credential
+ @SuppressWarnings("unchecked")
+ JanrainCredentials credential = new JanrainCredentials(tokenValue);
+
+ // retrieve service from session and put it into webflow
+ Service service = (Service) session.getAttribute("service");
+ context.getFlowScope().put("service", service);
+
+ try {
+ WebUtils.putTicketGrantingTicketInRequestScope(context, this.centralAuthenticationService
+ .createTicketGrantingTicket(credential));
+ return success();
+ } catch (final TicketException e) {
+ return error();
+ }
+ } else {
+ // put service in session from flow scope
+ Service service = (Service) context.getFlowScope().get("service");
+ session.setAttribute("service", service);
+ }
+
+ return error();
+ }
+
+ public void setCentralAuthenticationService(CentralAuthenticationService centralAuthenticationService) {
+ this.centralAuthenticationService = centralAuthenticationService;
+ }
+}
View
1  pom.xml
@@ -612,6 +612,7 @@ pTSqrOnmqmUUnopqmvummmmmmUUnopqmvummmmmmUUA1jJ
<module>cas-server-core</module>
<module>cas-server-webapp</module>
<module>cas-server-support-generic</module>
+ <module>cas-server-support-janrain</module>
<module>cas-server-support-jdbc</module>
<module>cas-server-support-ldap</module>
<module>cas-server-support-legacy</module>
Something went wrong with that request. Please try again.