use of org.keycloak.saml.SAML2LogoutResponseBuilder in project keycloak by keycloak.
the class LogoutTest method testLogoutWithPostBindingUnsetRedirectBindingSet.
@Test
public void testLogoutWithPostBindingUnsetRedirectBindingSet() {
// https://issues.jboss.org/browse/KEYCLOAK-4779
adminClient.realm(REALM_NAME).clients().get(sales2Rep.getId()).update(ClientBuilder.edit(sales2Rep).frontchannelLogout(true).attribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE, "").attribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE, "http://url-to-sales-2").build());
SAMLDocumentHolder samlResponse = prepareLogIntoTwoApps().logoutRequest(getAuthServerSamlEndpoint(REALM_NAME), SAML_CLIENT_ID_SALES_POST, POST).nameId(nameIdRef::get).sessionIndex(sessionIndexRef::get).build().processSamlResponse(REDIRECT).transformDocument(doc -> {
// Expect logout request for sales-post2
SAML2Object so = (SAML2Object) SAMLParser.getInstance().parse(new DOMSource(doc));
assertThat(so, isSamlLogoutRequest("http://url-to-sales-2"));
// Emulate successful logout response from sales-post2 logout
return new SAML2LogoutResponseBuilder().destination(getAuthServerSamlEndpoint(REALM_NAME).toString()).issuer(SAML_CLIENT_ID_SALES_POST2).logoutRequestID(((LogoutRequestType) so).getID()).buildDocument();
}).targetAttributeSamlResponse().targetUri(getAuthServerSamlEndpoint(REALM_NAME)).build().getSamlResponse(POST);
// Expect final successful logout response from auth server signalling final successful logout
assertThat(samlResponse.getSamlObject(), isSamlStatusResponse(JBossSAMLURIConstants.STATUS_SUCCESS));
assertThat(((StatusResponseType) samlResponse.getSamlObject()).getDestination(), is("http://url"));
assertLogoutEvent(SAML_CLIENT_ID_SALES_POST2);
}
use of org.keycloak.saml.SAML2LogoutResponseBuilder in project keycloak by keycloak.
the class SamlProtocol method finishLogout.
@Override
public Response finishLogout(UserSessionModel userSession) {
logger.debug("finishLogout");
String logoutBindingUri = userSession.getNote(SAML_LOGOUT_BINDING_URI);
if (logoutBindingUri == null) {
logger.error("Can't finish SAML logout as there is no logout binding set. Please configure the logout service url in the admin console for your client applications.");
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_LOGOUT);
}
String logoutRelayState = userSession.getNote(SAML_LOGOUT_RELAY_STATE);
SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
builder.logoutRequestID(userSession.getNote(SAML_LOGOUT_REQUEST_ID));
builder.destination(logoutBindingUri);
builder.issuer(getResponseIssuer(realm));
JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder(session);
binding.relayState(logoutRelayState);
String signingAlgorithm = userSession.getNote(SAML_LOGOUT_SIGNATURE_ALGORITHM);
boolean postBinding = isLogoutPostBindingForInitiator(userSession);
if (signingAlgorithm != null) {
SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(signingAlgorithm);
String canonicalization = userSession.getNote(SAML_LOGOUT_CANONICALIZATION);
if (canonicalization != null) {
binding.canonicalizationMethod(canonicalization);
}
KeyManager.ActiveRsaKey keys = session.keys().getActiveRsaKey(realm);
XmlKeyInfoKeyNameTransformer transformer = XmlKeyInfoKeyNameTransformer.from(userSession.getNote(SAML_SERVER_SIGNATURE_KEYINFO_KEY_NAME_TRANSFORMER), SamlClient.DEFAULT_XML_KEY_INFO_KEY_NAME_TRANSFORMER);
String keyName = transformer.getKeyName(keys.getKid(), keys.getCertificate());
binding.signatureAlgorithm(algorithm).signWith(keyName, keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate()).signDocument();
boolean addExtension = (!postBinding) && Objects.equals("true", userSession.getNote(SamlProtocol.SAML_LOGOUT_ADD_EXTENSIONS_ELEMENT_WITH_KEY_INFO));
if (addExtension) {
// Only include extension if REDIRECT binding and signing whole SAML protocol message
builder.addExtension(new KeycloakKeySamlExtensionGenerator(keyName));
}
}
Response response;
try {
response = buildLogoutResponse(userSession, logoutBindingUri, builder, binding);
} catch (ConfigurationException | ProcessingException | IOException e) {
throw new RuntimeException(e);
}
if (logoutBindingUri != null) {
event.detail(Details.REDIRECT_URI, logoutBindingUri);
}
event.event(EventType.LOGOUT).detail(Details.AUTH_METHOD, userSession.getAuthMethod()).client(session.getContext().getClient()).user(userSession.getUser()).session(userSession).detail(Details.USERNAME, userSession.getLoginUsername()).detail(Details.RESPONSE_MODE, postBinding ? SamlProtocol.SAML_POST_BINDING : SamlProtocol.SAML_REDIRECT_BINDING).detail(SamlProtocol.SAML_LOGOUT_REQUEST_ID, userSession.getNote(SAML_LOGOUT_REQUEST_ID)).success();
return response;
}
use of org.keycloak.saml.SAML2LogoutResponseBuilder in project keycloak by keycloak.
the class WebBrowserSsoAuthenticationHandler method logoutRequest.
@Override
protected AuthOutcome logoutRequest(LogoutRequestType request, String relayState) {
if (request.getSessionIndex() == null || request.getSessionIndex().isEmpty()) {
sessionStore.logoutByPrincipal(request.getNameID().getValue());
} else {
sessionStore.logoutBySsoId(request.getSessionIndex());
}
String issuerURL = deployment.getEntityID();
SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
builder.logoutRequestID(request.getID());
builder.destination(deployment.getIDP().getSingleLogoutService().getResponseBindingUrl());
builder.issuer(issuerURL);
BaseSAML2BindingBuilder binding = new BaseSAML2BindingBuilder().relayState(relayState);
if (deployment.getIDP().getSingleLogoutService().signResponse()) {
if (deployment.getSignatureCanonicalizationMethod() != null)
binding.canonicalizationMethod(deployment.getSignatureCanonicalizationMethod());
binding.signatureAlgorithm(deployment.getSignatureAlgorithm()).signWith(null, deployment.getSigningKeyPair()).signDocument();
// TODO: As part of KEYCLOAK-3810, add KeyID to the SAML document
// <related DocumentBuilder>.addExtension(new KeycloakKeySamlExtensionGenerator(<key ID>));
}
try {
SamlUtil.sendSaml(false, facade, deployment.getIDP().getSingleLogoutService().getResponseBindingUrl(), binding, builder.buildDocument(), deployment.getIDP().getSingleLogoutService().getResponseBinding());
} catch (Exception e) {
log.error("Could not send logout response SAML request", e);
return AuthOutcome.FAILED;
}
return AuthOutcome.NOT_ATTEMPTED;
}
use of org.keycloak.saml.SAML2LogoutResponseBuilder in project keycloak by keycloak.
the class ArtifactBindingTest method testSessionStateDuringArtifactBindingLogoutWithMoreFrontChannelClients.
// Won't work with openshift, because openshift wouldn't see ArtifactResolutionService
@AuthServerContainerExclude(AuthServerContainerExclude.AuthServer.REMOTE)
@Test
public void testSessionStateDuringArtifactBindingLogoutWithMoreFrontChannelClients() {
getCleanup().addCleanup(ClientAttributeUpdater.forClient(adminClient, REALM_NAME, SAML_CLIENT_ID_SALES_POST).setAttribute(SamlConfigAttributes.SAML_ARTIFACT_BINDING, "true").setAttribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_ARTIFACT_ATTRIBUTE, "http://url").setFrontchannelLogout(true).update()).addCleanup(ClientAttributeUpdater.forClient(adminClient, REALM_NAME, SAML_CLIENT_ID_SALES_POST2).setAttribute(SamlConfigAttributes.SAML_ARTIFACT_BINDING, "true").setAttribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_ARTIFACT_ATTRIBUTE, "http://url").setFrontchannelLogout(true).update());
ClientRepresentation salesRep = adminClient.realm(REALM_NAME).clients().findByClientId(SAML_CLIENT_ID_SALES_POST).get(0);
final String salesRepId = salesRep.getId();
ClientRepresentation salesRep2 = adminClient.realm(REALM_NAME).clients().findByClientId(SAML_CLIENT_ID_SALES_POST2).get(0);
final String salesRep2Id = salesRep2.getId();
final AtomicReference<String> userSessionId = new AtomicReference<>();
SAMLDocumentHolder response = new SamlClientBuilder().authnRequest(getAuthServerSamlEndpoint(REALM_NAME), SAML_CLIENT_ID_SALES_POST2, SAML_ASSERTION_CONSUMER_URL_SALES_POST2, REDIRECT).setProtocolBinding(JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.getUri()).build().login().user(bburkeUser).build().handleArtifact(getAuthServerSamlEndpoint(REALM_NAME), SAML_CLIENT_ID_SALES_POST2).setBeforeStepChecks(new SessionStateChecker(testingClient.server()).storeUserSessionId(userSessionId).expectedClientSession(salesRep2Id).expectedState(UserSessionModel.State.LOGGED_IN).expectedNumberOfClientSessions(1).consumeUserSession(userSessionModel -> assertThat(userSessionModel, notNullValue())).consumeClientSession(salesRep2Id, clientSession -> assertThat(clientSession, notNullValue()))).verifyRedirect(true).build().authnRequest(getAuthServerSamlEndpoint(REALM_NAME), SAML_CLIENT_ID_SALES_POST, SAML_ASSERTION_CONSUMER_URL_SALES_POST, REDIRECT).setProtocolBinding(JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.getUri()).build().handleArtifact(getAuthServerSamlEndpoint(REALM_NAME), SAML_CLIENT_ID_SALES_POST).setBeforeStepChecks(new SessionStateChecker(testingClient.server()).expectedUserSession(userSessionId).expectedState(UserSessionModel.State.LOGGED_IN).expectedClientSession(salesRepId).expectedNumberOfClientSessions(2).expectedAction(salesRep2Id, null).expectedAction(salesRepId, null)).verifyRedirect(true).build().logoutRequest(getAuthServerSamlEndpoint(REALM_NAME), SAML_CLIENT_ID_SALES_POST2, REDIRECT).build().handleArtifact(getAuthServerSamlEndpoint(REALM_NAME), SAML_CLIENT_ID_SALES_POST).setBeforeStepChecks(new SessionStateChecker(testingClient.server()).expectedUserSession(userSessionId).expectedState(UserSessionModel.State.LOGGING_OUT).expectedClientSession(salesRepId).expectedNumberOfClientSessions(2).expectedAction(salesRepId, CommonClientSessionModel.Action.LOGGING_OUT).expectedAction(salesRep2Id, CommonClientSessionModel.Action.LOGGING_OUT)).setAfterStepChecks(new SessionStateChecker(testingClient.server()).setUserSessionProvider(session -> userSessionId.get()).expectedState(UserSessionModel.State.LOGGING_OUT).expectedNumberOfClientSessions(2).expectedAction(salesRepId, CommonClientSessionModel.Action.LOGGED_OUT).expectedAction(salesRep2Id, CommonClientSessionModel.Action.LOGGING_OUT)).verifyRedirect(true).build().doNotFollowRedirects().processSamlResponse(ARTIFACT_RESPONSE).transformDocument(doc -> {
// Send LogoutResponse
SAML2Object so = (SAML2Object) SAMLParser.getInstance().parse(new DOMSource(doc));
return new SAML2LogoutResponseBuilder().destination(getAuthServerSamlEndpoint(REALM_NAME).toString()).issuer(SAML_CLIENT_ID_SALES_POST).logoutRequestID(((LogoutRequestType) so).getID()).buildDocument();
}).targetBinding(REDIRECT).targetAttributeSamlResponse().targetUri(getAuthServerSamlEndpoint(REALM_NAME)).build().handleArtifact(getAuthServerSamlEndpoint(REALM_NAME), SAML_CLIENT_ID_SALES_POST2).verifyRedirect(true).setBeforeStepChecks(new SessionStateChecker(testingClient.server()).expectedUserSession(userSessionId).expectedClientSession(salesRep2Id).expectedState(UserSessionModel.State.LOGGED_OUT_UNCONFIRMED).expectedNumberOfClientSessions(2).expectedAction(salesRepId, CommonClientSessionModel.Action.LOGGED_OUT).expectedAction(salesRep2Id, CommonClientSessionModel.Action.LOGGING_OUT)).setAfterStepChecks(new SessionStateChecker(testingClient.server()).consumeUserSession(userSessionModel -> assertThat(userSessionModel, nullValue())).setUserSessionProvider(session -> userSessionId.get())).build().executeAndTransform(this::getArtifactResponse);
assertThat(response.getSamlObject(), instanceOf(ArtifactResponseType.class));
ArtifactResponseType artifactResponse = (ArtifactResponseType) response.getSamlObject();
assertThat(artifactResponse.getSignature(), nullValue());
assertThat(artifactResponse, isSamlStatusResponse(JBossSAMLURIConstants.STATUS_SUCCESS));
assertThat(artifactResponse.getAny(), instanceOf(StatusResponseType.class));
}
Aggregations