move pre-auth

This commit is contained in:
Bill Burke 2014-10-01 14:57:52 -04:00
parent 71216bf2c9
commit 6cf62a2768
4 changed files with 96 additions and 58 deletions

View file

@ -585,7 +585,7 @@
promise.setSuccess();
}
var src = getRealmUrl() + '/login-status-iframe.html?client_id=' + encodeURIComponent(kc.clientId) + '&origin=' + getOrigin();
var src = getRealmUrl() + '/protocol/openid-connect/login-status-iframe.html?client_id=' + encodeURIComponent(kc.clientId) + '&origin=' + getOrigin();
iframe.setAttribute('src', src );
iframe.style.display = 'none';
document.body.appendChild(iframe);

View file

@ -7,8 +7,10 @@ import org.jboss.resteasy.spi.BadRequestException;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.HttpResponse;
import org.jboss.resteasy.spi.NotAcceptableException;
import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.UnauthorizedException;
import org.keycloak.ClientConnection;
import org.keycloak.Config;
import org.keycloak.OAuth2Constants;
import org.keycloak.OAuthErrorException;
import org.keycloak.RSATokenVerifier;
@ -33,12 +35,14 @@ import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.AuthenticationManager.AuthenticationStatus;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.Cors;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.util.Base64Url;
import org.keycloak.util.BasicAuthHelper;
import org.keycloak.util.StreamUtil;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@ -46,8 +50,10 @@ import javax.ws.rs.HeaderParam;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.HttpHeaders;
@ -58,6 +64,8 @@ import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Providers;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.HashMap;
import java.util.HashSet;
@ -169,6 +177,64 @@ public class OpenIDConnectService {
return uriBuilder.path(OpenIDConnectService.class, "refreshAccessToken");
}
/**
*
*
* @param client_id
* @param origin
* @return
*/
@Path("login-status-iframe.html")
@GET
@Produces(MediaType.TEXT_HTML)
public Response getLoginStatusIframe(@QueryParam("client_id") String client_id,
@QueryParam("origin") String origin) {
ClientModel client = realm.findClient(client_id);
if (client == null) {
throw new NotFoundException("could not find client: " + client_id);
}
InputStream is = getClass().getClassLoader().getResourceAsStream("login-status-iframe.html");
if (is == null) throw new NotFoundException("Could not find login-status-iframe.html ");
boolean valid = false;
for (String o : client.getWebOrigins()) {
if (o.equals("*") || o.equals(origin)) {
valid = true;
break;
}
}
for (String r : OpenIDConnectService.resolveValidRedirects(uriInfo, client.getRedirectUris())) {
int i = r.indexOf('/', 8);
if (i != -1) {
r = r.substring(0, i);
}
if (r.equals(origin)) {
valid = true;
break;
}
}
if (!valid) {
throw new BadRequestException("Invalid origin");
}
try {
String file = StreamUtil.readString(is);
file = file.replace("ORIGIN", origin);
CacheControl cacheControl = new CacheControl();
cacheControl.setNoTransform(false);
cacheControl.setMaxAge(Config.scope("theme").getInt("staticMaxAge", -1));
return Response.ok(file).cacheControl(cacheControl).build();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Direct grant REST invocation. One stop call to obtain an access token.
@ -730,15 +796,8 @@ public class OpenIDConnectService {
ClientSessionModel clientSession = pageInitializer.clientSession;
AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, uriInfo, clientConnection, headers);
if (authResult != null) {
UserModel user = authResult.getUser();
UserSessionModel userSession = authResult.getSession();
TokenManager.attachClientSession(userSession, clientSession);
event.user(user).session(userSession).detail(Details.AUTH_METHOD, "sso");
return authManager.nextActionAfterAuthentication(session, userSession, clientSession, clientConnection, request, uriInfo, event);
}
response = authManager.checkNonFormAuthentication(session, clientSession, realm, uriInfo, request, clientConnection, headers, event);
if (response != null) return response;
if (prompt != null && prompt.equals("none")) {
OpenIDConnect oauth = new OpenIDConnect(session, realm, request, uriInfo, clientConnection);

View file

@ -23,6 +23,7 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.LoginProtocol;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.resources.RealmsResource;
@ -193,6 +194,23 @@ public class AuthenticationManager {
return authResult;
}
public Response checkNonFormAuthentication(KeycloakSession session, ClientSessionModel clientSession, RealmModel realm, UriInfo uriInfo,
HttpRequest request,
ClientConnection clientConnection, HttpHeaders headers,
EventBuilder event) {
AuthResult authResult = authenticateIdentityCookie(session, realm, uriInfo, clientConnection, headers, true);
if (authResult != null) {
UserModel user = authResult.getUser();
UserSessionModel userSession = authResult.getSession();
TokenManager.attachClientSession(userSession, clientSession);
event.user(user).session(userSession).detail(Details.AUTH_METHOD, "sso");
return nextActionAfterAuthentication(session, userSession, clientSession, clientConnection, request, uriInfo, event);
}
return null;
}
public static Response redirectAfterSuccessfulFlow(KeycloakSession session, RealmModel realm, UserSessionModel userSession,
ClientSessionModel clientSession,
HttpRequest request, UriInfo uriInfo, ClientConnection clientConnection) {

View file

@ -14,6 +14,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.protocol.LoginProtocol;
import org.keycloak.protocol.LoginProtocolFactory;
import org.keycloak.protocol.oidc.OpenIDConnect;
import org.keycloak.protocol.oidc.OpenIDConnectService;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.BruteForceProtector;
@ -76,65 +77,25 @@ public class RealmsResource {
return base.path(RealmsResource.class).path(RealmsResource.class, "getAccountService");
}
/**
*
*
* @param name
* @param client_id
* @return
*/
@Path("{realm}/login-status-iframe.html")
@GET
@Produces(MediaType.TEXT_HTML)
@Deprecated
public Response getLoginStatusIframe(final @PathParam("realm") String name,
@QueryParam("client_id") String client_id,
@QueryParam("origin") String origin) {
// backward compatibility
RealmManager realmManager = new RealmManager(session);
RealmModel realm = locateRealm(name, realmManager);
ClientModel client = realm.findClient(client_id);
if (client == null) {
throw new NotFoundException("could not find client: " + client_id);
}
EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder();
AuthenticationManager authManager = new AuthenticationManager(protector);
InputStream is = getClass().getClassLoader().getResourceAsStream("login-status-iframe.html");
if (is == null) throw new NotFoundException("Could not find login-status-iframe.html ");
LoginProtocolFactory factory = (LoginProtocolFactory)session.getKeycloakSessionFactory().getProviderFactory(LoginProtocol.class, OpenIDConnect.LOGIN_PROTOCOL);
OpenIDConnectService endpoint = (OpenIDConnectService)factory.createProtocolEndpoint(realm, event, authManager);
boolean valid = false;
for (String o : client.getWebOrigins()) {
if (o.equals("*") || o.equals(origin)) {
valid = true;
break;
}
}
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
return endpoint.getLoginStatusIframe(client_id, origin);
for (String r : OpenIDConnectService.resolveValidRedirects(uriInfo, client.getRedirectUris())) {
int i = r.indexOf('/', 8);
if (i != -1) {
r = r.substring(0, i);
}
if (r.equals(origin)) {
valid = true;
break;
}
}
if (!valid) {
throw new BadRequestException("Invalid origin");
}
try {
String file = StreamUtil.readString(is);
file = file.replace("ORIGIN", origin);
CacheControl cacheControl = new CacheControl();
cacheControl.setNoTransform(false);
cacheControl.setMaxAge(Config.scope("theme").getInt("staticMaxAge", -1));
return Response.ok(file).cacheControl(cacheControl).build();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Path("{realm}/protocol/{protocol}")