KEYCLOAK-33

Callback URL for social includes realm name
This commit is contained in:
Stian Thorgersen 2013-08-13 16:38:02 +01:00
parent a4ba63b3d2
commit a0f0e30348
9 changed files with 153 additions and 198 deletions

View file

@ -49,7 +49,11 @@ public class KeycloakApplication extends Application {
KeycloakSessionFactory f = createSessionFactory();
this.factory = f;
classes.add(KeycloakSessionCleanupFilter.class);
singletons.add(new RealmsResource(new TokenManager(), new SocialRequestManager()));
TokenManager tokenManager = new TokenManager();
singletons.add(new RealmsResource(tokenManager));
singletons.add(new SocialResource(tokenManager, new SocialRequestManager()));
classes.add(SkeletonKeyContextResolver.class);
classes.add(SaasService.class);
}

View file

@ -1,14 +1,13 @@
package org.keycloak.services.resources;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import java.net.URI;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.HttpResponse;
import org.keycloak.services.JspRequestParameters;
import org.keycloak.services.managers.AccessCodeEntry;
import org.keycloak.services.managers.AuthenticationManager;
@ -18,57 +17,52 @@ import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserModel;
import java.net.URI;
public class OAuthUtil {
public abstract class AbstractLoginService {
@Context
protected UriInfo uriInfo;
@Context
protected HttpHeaders headers;
@Context
HttpRequest request;
@Context
HttpResponse response;
private static final Logger log = Logger.getLogger(OAuthUtil.class);
public final static String securityFailurePath = "/saas/securityFailure.jsp";
public final static String loginFormPath = "/sdk/login.xhtml";
public final static String oauthFormPath = "/saas/oauthGrantForm.jsp";
protected RealmModel realm;
protected TokenManager tokenManager;
protected AuthenticationManager authManager = new AuthenticationManager();
public AbstractLoginService(RealmModel realm, TokenManager tokenManager) {
this.realm = realm;
this.tokenManager = tokenManager;
}
protected Response processAccessCode(String scopeParam, String state, String redirect, UserModel client, UserModel user) {
public static Response processAccessCode(RealmModel realm, TokenManager tokenManager, AuthenticationManager authManager,
HttpRequest request, UriInfo uriInfo,
String scopeParam, String state,
String redirect,
UserModel client, UserModel user) {
RoleModel resourceRole = realm.getRole(RealmManager.RESOURCE_ROLE);
RoleModel identityRequestRole = realm.getRole(RealmManager.IDENTITY_REQUESTER_ROLE);
boolean isResource = realm.hasRole(client, resourceRole);
if (!isResource && !realm.hasRole(client, identityRequestRole)) {
securityFailureForward("Login requester not allowed to request login.");
securityFailureForward(request, "Login requester not allowed to request login.");
return null;
}
AccessCodeEntry accessCode = tokenManager.createAccessCode(scopeParam, state, redirect, realm, client, user);
getLogger().info("processAccessCode: isResource: " + isResource);
getLogger().info("processAccessCode: go to oauth page?: "
+ (!isResource && (accessCode.getRealmRolesRequested().size() > 0 || accessCode.getResourceRolesRequested()
.size() > 0)));
log.info("processAccessCode: isResource: " + isResource);
log.info(
"processAccessCode: go to oauth page?: "
+ (!isResource && (accessCode.getRealmRolesRequested().size() > 0 || accessCode
.getResourceRolesRequested().size() > 0)));
if (!isResource
&& (accessCode.getRealmRolesRequested().size() > 0 || accessCode.getResourceRolesRequested().size() > 0)) {
oauthGrantPage(accessCode, client);
oauthGrantPage(realm, request, uriInfo, accessCode, client);
return null;
}
return redirectAccessCode(accessCode, state, redirect);
return redirectAccessCode(realm, authManager, uriInfo, accessCode, state, redirect);
}
protected Response redirectAccessCode(AccessCodeEntry accessCode, String state, String redirect) {
public static void securityFailureForward(HttpRequest request, String message) {
log.error(message);
request.setAttribute(JspRequestParameters.KEYCLOAK_SECURITY_FAILURE_MESSAGE, message);
request.forward(securityFailurePath);
}
public static Response redirectAccessCode(RealmModel realm, AuthenticationManager authManager, UriInfo uriInfo,
AccessCodeEntry accessCode,
String state, String redirect) {
String code = accessCode.getCode();
UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam("code", code);
getLogger().info("redirectAccessCode: state: " + state);
log.info("redirectAccessCode: state: " + state);
if (state != null)
redirectUri.queryParam("state", state);
Response.ResponseBuilder location = Response.status(302).location(redirectUri.build());
@ -78,16 +72,11 @@ public abstract class AbstractLoginService {
return location.build();
}
protected void securityFailureForward(String message) {
getLogger().error(message);
request.setAttribute(JspRequestParameters.KEYCLOAK_SECURITY_FAILURE_MESSAGE, message);
request.forward(securityFailurePath);
}
protected void forwardToLoginForm(String redirect, String clientId, String scopeParam, String state) {
public static void forwardToLoginForm(RealmModel realm, HttpRequest request, UriInfo uriInfo, String redirect,
String clientId, String scopeParam, String state) {
request.setAttribute(RealmModel.class.getName(), realm);
request.setAttribute("KEYCLOAK_LOGIN_ACTION", TokenService.processLoginUrl(uriInfo).build(realm.getId()));
request.setAttribute("KEYCLOAK_SOCIAL_LOGIN", SocialService.redirectToProviderAuthUrl(uriInfo).build(realm.getId()));
request.setAttribute("KEYCLOAK_SOCIAL_LOGIN", SocialResource.redirectToProviderAuthUrl(uriInfo).build(realm.getId()));
request.setAttribute("KEYCLOAK_REGISTRATION_PAGE", URI.create("not-implemented-yet"));
// RESTEASY eats the form data, so we send via an attribute
@ -98,7 +87,8 @@ public abstract class AbstractLoginService {
request.forward(loginFormPath);
}
protected void oauthGrantPage(AccessCodeEntry accessCode, UserModel client) {
public static void oauthGrantPage(RealmModel realm, HttpRequest request, UriInfo uriInfo, AccessCodeEntry accessCode,
UserModel client) {
request.setAttribute("realmRolesRequested", accessCode.getRealmRolesRequested());
request.setAttribute("resourceRolesRequested", accessCode.getResourceRolesRequested());
request.setAttribute("client", client);
@ -108,5 +98,4 @@ public abstract class AbstractLoginService {
request.forward(oauthFormPath);
}
protected abstract Logger getLogger();
}

View file

@ -43,11 +43,8 @@ public class RealmsResource {
protected TokenManager tokenManager;
protected SocialRequestManager socialRequestManager;
public RealmsResource(TokenManager tokenManager, SocialRequestManager socialRequestManager) {
public RealmsResource(TokenManager tokenManager) {
this.tokenManager = tokenManager;
this.socialRequestManager = socialRequestManager;
}
public static UriBuilder realmBaseUrl(UriInfo uriInfo) {
@ -73,24 +70,6 @@ public class RealmsResource {
}
@Path("{realm}/social")
public SocialService getSocialService(final @PathParam("realm") String id) {
return new Transaction(false) {
@Override
protected SocialService callImpl() {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.getRealm(id);
if (realm == null) {
logger.debug("realm not found");
throw new NotFoundException();
}
SocialService socialService = new SocialService(realm, tokenManager, socialRequestManager);
resourceContext.initResource(socialService);
return socialService;
}
}.call();
}
@Path("{realm}")
public PublicRealmResource getRealmResource(final @PathParam("realm") String id) {
return new Transaction(false) {

View file

@ -222,7 +222,7 @@ public class SaasService {
URI register = contextRoot(uriInfo).path(saasRegisterPath).build();
request.setAttribute("KEYCLOAK_LOGIN_ACTION", action);
request.setAttribute("KEYCLOAK_REGISTRATION_PAGE", register);
request.setAttribute("KEYCLOAK_SOCIAL_LOGIN", SocialService.redirectToProviderAuthUrl(uriInfo).build(realm.getId()));
request.setAttribute("KEYCLOAK_SOCIAL_LOGIN", SocialResource.redirectToProviderAuthUrl(uriInfo).build(realm.getId()));
request.forward(loginFormPath);
}

View file

@ -1,30 +1,8 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2012, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.keycloak.services.resources;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@ -32,17 +10,19 @@ import java.util.Map.Entry;
import javax.imageio.spi.ServiceRegistry;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.TokenManager;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.UserModel;
@ -56,39 +36,42 @@ import org.keycloak.social.SocialProviderException;
import org.keycloak.social.SocialRequestManager;
import org.keycloak.social.SocialUser;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class SocialService extends AbstractLoginService {
@Path("/social")
public class SocialResource {
private static final Logger logger = Logger.getLogger(SocialService.class);
protected static Logger logger = Logger.getLogger(SocialResource.class);
@Context
private HttpHeaders headers;
protected UriInfo uriInfo;
@Context
private UriInfo uriInfo;
protected HttpHeaders headers;
@Context
private HttpRequest request;
private SocialRequestManager socialRequestManager;
private TokenManager tokenManager;
private AuthenticationManager authManager = new AuthenticationManager();
public SocialResource(TokenManager tokenManager, SocialRequestManager socialRequestManager) {
this.tokenManager = tokenManager;
this.socialRequestManager = socialRequestManager;
}
public static UriBuilder socialServiceBaseUrl(UriInfo uriInfo) {
UriBuilder base = uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getSocialService");
UriBuilder base = uriInfo.getBaseUriBuilder().path(SocialResource.class);
return base;
}
public static UriBuilder redirectToProviderAuthUrl(UriInfo uriInfo) {
return socialServiceBaseUrl(uriInfo).path(SocialService.class, "redirectToProviderAuth");
return socialServiceBaseUrl(uriInfo).path(SocialResource.class, "redirectToProviderAuth");
}
public static UriBuilder callbackUrl(UriInfo uriInfo) {
return socialServiceBaseUrl(uriInfo).path(SocialService.class, "callback");
}
private SocialRequestManager socialRequestManager;
public SocialService(RealmModel realm, TokenManager tokenManager, SocialRequestManager socialRequestManager) {
super(realm, tokenManager);
this.socialRequestManager = socialRequestManager;
return socialServiceBaseUrl(uriInfo).path(SocialResource.class, "callback");
}
@GET
@ -101,9 +84,11 @@ public class SocialService extends AbstractLoginService {
RequestDetails requestData = getRequestDetails(queryParams);
SocialProvider provider = getProvider(requestData.getProviderId());
String realmId = requestData.getClientAttribute("realmId");
String key = System.getProperty("keycloak.social." + requestData.getProviderId() + ".key");
String secret = System.getProperty("keycloak.social." + requestData.getProviderId() + ".secret");
String callbackUri = callbackUrl(uriInfo).build(realm.getId()).toString();
String callbackUri = callbackUrl(uriInfo).build().toString();
SocialProviderConfig config = new SocialProviderConfig(key, secret, callbackUri);
@ -114,12 +99,15 @@ public class SocialService extends AbstractLoginService {
socialUser = provider.processCallback(config, callback);
} catch (SocialProviderException e) {
logger.warn("Failed to process social callback", e);
securityFailureForward("Failed to process social callback");
OAuthUtil.securityFailureForward(request, "Failed to process social callback");
return null;
}
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.getRealm(realmId);
if (!realm.isEnabled()) {
securityFailureForward("Realm not enabled.");
OAuthUtil.securityFailureForward(request, "Realm not enabled.");
return null;
}
@ -127,11 +115,11 @@ public class SocialService extends AbstractLoginService {
UserModel client = realm.getUser(clientId);
if (client == null) {
securityFailureForward("Unknown login requester.");
OAuthUtil.securityFailureForward(request, "Unknown login requester.");
return null;
}
if (!client.isEnabled()) {
securityFailureForward("Login requester not enabled.");
OAuthUtil.securityFailureForward(request, "Login requester not enabled.");
return null;
}
@ -149,7 +137,7 @@ public class SocialService extends AbstractLoginService {
}
if (!user.isEnabled()) {
securityFailureForward("Your account is not enabled.");
OAuthUtil.securityFailureForward(request, "Your account is not enabled.");
return null;
}
@ -157,60 +145,46 @@ public class SocialService extends AbstractLoginService {
String state = requestData.getClientAttributes().get("state");
String redirectUri = requestData.getClientAttributes().get("redirectUri");
return processAccessCode(scope, state, redirectUri, client, user);
return OAuthUtil.processAccessCode(realm, tokenManager, authManager, request, uriInfo, scope, state,
redirectUri, client, user);
}
}.call();
}
@GET
@Path("providers")
@Produces(MediaType.APPLICATION_JSON)
public List<SocialProvider> getProviders() {
List<SocialProvider> providers = new LinkedList<SocialProvider>();
Iterator<SocialProvider> itr = ServiceRegistry.lookupProviders(SocialProvider.class);
while (itr.hasNext()) {
providers.add(itr.next());
@Path("{realm}/login")
public Response redirectToProviderAuth(@PathParam("realm") final String realmId,
@QueryParam("provider_id") final String providerId, @QueryParam("client_id") final String clientId,
@QueryParam("scope") final String scope, @QueryParam("state") final String state,
@QueryParam("redirect_uri") final String redirectUri) {
SocialProvider provider = getProvider(providerId);
if (provider == null) {
OAuthUtil.securityFailureForward(request, "Social provider not found");
return null;
}
return providers;
}
@GET
@Path("login")
public Response redirectToProviderAuth(@QueryParam("provider_id") final String providerId,
@QueryParam("client_id") final String clientId, @QueryParam("scope") final String scope,
@QueryParam("state") final String state, @QueryParam("redirect_uri") final String redirectUri) {
return new Transaction() {
protected Response callImpl() {
SocialProvider provider = getProvider(providerId);
if (provider == null) {
securityFailureForward("Social provider not found");
return null;
}
String key = System.getProperty("keycloak.social." + providerId + ".key");
String secret = System.getProperty("keycloak.social." + providerId + ".secret");
String callbackUri = callbackUrl(uriInfo).build().toString();
String key = System.getProperty("keycloak.social." + providerId + ".key");
String secret = System.getProperty("keycloak.social." + providerId + ".secret");
String callbackUri = callbackUrl(uriInfo).build(realm.getId()).toString();
SocialProviderConfig config = new SocialProviderConfig(key, secret, callbackUri);
SocialProviderConfig config = new SocialProviderConfig(key, secret, callbackUri);
try {
AuthRequest authRequest = provider.getAuthUrl(config);
try {
AuthRequest authRequest = provider.getAuthUrl(config);
RequestDetails socialRequest = RequestDetailsBuilder.create(providerId)
.putSocialAttributes(authRequest.getAttributes()).putClientAttribute("realmId", realmId)
.putClientAttribute("clientId", clientId).putClientAttribute("scope", scope)
.putClientAttribute("state", state).putClientAttribute("redirectUri", redirectUri).build();
RequestDetails socialRequest = RequestDetailsBuilder.create(providerId)
.putSocialAttributes(authRequest.getAttributes()).putClientAttribute("clientId", clientId)
.putClientAttribute("scope", scope).putClientAttribute("state", state)
.putClientAttribute("redirectUri", redirectUri).build();
socialRequestManager.addRequest(authRequest.getId(), socialRequest);
socialRequestManager.addRequest(authRequest.getId(), socialRequest);
return Response.status(Status.FOUND).location(authRequest.getAuthUri()).build();
} catch (Throwable t) {
logger.error("Failed to redirect to social auth", t);
securityFailureForward("Failed to redirect to social auth");
return null;
}
}
}.call();
return Response.status(Status.FOUND).location(authRequest.getAuthUri()).build();
} catch (Throwable t) {
logger.error("Failed to redirect to social auth", t);
OAuthUtil.securityFailureForward(request, "Failed to redirect to social auth");
return null;
}
}
private RequestDetails getRequestDetails(Map<String, String[]> queryParams) {
@ -251,9 +225,4 @@ public class SocialService extends AbstractLoginService {
return queryParams;
}
@Override
protected Logger getLogger() {
return logger;
}
}

View file

@ -6,6 +6,8 @@ import org.jboss.resteasy.jose.jws.JWSInput;
import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
import org.jboss.resteasy.jwt.JsonSerialization;
import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.HttpResponse;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.SkeletonKeyToken;
import org.keycloak.services.managers.AccessCodeEntry;
@ -25,6 +27,7 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
@ -40,20 +43,32 @@ import java.util.Map;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class TokenService extends AbstractLoginService {
public class TokenService {
protected static final Logger logger = Logger.getLogger(TokenService.class);
protected RealmModel realm;
protected TokenManager tokenManager;
protected AuthenticationManager authManager = new AuthenticationManager();
@Context
protected Providers providers;
@Context
protected SecurityContext securityContext;
@Context
protected UriInfo uriInfo;
@Context
protected HttpHeaders headers;
@Context
HttpRequest request;
@Context
HttpResponse response;
private ResourceAdminManager resourceAdminManager = new ResourceAdminManager();
public TokenService(RealmModel realm, TokenManager tokenManager) {
super(realm, tokenManager);
this.realm = realm;
this.tokenManager = tokenManager;
}
public static UriBuilder tokenServiceBaseUrl(UriInfo uriInfo) {
@ -168,16 +183,16 @@ public class TokenService extends AbstractLoginService {
String redirect = formData.getFirst("redirect_uri");
if (!realm.isEnabled()) {
securityFailureForward("Realm not enabled.");
OAuthUtil.securityFailureForward(request, "Realm not enabled.");
return null;
}
UserModel client = realm.getUser(clientId);
if (client == null) {
securityFailureForward("Unknown login requester.");
OAuthUtil.securityFailureForward(request, "Unknown login requester.");
return null;
}
if (!client.isEnabled()) {
securityFailureForward("Login requester not enabled.");
OAuthUtil.securityFailureForward(request, "Login requester not enabled.");
return null;
}
String username = formData.getFirst("username");
@ -185,11 +200,11 @@ public class TokenService extends AbstractLoginService {
if (user == null) {
logger.error("Incorrect user name.");
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Incorrect user name.");
forwardToLoginForm(redirect, clientId, scopeParam, state);
OAuthUtil.forwardToLoginForm(realm, request, uriInfo, redirect, clientId, scopeParam, state);
return null;
}
if (!user.isEnabled()) {
securityFailureForward("Your account is not enabled.");
OAuthUtil.securityFailureForward(request, "Your account is not enabled.");
return null;
}
boolean authenticated = authManager.authenticateForm(realm, user, formData);
@ -197,11 +212,12 @@ public class TokenService extends AbstractLoginService {
logger.error("Authentication failed");
request.setAttribute("username", username);
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Invalid credentials.");
forwardToLoginForm(redirect, clientId, scopeParam, state);
OAuthUtil.forwardToLoginForm(realm, request, uriInfo, redirect, clientId, scopeParam, state);
return null;
}
return processAccessCode(scopeParam, state, redirect, client, user);
return OAuthUtil.processAccessCode(realm, tokenManager, authManager, request, uriInfo, scopeParam, state,
redirect, client, user);
}
}.call();
}
@ -341,18 +357,18 @@ public class TokenService extends AbstractLoginService {
return new Transaction() {
protected Response callImpl() {
if (!realm.isEnabled()) {
securityFailureForward("Realm not enabled");
OAuthUtil.securityFailureForward(request, "Realm not enabled");
return null;
}
UserModel client = realm.getUser(clientId);
if (client == null) {
securityFailureForward("Unknown login requester.");
OAuthUtil.securityFailureForward(request, "Unknown login requester.");
transaction.rollback();
return null;
}
if (!client.isEnabled()) {
securityFailureForward("Login requester not enabled.");
OAuthUtil.securityFailureForward(request, "Login requester not enabled.");
transaction.rollback();
session.close();
return null;
@ -362,7 +378,7 @@ public class TokenService extends AbstractLoginService {
RoleModel identityRequestRole = realm.getRole(RealmManager.IDENTITY_REQUESTER_ROLE);
boolean isResource = realm.hasRole(client, resourceRole);
if (!isResource && !realm.hasRole(client, identityRequestRole)) {
securityFailureForward("Login requester not allowed to request login.");
OAuthUtil.securityFailureForward(request, "Login requester not allowed to request login.");
transaction.rollback();
session.close();
return null;
@ -371,10 +387,11 @@ public class TokenService extends AbstractLoginService {
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
if (user != null) {
logger.info(user.getLoginName() + " already logged in.");
return processAccessCode(scopeParam, state, redirect, client, user);
return OAuthUtil.processAccessCode(realm, tokenManager, authManager, request, uriInfo, scopeParam, state,
redirect, client, user);
}
forwardToLoginForm(redirect, clientId, scopeParam, state);
OAuthUtil.forwardToLoginForm(realm, request, uriInfo, redirect, clientId, scopeParam, state);
return null;
}
}.call();
@ -415,14 +432,14 @@ public class TokenService extends AbstractLoginService {
logger.debug("Failed to verify signature", ignored);
}
if (!verifiedCode) {
securityFailureForward("Illegal access code.");
OAuthUtil.securityFailureForward(request, "Illegal access code.");
session.close();
return null;
}
String key = input.readContent(String.class);
AccessCodeEntry accessCodeEntry = tokenManager.getAccessCode(key);
if (accessCodeEntry == null) {
securityFailureForward("Unknown access code.");
OAuthUtil.securityFailureForward(request, "Unknown access code.");
session.close();
return null;
}
@ -434,7 +451,7 @@ public class TokenService extends AbstractLoginService {
return redirectAccessDenied(redirect, state);
}
return redirectAccessCode(accessCodeEntry, state, redirect);
return OAuthUtil.redirectAccessCode(realm, authManager, uriInfo, accessCodeEntry, state, redirect);
}
}.call();
}
@ -446,9 +463,4 @@ public class TokenService extends AbstractLoginService {
return location.build();
}
@Override
protected Logger getLogger() {
return logger;
}
}

View file

@ -18,7 +18,17 @@ Social provides implementations for Facebook, Google and Twitter.
Configure Facebook
------------------
Open https://developers.facebook.com/apps. Click on Create New App
Use any app name that you'd like, click Continue
Select Disabled for Sandbox Mode
Under Select how your app integrates with Facebook select Website with Facebook login. Fill in the form with the following values:
* Site URL: http://<HOSTNAME>[<PORT>]/auth-server/rest/social/callback
Click on Save changes. Use the value of App ID as the value of the system property "keycloak.social.facebook.key", and the value of App Secret as the value of "keycloak.social.facebook.secret".
Configure Google
@ -30,7 +40,7 @@ Use any name that you'd like, click Create Project, select API Access and click
Use any product name you'd like and leave the other fields empty, then click Next. On the next page select Web application as the application type. Click more options next> to Your site or hostname. Fill in the form with the following values:
* Authorized Redirect URIs: http://<HOSTNAME>[<PORT>]/auth-server/rest/realms/<REALM>/social/callback
* Authorized Redirect URIs: http://<HOSTNAME>[<PORT>]/auth-server/rest/social/callback
Click on Create client ID. Use the value of Client ID as the value of the system property "keycloak.social.google.key", and the value of Client secret as the value of "keycloak.social.google.secret".
@ -40,10 +50,7 @@ Configure Twitter
Open https://dev.twitter.com/apps. Click on Create a new application.
Fill in name, description and website. For Callback URL use the following value:
Callback URL: http://mbaas-stianst.rhcloud.com/ejs-identity/api/callback/516131bc-e3e4-4736-928b-cf1df8c0fe74
Note: Twitter doesn't allow localhost as domain, use 127.0.0.1 instead!
Fill in name, description and website. Leave Callback URL empty!
Agree to the rules, fill in the captcha and click on Create your Twitter application.

View file

@ -21,25 +21,20 @@
*/
package org.keycloak.social;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@XmlRootElement
public interface SocialProvider {
String getId();
@XmlTransient
AuthRequest getAuthUrl(SocialProviderConfig config) throws SocialProviderException;
String getRequestIdParamName();
String getName();
@XmlTransient
SocialUser processCallback(SocialProviderConfig config, AuthCallback callback) throws SocialProviderException;
}

View file

@ -49,7 +49,7 @@ public class TwitterProvider implements SocialProvider {
Twitter twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer(request.getKey(), request.getSecret());
RequestToken requestToken = twitter.getOAuthRequestToken();
RequestToken requestToken = twitter.getOAuthRequestToken(request.getCallbackUrl());
return AuthRequestBuilder.create(requestToken.getToken(), requestToken.getAuthenticationURL())
.setAttribute("token", requestToken.getToken()).setAttribute("tokenSecret", requestToken.getTokenSecret())