Display error page if kerberos token is unavailable

This commit is contained in:
mposolda 2015-02-11 11:52:14 +01:00
parent 07bda93b81
commit 4b637036ac
9 changed files with 48 additions and 20 deletions

View file

@ -2,10 +2,10 @@
<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>
<artifactId>keycloak-broker-parent</artifactId>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.2.0.Beta1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View file

@ -19,6 +19,7 @@ package org.keycloak.broker.provider;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import javax.ws.rs.core.UriInfo;
@ -28,6 +29,7 @@ import javax.ws.rs.core.UriInfo;
*/
public class AuthenticationRequest {
private final KeycloakSession session;
private final UriInfo uriInfo;
private final String state;
private final HttpRequest httpRequest;
@ -35,7 +37,8 @@ public class AuthenticationRequest {
private final String redirectUri;
private final ClientSessionModel clientSession;
public AuthenticationRequest(RealmModel realm, ClientSessionModel clientSession, HttpRequest httpRequest, UriInfo uriInfo, String state, String redirectUri) {
public AuthenticationRequest(KeycloakSession session, RealmModel realm, ClientSessionModel clientSession, HttpRequest httpRequest, UriInfo uriInfo, String state, String redirectUri) {
this.session = session;
this.realm = realm;
this.httpRequest = httpRequest;
this.uriInfo = uriInfo;
@ -44,6 +47,10 @@ public class AuthenticationRequest {
this.clientSession = clientSession;
}
public KeycloakSession getSession() {
return session;
}
public UriInfo getUriInfo() {
return this.uriInfo;
}

View file

@ -2,10 +2,10 @@
<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>
<artifactId>keycloak-broker-parent</artifactId>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.2.0.Beta1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -20,6 +20,11 @@
<artifactId>keycloak-broker-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-login-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>

View file

@ -3,6 +3,7 @@ package org.keycloak.broker.kerberos;
import java.net.URI;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
@ -14,6 +15,7 @@ import org.keycloak.broker.provider.AbstractIdentityProvider;
import org.keycloak.broker.provider.AuthenticationRequest;
import org.keycloak.broker.provider.AuthenticationResponse;
import org.keycloak.broker.provider.FederatedIdentity;
import org.keycloak.login.LoginFormsProvider;
import org.keycloak.models.FederatedIdentityModel;
/**
@ -54,16 +56,16 @@ public class KerberosIdentityProvider extends AbstractIdentityProvider<KerberosI
// Case when we don't yet have any Negotiate header
if (authHeader == null) {
return sendNegotiateResponse(null);
return sendNegotiateResponse(request, null);
}
String[] tokens = authHeader.split(" ");
if (tokens.length != 2) {
logger.warn("Invalid length of tokens: " + tokens.length);
return sendNegotiateResponse(null);
return sendNegotiateResponse(request, null);
} else if (!KerberosConstants.NEGOTIATE.equalsIgnoreCase(tokens[0])) {
logger.warn("Unknown scheme " + tokens[0]);
return sendNegotiateResponse(null);
return sendNegotiateResponse(request, null);
} else {
String spnegoToken = tokens[1];
SPNEGOAuthenticator spnegoAuthenticator = createSPNEGOAuthenticator(spnegoToken);
@ -73,7 +75,7 @@ public class KerberosIdentityProvider extends AbstractIdentityProvider<KerberosI
FederatedIdentity federatedIdentity = getFederatedIdentity(spnegoAuthenticator);
return AuthenticationResponse.end(federatedIdentity);
} else {
return sendNegotiateResponse(spnegoAuthenticator.getResponseToken());
return sendNegotiateResponse(request, spnegoAuthenticator.getResponseToken());
}
}
}
@ -94,16 +96,22 @@ public class KerberosIdentityProvider extends AbstractIdentityProvider<KerberosI
* @param negotiateToken token to be send back in response or null if just "WWW-Authenticate: Negotiate" should be sent
* @return AuthenticationResponse
*/
protected AuthenticationResponse sendNegotiateResponse(String negotiateToken) {
protected AuthenticationResponse sendNegotiateResponse(AuthenticationRequest request, String negotiateToken) {
String negotiateHeader = negotiateToken == null ? KerberosConstants.NEGOTIATE : KerberosConstants.NEGOTIATE + " " + negotiateToken;
if (logger.isTraceEnabled()) {
logger.trace("Sending back " + HttpHeaders.WWW_AUTHENTICATE + ": " + negotiateHeader);
}
Response response = Response.status(Response.Status.UNAUTHORIZED)
.header(HttpHeaders.WWW_AUTHENTICATE, negotiateHeader)
.build();
// Error page is rendered just if browser is unable to send Authorization header with SPNEGO token
Response response = request.getSession().getProvider(LoginFormsProvider.class)
.setRealm(request.getRealm())
.setUriInfo(request.getUriInfo())
.setError("errorKerberosLogin")
.setStatus(Response.Status.UNAUTHORIZED)
.createErrorPage();
response.getMetadata().putSingle(HttpHeaders.WWW_AUTHENTICATE, negotiateHeader);
return AuthenticationResponse.fromResponse(response);
}

View file

@ -2,10 +2,10 @@
<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>
<artifactId>keycloak-broker-parent</artifactId>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.2.0.Beta1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View file

@ -2,10 +2,10 @@
<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>
<artifactId>keycloak-broker-parent</artifactId>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.2.0.Beta1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View file

@ -97,6 +97,8 @@ actionPasswordWarning=You need to change your password to activate your account.
actionEmailWarning=You need to verify your email address to activate your account.
actionFollow=Please fill in the fields below.
errorKerberosLogin=Unable to login with Kerberos
successHeader=Success!
errorHeader=Error!

View file

@ -53,7 +53,7 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
private String message;
private String accessCode;
private Response.Status status = Response.Status.OK;
private Response.Status status;
private List<RoleModel> realmRolesRequested;
private MultivaluedMap<String, RoleModel> resourceRolesRequested;
private MultivaluedMap<String, String> queryParams;
@ -218,6 +218,10 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
break;
}
if (status == null) {
status = Response.Status.OK;
}
try {
String result = freeMarker.processTemplate(attributes, Templates.getTemplate(page), theme);
Response.ResponseBuilder builder = Response.status(status).type(MediaType.TEXT_HTML).entity(result);
@ -246,7 +250,9 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
}
public Response createErrorPage() {
setStatus(Response.Status.INTERNAL_SERVER_ERROR);
if (status == null) {
status = Response.Status.INTERNAL_SERVER_ERROR;
}
return createResponse(LoginFormsPages.ERROR);
}

View file

@ -422,7 +422,7 @@ public class AuthenticationBrokerResource {
}
private AuthenticationRequest createAuthenticationRequest(String providerId, String code, RealmModel realm, ClientSessionModel clientSession) {
return new AuthenticationRequest(realm, clientSession, this.request, this.uriInfo, code, getRedirectUri(providerId, realm));
return new AuthenticationRequest(this.session, realm, clientSession, this.request, this.uriInfo, code, getRedirectUri(providerId, realm));
}
private String getRedirectUri(String providerId, RealmModel realm) {