Updated to social

This commit is contained in:
Stian Thorgersen 2013-07-24 12:29:43 +01:00
parent ae045d4822
commit 75dd88cf5d
9 changed files with 59 additions and 34 deletions

View file

@ -31,30 +31,26 @@
<dependency> <dependency>
<groupId>org.jboss.spec.javax.ejb</groupId> <groupId>org.jboss.spec.javax.ejb</groupId>
<artifactId>jboss-ejb-api_3.2_spec</artifactId> <artifactId>jboss-ejb-api_3.2_spec</artifactId>
<scope>provided</scope>
<version>1.0.0.Alpha2</version> <version>1.0.0.Alpha2</version>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.api-client</groupId> <groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId> <artifactId>google-api-client</artifactId>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.http-client</groupId> <groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson</artifactId> <artifactId>google-http-client-jackson</artifactId>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.apis</groupId> <groupId>com.google.apis</groupId>
<artifactId>google-api-services-oauth2</artifactId> <artifactId>google-api-services-oauth2</artifactId>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.twitter4j</groupId> <groupId>org.twitter4j</groupId>
<artifactId>twitter4j-core</artifactId> <artifactId>twitter4j-core</artifactId>
<scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View file

@ -37,7 +37,7 @@ public interface IdentityProvider {
String getId(); String getId();
@XmlTransient @XmlTransient
URI getAuthUrl(IdentityProviderCallback callback); URI getAuthUrl(IdentityProviderCallback callback) throws IdentityProviderException;
String getName(); String getName();
@ -45,6 +45,6 @@ public interface IdentityProvider {
boolean isCallbackHandler(IdentityProviderCallback callback); boolean isCallbackHandler(IdentityProviderCallback callback);
@XmlTransient @XmlTransient
User processCallback(IdentityProviderCallback callback); User processCallback(IdentityProviderCallback callback) throws IdentityProviderException;
} }

View file

@ -0,0 +1,6 @@
package org.keycloak.social;
public class IdentityProviderErrors {
public static final String INVALID_PROVIDER = "invalid_provider";
public static final String PROVIDER_ERROR = "provider_error";
}

View file

@ -0,0 +1,11 @@
package org.keycloak.social;
public class IdentityProviderException extends Exception {
private static final long serialVersionUID = 1L;
public IdentityProviderException(Throwable cause) {
super(cause);
}
}

View file

