8000 Use POST binding for logout when REDIRECT url is not set and forced POST (26.2) by rmartinc · Pull Request #40824 · keycloak/keycloak · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Use POST binding for logout when REDIRECT url is not set and forced POST (26.2) #40824

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -375,33 +375,35 @@ public static String getLogoutBindingTypeForClientSession(AuthenticatedClientSes
boolean redirectUrlSet = !(logoutRedirectUrl == null || logoutRedirectUrl.trim().isEmpty());
boolean artifactUrlSet = !(logoutArtifactUrl == null || logoutArtifactUrl.trim().isEmpty());

// Default to Redirect
String bindingType = SAML_REDIRECT_BINDING;
// client configured to force post binding and postUrl for logout is set
if (samlClient.forcePostBinding() && postUrlSet) {
return SAML_POST_BINDING;
}

// fall back to post binding if no redirect URL is set
if (postUrlSet && !redirectUrlSet) {
bindingType = SAML_POST_BINDING;
// client configured to force artifact binding and artifactUrl for logout is set
if (samlClient.forceArtifactBinding() && artifactUrlSet) {
return SAML_ARTIFACT_BINDING;
}

// evaluate how the user logged in
if (clientSession != null) {
String sessionBinding = clientSession.getNote(SAML_BINDING);
if (SAML_ARTIFACT_BINDING.equals(sessionBinding) && artifactUrlSet) {
bindingType = SAML_ARTIFACT_BINDING;
}
final String bindingType = clientSession.getNote(SAML_BINDING);

// if the login binding was artifact and url set, return artifact
if (SAML_ARTIFACT_BINDING.equals(bindingType) && artifactUrlSet) {
return SAML_ARTIFACT_BINDING;
}

// client configured to force artifact binding and artifactUrl for logout is set
if (samlClient.forceArtifactBinding() && artifactUrlSet) {
bindingType = SAML_ARTIFACT_BINDING;
// if the login binding was POST and url set, return POST
if (SAML_POST_BINDING.equals(bindingType) && postUrlSet) {
return SAML_POST_BINDING;
}

// client configured to force post binding and postUrl for logout ‚is set
if (samlClient.forcePostBinding() && postUrlSet) {
bindingType = SAML_POST_BINDING;
// fall back to post binding if no redirect URL
if (!redirectUrlSet && (postUrlSet || samlClient.forcePostBinding())) {
return SAML_POST_BINDING;
}

return bindingType;
// Default to Redirect
return SAML_REDIRECT_BINDING;
}

protected String getNameIdFormat(SamlClient samlClient, AuthenticationSessionModel authSession) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,11 @@ public void testGetLogoutBindingTypeForClientSession() {
String bindingType = SamlProtocol.getLogoutBindingTypeForClientSession(clientSession);
assertEquals(SamlProtocol.SAML_REDIRECT_BINDING, bindingType);

// default to POST if forced with no url
client.setForcePostBinding(true);
assertEquals(SamlProtocol.SAML_REDIRECT_BINDING, bindingType);

client.setForcePostBinding(false);
clientSession.setNote(SamlProtocol.SAML_BINDING, SamlProtocol.SAML_ARTIFACT_BINDING);
client.defineSetLogoutUrls(false, false, true, false);
bindingType = SamlProtocol.getLogoutBindingTypeForClientSession(clientSession);
Expand All @@ -143,10 +147,8 @@ public void testGetLogoutBindingTypeForClientSession() {
client.defineSetLogoutUrls(false, false, true, false);
bindingType = SamlProtocol.getLogoutBindingTypeForClientSession(clientSession);
assertEquals(SamlProtocol.SAML_ARTIFACT_BINDING, bindingType);

}


@Test
public void frontchannelLogoutSignsLogoutRequestsEvenThoughArtifactWasUsed() {
TestClientModel client = new TestClientModel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,49 @@ public void testLogoutWithPostBindingUnsetRedirectBindingSet() {
assertLogoutEvent(SAML_CLIENT_ID_SALES_POST2);
}

@Test
public void testFrontchannelLogoutInSameBrowserUsingDefaultAdminUrl() {
adminClient.realm(REALM_NAME)
.clients().get(sales2Rep.getId())
.update(ClientBuilder.edit(sales2Rep)
.frontchannelLogout(true)
.attribute(SamlConfigAttributes.SAML_FORCE_POST_BINDING, Boolean.TRUE.toString())
.attribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE, "")
.attribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE, "")
.adminUrl(SAML_ASSERTION_CONSUMER_URL_SALES_POST2)
.build());

SAMLDocumentHolder samlResponse = prepareLogIntoTwoApps()
.logoutRequest(getAuthServerSamlEndpoint(REALM_NAME), SAML_CLIENT_ID_SALES_POST, POST)
.nameId(nameIdRef::get)
.sessionIndex(sessionIndexRef::get)
.build()

.processSamlResponse(POST)
.transformDocument(doc -> {
// Expect logout request for sales-post2
SAML2Object so = (SAML2Object) SAMLParser.getInstance().parse(new DOMSource(doc));
assertThat(so, isSamlLogoutRequest(SAML_ASSERTION_CONSUMER_URL_SALES_POST2));

// 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.getSaml 61B4 Object(), isSamlStatusResponse(JBossSAMLURIConstants.STATUS_SUCCESS));
assertThat(((StatusResponseType) samlResponse.getSamlObject()).getDestination(), is("http://url"));
assertLogoutEvent(SAML_CLIENT_ID_SALES_POST2);
}

private void assertLogoutEvent(String clientId) {
List<EventRepresentation> logoutEvents = adminClient.realm(REALM_NAME)
.getEvents(Arrays.asList(EventType.LOGOUT.name()), clientId, null, null, null, null, null, null);
Expand Down
Loading
0