Skip to content

Commit a1549d9

Browse files
committed
Merge branch '6.2.x'
2 parents 24103b1 + cfb9f1e commit a1549d9

File tree

5 files changed

+246
-152
lines changed

5 files changed

+246
-152
lines changed

cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.springframework.security.authentication.AuthenticationProvider;
3232
import org.springframework.security.authentication.BadCredentialsException;
3333
import org.springframework.security.cas.ServiceProperties;
34-
import org.springframework.security.cas.web.authentication.ServiceAuthenticationDetails;
3534
import org.springframework.security.core.Authentication;
3635
import org.springframework.security.core.AuthenticationException;
3736
import org.springframework.security.core.SpringSecurityMessageSource;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2011-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.cas.authentication;
18+
19+
import java.io.Serializable;
20+
21+
import org.springframework.security.cas.ServiceProperties;
22+
import org.springframework.security.core.Authentication;
23+
24+
/**
25+
* In order for the {@link CasAuthenticationProvider} to provide the correct service url
26+
* to authenticate the ticket, the returned value of {@link Authentication#getDetails()}
27+
* should implement this interface when tickets can be sent to any URL rather than only
28+
* {@link ServiceProperties#getService()}.
29+
*
30+
* @author Rob Winch
31+
* @see org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource
32+
*/
33+
public interface ServiceAuthenticationDetails extends Serializable {
34+
35+
/**
36+
* Gets the absolute service url (i.e. https://example.com/service/).
37+
* @return the service url. Cannot be <code>null</code>.
38+
*/
39+
String getServiceUrl();
40+
41+
}

cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetails.java

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2023 the original author or authors.
2+
* Copyright 2011-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,22 +16,24 @@
1616

1717
package org.springframework.security.cas.web.authentication;
1818

19-
import java.io.Serializable;
20-
2119
import org.springframework.security.cas.ServiceProperties;
22-
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
2320
import org.springframework.security.core.Authentication;
2421