@ -24,9 +24,9 @@ package org.keycloak.social.google;
import java.net.URI; import java.net.URI;
import java.util.UUID; import java.util.UUID;
import org.jboss.resteasy.logging.Logger;
import org.keycloak.social.IdentityProvider; import org.keycloak.social.IdentityProvider;
import org.keycloak.social.IdentityProviderCallback; import org.keycloak.social.IdentityProviderCallback;
import org.keycloak.social.IdentityProviderException;
import org.picketlink.idm.model.SimpleUser; import org.picketlink.idm.model.SimpleUser;
import org.picketlink.idm.model.User; import org.picketlink.idm.model.User;
@ -46,8 +46,6 @@ public class GoogleProvider implements IdentityProvider {
private static final JacksonFactory JSON_FACTORY = new JacksonFactory(); private static final JacksonFactory JSON_FACTORY = new JacksonFactory();
private static final Logger log = Logger.getLogger(GoogleProvider.class);
private static final NetHttpTransport TRANSPORT = new NetHttpTransport(); private static final NetHttpTransport TRANSPORT = new NetHttpTransport();
@Override @Override
@ -81,7 +79,7 @@ public class GoogleProvider implements IdentityProvider {
} }
@Override @Override
public User processCallback(IdentityProviderCallback callback) { public User processCallback(IdentityProviderCallback callback) throws IdentityProviderException {
String code = callback.getQueryParam("code"); String code = callback.getQueryParam("code");
try { try {
@ -109,8 +107,7 @@ public class GoogleProvider implements IdentityProvider {
return user; return user;
} catch (Exception e) { } catch (Exception e) {
log.error("Failed to process callback", e); throw new IdentityProviderException(e);
return null;
} }
} }

View file

@ -0,0 +1,9 @@
package org.keycloak.social.resources;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("social/api")
public class SocialApplication extends Application {
}

View file

@ -41,8 +41,11 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.UriInfo;
import org.jboss.resteasy.logging.Logger;
import org.keycloak.social.IdentityProvider; import org.keycloak.social.IdentityProvider;
import org.keycloak.social.IdentityProviderCallback; import org.keycloak.social.IdentityProviderCallback;
import org.keycloak.social.IdentityProviderErrors;
import org.keycloak.social.IdentityProviderException;
import org.keycloak.social.IdentityProviderState; import org.keycloak.social.IdentityProviderState;
import org.keycloak.social.util.UriBuilder; import org.keycloak.social.util.UriBuilder;
import org.picketlink.idm.model.Attribute; import org.picketlink.idm.model.Attribute;
@ -51,9 +54,11 @@ import org.picketlink.idm.model.User;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/ */
@Path("social") @Path("")
public class SocialResource { public class SocialResource {
private static final Logger log = Logger.getLogger(SocialResource.class);
// TODO This is just temporary - need to either save state variables somewhere they can be flushed after a timeout, or // TODO This is just temporary - need to either save state variables somewhere they can be flushed after a timeout, or
// alternatively they could be saved in http session, but that is probably not a good idea // alternatively they could be saved in http session, but that is probably not a good idea
private static final Map<String, IdentityProviderState> states = new HashMap<String, IdentityProviderState>(); private static final Map<String, IdentityProviderState> states = new HashMap<String, IdentityProviderState>();
@ -89,9 +94,12 @@ public class SocialResource {
callback.setProviderState(getProviderState(provider)); callback.setProviderState(getProviderState(provider));
if (provider.isCallbackHandler(callback)) { if (provider.isCallbackHandler(callback)) {
User user = provider.processCallback(callback); User user = null;
if (user == null) { try {
break; user = provider.processCallback(callback);
} catch (IdentityProviderException e) {
log.warn("Failed to process callback", e);
redirectToLogin(application, IdentityProviderErrors.PROVIDER_ERROR);
} }
String providerUsername = user.getLoginName(); String providerUsername = user.getLoginName();
@ -135,6 +143,7 @@ public class SocialResource {
@GET @GET
@Path("providers") @Path("providers")
@Produces(MediaType.APPLICATION_JSON)
public List<IdentityProvider> getProviders() { public List<IdentityProvider> getProviders() {
List<IdentityProvider> providers = new LinkedList<IdentityProvider>(); List<IdentityProvider> providers = new LinkedList<IdentityProvider>();
Iterator<IdentityProvider> itr = ServiceRegistry.lookupProviders(IdentityProvider.class); Iterator<IdentityProvider> itr = ServiceRegistry.lookupProviders(IdentityProvider.class);
@ -170,13 +179,12 @@ public class SocialResource {
} }
private Response redirectToLogin(String application, String error) { private Response redirectToLogin(String application, String error) {
URI uri = new UriBuilder(headers, uriInfo, "login?application=" + application + "&error=login_failed").build(); URI uri = new UriBuilder(headers, uriInfo, "sdk/api/" + application + "/login").setQueryParam("error", error).build();
return Response.seeOther(uri).build(); return Response.seeOther(uri).build();
} }
@GET @GET
@Path("{application}/auth/{provider}") @Path("{application}/auth/{provider}")
@Produces(MediaType.TEXT_HTML)
public Response redirectToProviderAuth(@PathParam("application") String application, public Response redirectToProviderAuth(@PathParam("application") String application,
@PathParam("provider") String providerId) { @PathParam("provider") String providerId) {
Iterator<IdentityProvider> itr = ServiceRegistry.lookupProviders(IdentityProvider.class); Iterator<IdentityProvider> itr = ServiceRegistry.lookupProviders(IdentityProvider.class);
@ -186,7 +194,8 @@ public class SocialResource {
} }
if (provider == null) { if (provider == null) {
return redirectToLogin(application, "invalid_provider"); log.warn("Failed to redirect to provider auth: " + providerId + " not found");
return redirectToLogin(application, IdentityProviderErrors.INVALID_PROVIDER);
} }
IdentityProviderCallback callback = new IdentityProviderCallback(); IdentityProviderCallback callback = new IdentityProviderCallback();
@ -195,12 +204,13 @@ public class SocialResource {
callback.setUriInfo(uriInfo); callback.setUriInfo(uriInfo);
callback.setProviderKey(null); // TODO Get provider key callback.setProviderKey(null); // TODO Get provider key
callback.setProviderSecret(null); // TODO Get provider secret callback.setProviderSecret(null); // TODO Get provider secret
callback.setProviderState(getProviderState(provider));
URI authUrl = provider.getAuthUrl(callback); try {
if (authUrl != null) { return Response.seeOther(provider.getAuthUrl(callback)).build();
return Response.seeOther(authUrl).build(); } catch (Throwable t) {
} else { log.warn("Failed to redirect to provider auth", t);
return redirectToLogin(application, "invalid_provider"); return redirectToLogin(application, IdentityProviderErrors.PROVIDER_ERROR);
} }
} }

View file

@ -23,9 +23,9 @@ package org.keycloak.social.twitter;
import java.net.URI; import java.net.URI;
import org.jboss.resteasy.logging.Logger;
import org.keycloak.social.IdentityProvider; import org.keycloak.social.IdentityProvider;
import org.keycloak.social.IdentityProviderCallback; import org.keycloak.social.IdentityProviderCallback;
import org.keycloak.social.IdentityProviderException;
import org.picketlink.idm.model.SimpleUser; import org.picketlink.idm.model.SimpleUser;
import org.picketlink.idm.model.User; import org.picketlink.idm.model.User;
@ -38,15 +38,13 @@ import twitter4j.auth.RequestToken;
*/ */
public class TwitterProvider implements IdentityProvider { public class TwitterProvider implements IdentityProvider {
private static final Logger log = Logger.getLogger(TwitterProvider.class);
@Override @Override
public String getId() { public String getId() {
return "twitter"; return "twitter";
} }
@Override @Override
public URI getAuthUrl(IdentityProviderCallback callback) { public URI getAuthUrl(IdentityProviderCallback callback) throws IdentityProviderException {
try { try {
Twitter twitter = new TwitterFactory().getInstance(); Twitter twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer(callback.getProviderKey(), callback.getProviderSecret()); twitter.setOAuthConsumer(callback.getProviderKey(), callback.getProviderSecret());
@ -55,8 +53,7 @@ public class TwitterProvider implements IdentityProvider {
callback.putState(requestToken.getToken(), requestToken); callback.putState(requestToken.getToken(), requestToken);
return callback.createUri(requestToken.getAuthenticationURL()).build(); return callback.createUri(requestToken.getAuthenticationURL()).build();
} catch (Exception e) { } catch (Exception e) {
log.error("Failed to retrieve login url", e); throw new IdentityProviderException(e);
return null;
} }
} }
@ -71,7 +68,7 @@ public class TwitterProvider implements IdentityProvider {
} }
@Override @Override
public User processCallback(IdentityProviderCallback callback) { public User processCallback(IdentityProviderCallback callback) throws IdentityProviderException {
try { try {
Twitter twitter = new TwitterFactory().getInstance(); Twitter twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer(callback.getProviderKey(), callback.getProviderSecret()); twitter.setOAuthConsumer(callback.getProviderKey(), callback.getProviderSecret());
@ -86,8 +83,7 @@ public class TwitterProvider implements IdentityProvider {
user.setFirstName(twitterUser.getName()); user.setFirstName(twitterUser.getName());
return user; return user;
} catch (Exception e) { } catch (Exception e) {
log.error("Failed to process callback", e); throw new IdentityProviderException(e);
return null;
} }
} }