This change allows for the caller of the `saml/prepare` API to pass a `relay_state` parameter that will then be part of the redirect URL in the response as the `RelayState` query parameter. The SAML IdP is required to reflect back the value of that relay state when sending a SAML Response. The caller of the APIs can then, when receiving the SAML Response, read and consume the value as it see fit.
This commit is contained in:
parent
eef1ba3fad
commit
23bceaadf8
|
@ -179,8 +179,8 @@ task verifyVersions {
|
|||
* after the backport of the backcompat code is complete.
|
||||
*/
|
||||
|
||||
boolean bwc_tests_enabled = true
|
||||
final String bwc_tests_disabled_issue = "" /* place a PR link here when committing bwc changes */
|
||||
boolean bwc_tests_enabled = false
|
||||
final String bwc_tests_disabled_issue = "https://github.com/elastic/elasticsearch/pull/46534" /* place a PR link here when committing bwc changes */
|
||||
if (bwc_tests_enabled == false) {
|
||||
if (bwc_tests_disabled_issue.isEmpty()) {
|
||||
throw new GradleException("bwc_tests_disabled_issue must be set when bwc_tests_enabled == false")
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.core.security.action.saml;
|
||||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
|
@ -24,10 +25,16 @@ public final class SamlPrepareAuthenticationRequest extends ActionRequest {
|
|||
@Nullable
|
||||
private String assertionConsumerServiceURL;
|
||||
|
||||
@Nullable
|
||||
private String relayState;
|
||||
|
||||
public SamlPrepareAuthenticationRequest(StreamInput in) throws IOException {
|
||||
super(in);
|
||||
realmName = in.readOptionalString();
|
||||
assertionConsumerServiceURL = in.readOptionalString();
|
||||
if (in.getVersion().onOrAfter(Version.V_7_5_0)) {
|
||||
relayState = in.readOptionalString();
|
||||
}
|
||||
}
|
||||
|
||||
public SamlPrepareAuthenticationRequest() {
|
||||
|
@ -54,11 +61,20 @@ public final class SamlPrepareAuthenticationRequest extends ActionRequest {
|
|||
this.assertionConsumerServiceURL = assertionConsumerServiceURL;
|
||||
}
|
||||
|
||||
public String getRelayState() {
|
||||
return relayState;
|
||||
}
|
||||
|
||||
public void setRelayState(String relayState) {
|
||||
this.relayState = relayState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "{" +
|
||||
"realmName=" + realmName +
|
||||
", assertionConsumerServiceURL=" + assertionConsumerServiceURL +
|
||||
", relayState=" + relayState +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
@ -67,5 +83,8 @@ public final class SamlPrepareAuthenticationRequest extends ActionRequest {
|
|||
super.writeTo(out);
|
||||
out.writeOptionalString(realmName);
|
||||
out.writeOptionalString(assertionConsumerServiceURL);
|
||||
if (out.getVersion().onOrAfter(Version.V_7_5_0)) {
|
||||
out.writeOptionalString(relayState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,14 +49,14 @@ public final class TransportSamlPrepareAuthenticationAction
|
|||
} else if (realms.size() > 1) {
|
||||
listener.onFailure(SamlUtils.samlException("Found multiple matching realms [{}] for [{}]", realms, request));
|
||||
} else {
|
||||
prepareAuthentication(realms.get(0), listener);
|
||||
prepareAuthentication(realms.get(0), request.getRelayState(), listener);
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareAuthentication(SamlRealm realm, ActionListener<SamlPrepareAuthenticationResponse> listener) {
|
||||
private void prepareAuthentication(SamlRealm realm, String relayState, ActionListener<SamlPrepareAuthenticationResponse> listener) {
|
||||
final AuthnRequest authnRequest = realm.buildAuthenticationRequest();
|
||||
try {
|
||||
String redirectUrl = new SamlRedirect(authnRequest, realm.getSigningConfiguration()).getRedirectUrl();
|
||||
String redirectUrl = new SamlRedirect(authnRequest, realm.getSigningConfiguration()).getRedirectUrl(relayState);
|
||||
listener.onResponse(new SamlPrepareAuthenticationResponse(
|
||||
realm.name(),
|
||||
authnRequest.getID(),
|
||||
|
|
|
@ -25,7 +25,7 @@ public class SamlRedirect {
|
|||
private final SAMLObject samlObject;
|
||||
private final String destination;
|
||||
private final String parameterName;
|
||||
private final SigningConfiguration signing;
|
||||
private final SigningConfiguration signing;
|
||||
|
||||
public SamlRedirect(RequestAbstractType request, SigningConfiguration signing) {
|
||||
this.samlObject = request;
|
||||
|
|
|
@ -44,6 +44,7 @@ public class RestSamlPrepareAuthenticationAction extends SamlBaseRestHandler {
|
|||
static {
|
||||
PARSER.declareString(SamlPrepareAuthenticationRequest::setAssertionConsumerServiceURL, new ParseField("acs"));
|
||||
PARSER.declareString(SamlPrepareAuthenticationRequest::setRealmName, new ParseField("realm"));
|
||||
PARSER.declareString(SamlPrepareAuthenticationRequest::setRelayState, new ParseField("relay_state"));
|
||||
}
|
||||
|
||||
public RestSamlPrepareAuthenticationAction(Settings settings, RestController controller, XPackLicenseState licenseState) {
|
||||
|
|
|
@ -18,6 +18,7 @@ public class SamlPrepareAuthenticationRequestTests extends SamlTestCase {
|
|||
final SamlPrepareAuthenticationRequest req = new SamlPrepareAuthenticationRequest();
|
||||
req.setRealmName("saml1");
|
||||
req.setAssertionConsumerServiceURL("https://sp.example.com/sso/saml2/post");
|
||||
req.setRelayState("the_relay_state");
|
||||
serialiseAndValidate(req);
|
||||
}
|
||||
|
||||
|
@ -25,6 +26,7 @@ public class SamlPrepareAuthenticationRequestTests extends SamlTestCase {
|
|||
final SamlPrepareAuthenticationRequest req = new SamlPrepareAuthenticationRequest();
|
||||
req.setRealmName(null);
|
||||
req.setAssertionConsumerServiceURL(null);
|
||||
req.setRelayState(null);
|
||||
serialiseAndValidate(req);
|
||||
}
|
||||
|
||||
|
@ -36,7 +38,8 @@ public class SamlPrepareAuthenticationRequestTests extends SamlTestCase {
|
|||
|
||||
assertThat(req2.getRealmName(), Matchers.equalTo(req1.getRealmName()));
|
||||
assertThat(req2.getAssertionConsumerServiceURL(), Matchers.equalTo(req1.getAssertionConsumerServiceURL()));
|
||||
assertThat(req2.getRelayState(), Matchers.equalTo(req1.getRelayState()));
|
||||
assertThat(req2.getParentTask(), Matchers.equalTo(req1.getParentTask()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue