Skip to content
Open
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 @@ -37,6 +37,13 @@ public interface Saml2ErrorCodes {
*/
String MALFORMED_RESPONSE_DATA = "malformed_response_data";

/**
* Request is invalid in a general way.
*
* @since 5.5
*/
String INVALID_REQUEST = "invalid_request";

/**
* Response is invalid in a general way.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ public static Converter<ResponseToken, Saml2Authentication> createDefaultRespons
String username = assertion.getSubject().getNameID().getValue();
Map<String, List<Object>> attributes = getAssertionAttributes(assertion);
return new Saml2Authentication(new DefaultSaml2AuthenticatedPrincipal(username, attributes),
token.getSaml2Response(), Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")));
token.getSaml2Response(), Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")), responseToken.token.getRelyingPartyRegistration());
};
}

Expand Down Expand Up @@ -709,7 +709,8 @@ private Converter<ResponseToken, Saml2Authentication> createCompatibleResponseAu
Map<String, List<Object>> attributes = getAssertionAttributes(assertion);
return new Saml2Authentication(new DefaultSaml2AuthenticatedPrincipal(username, attributes),
token.getSaml2Response(),
this.authoritiesMapper.mapAuthorities(getAssertionAuthorities(assertion)));
this.authoritiesMapper.mapAuthorities(getAssertionAuthorities(assertion)),
responseToken.token.getRelyingPartyRegistration());
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.springframework.security.core.AuthenticatedPrincipal;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.util.Assert;

/**
Expand All @@ -41,14 +42,38 @@ public class Saml2Authentication extends AbstractAuthenticationToken {

private final String saml2Response;

private final RelyingPartyRegistration registration;

/**
* Construct a {@link Saml2Authentication} using the provided parameters
* @param principal the logged in user
* @param saml2Response the SAML 2.0 response used to authenticate the user
* @param authorities the authorities for the logged in user
* @deprecated Use {@link Saml2Authentication(AuthenticatedPrincipal, String,
* Collection, RelyingPartyRegistration) instead}
*/
@Deprecated
public Saml2Authentication(AuthenticatedPrincipal principal, String saml2Response,
Collection<? extends GrantedAuthority> authorities) {
this(principal, saml2Response, authorities, null);
}

/**
* Construct a {@link Saml2Authentication} using the provided parameters
* @param principal the logged in user
* @param saml2Response the SAML 2.0 response used to authenticate the user
* @param authorities the authorities for the logged in user
* @param registration the {@link RelyingPartyRegistration} associated with this user
*/
public Saml2Authentication(AuthenticatedPrincipal principal, String saml2Response,
Collection<? extends GrantedAuthority> authorities, RelyingPartyRegistration registration) {
super(authorities);
Assert.notNull(principal, "principal cannot be null");
Assert.hasText(saml2Response, "saml2Response cannot be null");
this.principal = principal;
this.saml2Response = saml2Response;
setAuthenticated(true);
this.registration = registration;
}

@Override
Expand All @@ -69,4 +94,8 @@ public Object getCredentials() {
return getSaml2Response();
}

public RelyingPartyRegistration getRegistration() {
return this.registration;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.security.saml2.provider.service.authentication.logout;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

public class Saml2LogoutRequest {

private final Map<String, String> parameters;

private Saml2LogoutRequest(Map<String, String> parameters) {
this.parameters = Collections.unmodifiableMap(new HashMap<>(parameters));
}

public String getSamlRequest() {
return this.parameters.get("SAMLRequest");
}

public String getParameter(String name) {
return this.parameters.get(name);
}

public Map<String, String> getParameters() {
return this.parameters;
}

public static Builder builder() {
return new Builder();
}

public static class Builder {

private Map<String, String> parameters = new HashMap<>();

public Builder samlRequest(String samlRequest) {
this.parameters.put("SAMLRequest", samlRequest);
return this;
}

public Builder parameters(Consumer<Map<String, String>> parametersConsumer) {
parametersConsumer.accept(this.parameters);
return this;
}

public Saml2LogoutRequest build() {
return new Saml2LogoutRequest(this.parameters);
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.security.saml2.provider.service.authentication.logout;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

public class Saml2LogoutResponse {

private final Map<String, String> parameters;

private Saml2LogoutResponse(Map<String, String> parameters) {
this.parameters = Collections.unmodifiableMap(new HashMap<>(parameters));
}

public String getSamlResponse() {
return this.parameters.get("SAMLResponse");
}

public String getParameter(String name) {
return this.parameters.get(name);
}

public Map<String, String> getParameters() {
return this.parameters;
}

public static Builder builder() {
return new Builder();
}

public static class Builder {

private Map<String, String> parameters = new HashMap<>();

public Builder samlRequest(String samlRequest) {
this.parameters.put("SAMLRequest", samlRequest);
return this;
}

public Builder parameters(Consumer<Map<String, String>> parametersConsumer) {
parametersConsumer.accept(this.parameters);
return this;
}

public Saml2LogoutResponse build() {
return new Saml2LogoutResponse(this.parameters);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.opensaml.saml.saml2.metadata.Extensions;
import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
import org.opensaml.saml.saml2.metadata.KeyDescriptor;
import org.opensaml.saml.saml2.metadata.SingleLogoutService;
import org.opensaml.saml.saml2.metadata.SingleSignOnService;
import org.opensaml.security.credential.UsageType;
import org.opensaml.xmlsec.keyinfo.KeyInfoSupport;
Expand Down Expand Up @@ -105,6 +106,10 @@ RelyingPartyRegistration.Builder convert(InputStream inputStream) {
builder.assertingPartyDetails(
(party) -> party.signingAlgorithms((algorithms) -> algorithms.add(method.getAlgorithm())));
}
if (idpssoDescriptor.getSingleSignOnServices().isEmpty()) {
throw new Saml2Exception(
"Metadata response is missing a SingleSignOnService, necessary for sending AuthnRequests");
}
for (SingleSignOnService singleSignOnService : idpssoDescriptor.getSingleSignOnServices()) {
Saml2MessageBinding binding;
if (singleSignOnService.getBinding().equals(Saml2MessageBinding.POST.getUrn())) {
Expand All @@ -119,10 +124,26 @@ else if (singleSignOnService.getBinding().equals(Saml2MessageBinding.REDIRECT.ge
builder.assertingPartyDetails(
(party) -> party.singleSignOnServiceLocation(singleSignOnService.getLocation())
.singleSignOnServiceBinding(binding));
return builder;
break;
}
for (SingleLogoutService singleLogoutService : idpssoDescriptor.getSingleLogoutServices()) {
Saml2MessageBinding binding;
if (singleLogoutService.getBinding().equals(Saml2MessageBinding.POST.getUrn())) {
binding = Saml2MessageBinding.POST;
}
else if (singleLogoutService.getBinding().equals(Saml2MessageBinding.REDIRECT.getUrn())) {
binding = Saml2MessageBinding.REDIRECT;
}
else {
continue;
}
builder.assertingPartyDetails(
(party) -> party.singleLogoutServiceLocation(singleLogoutService.getLocation())
.singleLogoutServiceResponseLocation(singleLogoutService.getResponseLocation())
.singleLogoutServiceBinding(binding));
break;
}
throw new Saml2Exception(
"Metadata response is missing a SingleSignOnService, necessary for sending AuthnRequests");
return builder;
}

private List<X509Certificate> certificates(KeyDescriptor keyDescriptor) {
Expand Down
Loading