2522
/**
26-
* In order for the {@link CasAuthenticationProvider} to provide the correct service url
27-
* to authenticate the ticket, the returned value of {@link Authentication#getDetails()}
28-
* should implement this interface when tickets can be sent to any URL rather than only
29-
* {@link ServiceProperties#getService()}.
23+
* In order for the
24+
* {@link org.springframework.security.cas.authentication.CasAuthenticationProvider} to
25+
* provide the correct service url to authenticate the ticket, the returned value of
26+
* {@link Authentication#getDetails()} should implement this interface when tickets can be
27+
* sent to any URL rather than only {@link ServiceProperties#getService()}.
3028
*
3129
* @author Rob Winch
3230
* @see ServiceAuthenticationDetailsSource
31+
* @deprecated Please use
32+
* org.springframework.security.cas.authentication.ServiceAuthenticationDetails
3333
*/
34-
public interface ServiceAuthenticationDetails extends Serializable {
34+
@Deprecated
35+
public interface ServiceAuthenticationDetails
36+
extends org.springframework.security.cas.authentication.ServiceAuthenticationDetails {
3537

3638
/**
3739
* Gets the absolute service url (i.e. https://example.com/service/).
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,166 +16,33 @@
1616

1717
package org.springframework.security.saml2.provider.service.metadata;
1818

19-
import java.io.UnsupportedEncodingException;
20-
import java.net.URLEncoder;
21-
import java.nio.charset.StandardCharsets;
22-
import java.util.Collections;
23-
import java.util.LinkedHashMap;
24-
import java.util.Map;
25-
import java.util.UUID;
26-
27-
import jakarta.servlet.http.HttpServletRequest;
28-
29-
import org.springframework.security.saml2.Saml2Exception;
3019
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
3120
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
32-
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers;
33-
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers.UriResolver;
34-
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
35-
import org.springframework.security.web.util.matcher.OrRequestMatcher;
3621
import org.springframework.security.web.util.matcher.RequestMatcher;
37-
import org.springframework.util.Assert;
3822

3923
/**
4024
* An implementation of {@link Saml2MetadataResponseResolver} that identifies which
4125
* {@link RelyingPartyRegistration}s to use with a {@link RequestMatcher}
4226
*
4327
* @author Josh Cummings
4428
* @since 6.1
29+
* @deprecated Please use
30+
* {@link org.springframework.security.saml2.provider.service.web.metadata.RequestMatcherMetadataResponseResolver}
4531
*/
46-
public final class RequestMatcherMetadataResponseResolver implements Saml2MetadataResponseResolver {
47-
48-
private static final String DEFAULT_METADATA_FILENAME = "saml-{registrationId}-metadata.xml";
49-
50-
private RequestMatcher matcher = new OrRequestMatcher(
51-
new AntPathRequestMatcher("/saml2/service-provider-metadata/{registrationId}"),
52-
new AntPathRequestMatcher("/saml2/metadata/{registrationId}"),
53-
new AntPathRequestMatcher("/saml2/metadata"));
54-
55-
private String filename = DEFAULT_METADATA_FILENAME;
56-
57-
private final RelyingPartyRegistrationRepository registrations;
58-
59-
private final Saml2MetadataResolver metadata;
32+
@Deprecated
33+
public final class RequestMatcherMetadataResponseResolver extends
34+
org.springframework.security.saml2.provider.service.web.metadata.RequestMatcherMetadataResponseResolver {
6035

6136
/**
62-
* Construct a {@link RequestMatcherMetadataResponseResolver}
37+
* Construct a
38+
* {@link org.springframework.security.saml2.provider.service.web.metadata.RequestMatcherMetadataResponseResolver}
6339
* @param registrations the source for relying party metadata
6440
* @param metadata the strategy for converting {@link RelyingPartyRegistration}s into
6541
* metadata
6642
*/
6743
public RequestMatcherMetadataResponseResolver(RelyingPartyRegistrationRepository registrations,
6844
Saml2MetadataResolver metadata) {
69-
Assert.notNull(registrations, "relyingPartyRegistrationRepository cannot be null");
70-
Assert.notNull(metadata, "saml2MetadataResolver cannot be null");
71-
this.registrations = registrations;
72-
this.metadata = metadata;
73-
}
74-
75-
/**
76-
* Construct and serialize a relying party's SAML 2.0 metadata based on the given
77-
* {@link HttpServletRequest}. Uses the configured {@link RequestMatcher} to identify
78-
* the metadata request, including looking for any indicated {@code registrationId}.
79-
*
80-
* <p>
81-
* If a {@code registrationId} is found in the request, it will attempt to use that,
82-
* erroring if no {@link RelyingPartyRegistration} is found.
83-
*
84-
* <p>
85-
* If no {@code registrationId} is found in the request, it will attempt to show all
86-
* {@link RelyingPartyRegistration}s in an {@code <md:EntitiesDescriptor>}. To
87-
* exercise this functionality, the provided
88-
* {@link RelyingPartyRegistrationRepository} needs to implement {@link Iterable}.
89-
* @param request the HTTP request
90-
* @return a {@link Saml2MetadataResponse} instance
91-
* @throws Saml2Exception if the {@link RequestMatcher} specifies a non-existent
92-
* {@code registrationId}
93-
*/
94-
@Override
95-
public Saml2MetadataResponse resolve(HttpServletRequest request) {
96-
RequestMatcher.MatchResult result = this.matcher.matcher(request);
97-
if (!result.isMatch()) {
98-
return null;
99-
}
100-
String registrationId = result.getVariables().get("registrationId");
101-
Saml2MetadataResponse response = responseByRegistrationId(request, registrationId);
102-
if (response != null) {
103-
return response;
104-
}
105-
if (this.registrations instanceof Iterable<?>) {
106-
Iterable<RelyingPartyRegistration> registrations = (Iterable<RelyingPartyRegistration>) this.registrations;
107-
return responseByIterable(request, registrations);
108-
}
109-
return null;
110-
}
111-
112-
private Saml2MetadataResponse responseByRegistrationId(HttpServletRequest request, String registrationId) {
113-
if (registrationId == null) {
114-
return null;
115-
}
116-
RelyingPartyRegistration registration = this.registrations.findByRegistrationId(registrationId);
117-
if (registration == null) {
118-
throw new Saml2Exception("registration not found");
119-
}
120-
return responseByIterable(request, Collections.singleton(registration));
121-
}
122-
123-
private Saml2MetadataResponse responseByIterable(HttpServletRequest request,
124-
Iterable<RelyingPartyRegistration> registrations) {
125-
Map<String, RelyingPartyRegistration> results = new LinkedHashMap<>();
126-
for (RelyingPartyRegistration registration : registrations) {
127-
UriResolver uriResolver = RelyingPartyRegistrationPlaceholderResolvers.uriResolver(request, registration);
128-
String entityId = uriResolver.resolve(registration.getEntityId());
129-
results.computeIfAbsent(entityId, (e) -> {
130-
String ssoLocation = uriResolver.resolve(registration.getAssertionConsumerServiceLocation());
131-
String sloLocation = uriResolver.resolve(registration.getSingleLogoutServiceLocation());
132-
String sloResponseLocation = uriResolver.resolve(registration.getSingleLogoutServiceResponseLocation());
133-
return registration.mutate()
134-
.entityId(entityId)
135-
.assertionConsumerServiceLocation(ssoLocation)
136-
.singleLogoutServiceLocation(sloLocation)
137-
.singleLogoutServiceResponseLocation(sloResponseLocation)
138-
.build();
139-
});
140-
}
141-
String metadata = this.metadata.resolve(results.values());
142-
String value = (results.size() == 1) ? results.values().iterator().next().getRegistrationId()
143-
: UUID.randomUUID().toString();
144-
String fileName = this.filename.replace("{registrationId}", value);
145-
try {
146-
String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
147-
return new Saml2MetadataResponse(metadata, encodedFileName);
148-
}
149-
catch (UnsupportedEncodingException ex) {
150-
throw new Saml2Exception(ex);
151-
}
152-
}
153-
154-
/**
155-
* Use this {@link RequestMatcher} to identity which requests to generate metadata
156-
* for. By default, matches {@code /saml2/metadata},
157-
* {@code /saml2/metadata/{registrationId}}, {@code /saml2/service-provider-metadata},
158-
* and {@code /saml2/service-provider-metadata/{registrationId}}
159-
* @param requestMatcher the {@link RequestMatcher} to use
160-
*/
161-
public void setRequestMatcher(RequestMatcher requestMatcher) {
162-
Assert.notNull(requestMatcher, "requestMatcher cannot be empty");
163-
this.matcher = requestMatcher;
164-
}
165-
166-
/**
167-
* Sets the metadata filename template. If it contains the {@code {registrationId}}
168-
* placeholder, it will be resolved as a random UUID if there are multiple
169-
* {@link RelyingPartyRegistration}s. Otherwise, it will be replaced by the
170-
* {@link RelyingPartyRegistration}'s id.
171-
*
172-
* <p>
173-
* The default value is {@code saml-{registrationId}-metadata.xml}
174-
* @param metadataFilename metadata filename, must contain a {registrationId}
175-
*/
176-
public void setMetadataFilename(String metadataFilename) {
177-
Assert.hasText(metadataFilename, "metadataFilename cannot be empty");
178-
this.filename = metadataFilename;
45+
super(registrations, metadata);
17946
}
18047

18148
}

0 commit comments

Comments
 (0)