Compare commits
75 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e8aef09b4f | |||
| f8d417dc03 | |||
| 79bacf8204 | |||
| 9bcfeab1d6 | |||
| 254c9c9b2d | |||
| a5d963387b | |||
| e5d9659b8f | |||
| 99c4f58c34 | |||
| cb60d8b3ed | |||
| c1aa99fdd2 | |||
| f1a211ae0c | |||
| a1481572ed | |||
| eb01394427 | |||
| 0ff3474e2d | |||
| 2ce4aecec7 | |||
| 7c90300912 | |||
| 0d3d6f75f8 | |||
| a10a35c2ac | |||
| ee13d19503 | |||
| eb83c35ded | |||
| db34de59bc | |||
| 3c0fef59b5 | |||
| da94fbe431 | |||
| a081402383 | |||
| f3c8262a00 | |||
| 0954638d57 | |||
| 857ef6fe08 | |||
| 55815103a5 | |||
| 26c63aeb01 | |||
| b7df86197c | |||
| c84c438075 | |||
| 1ad4323cec | |||
| 1e7db094d1 | |||
| 6c5b6d1c51 | |||
| 456604ab45 | |||
| 15b9a50060 | |||
| fcc1bd598d | |||
| 1f3dd53bdf | |||
| a6b5c05da9 | |||
| 9c054474a8 | |||
| 593f7c4490 | |||
| 4e20d56d2d | |||
| 26aa253633 | |||
| af2668f7cb | |||
| 0a084135ec | |||
| 5571ad1b27 | |||
| e3a715b8f5 | |||
| 2f04512e01 | |||
| 23444dd13f | |||
| 883765b2de | |||
| c032b20178 | |||
| 58e7ba4a4b | |||
| db8b6322e2 | |||
| 72554f7f36 | |||
| af8786150e | |||
| 65e83f8e7a | |||
| 96cfbd1e6c | |||
| ab6e9d2d1f | |||
| a53ca7c3d0 | |||
| af40d7e35a | |||
| daf8cfe8d2 | |||
| 75b537f99a | |||
| 55d61224e5 | |||
| d1b7f8a119 | |||
| 85c906290d | |||
| 68f08c26d0 | |||
| 5353d499b4 | |||
| 60df37b026 | |||
| d9a937f0c1 | |||
| 06893bc047 | |||
| 1d75b907f9 | |||
| 7dbd69fee1 | |||
| 816f3cd64d | |||
| 147081f771 | |||
| 0bc9313fdd |
@@ -18,7 +18,7 @@ jobs:
|
||||
matrix:
|
||||
branch: [ '5.8.x', '6.2.x', '6.3.x', 'main' ]
|
||||
steps:
|
||||
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@852920ba3fb1f28b35a2f13201133bc00ef33677
|
||||
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@e28269199d1d27975cf7f65e16d6095c555b3cd0
|
||||
name: Update
|
||||
with:
|
||||
docs-branch: ${{ matrix.branch }}
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Update on docs-build
|
||||
steps:
|
||||
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@852920ba3fb1f28b35a2f13201133bc00ef33677
|
||||
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@e28269199d1d27975cf7f65e16d6095c555b3cd0
|
||||
name: Update
|
||||
with:
|
||||
docs-branch: 'docs-build'
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ wrapperUpgrade {
|
||||
gradle {
|
||||
'spring-security' {
|
||||
repo = 'spring-projects/spring-security'
|
||||
baseBranch = '6.2.x' // runs only on 6.2.x and the update is merged forward to main
|
||||
baseBranch = '6.3.x' // runs only on 6.3.x and the update is merged forward to main
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -183,6 +183,9 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
|
||||
BeanDefinitionBuilder csrfAuthenticationStrategy = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(CsrfAuthenticationStrategy.class);
|
||||
csrfAuthenticationStrategy.addConstructorArgReference(this.csrfRepositoryRef);
|
||||
if (StringUtils.hasText(this.requestHandlerRef)) {
|
||||
csrfAuthenticationStrategy.addPropertyReference("requestHandler", this.requestHandlerRef);
|
||||
}
|
||||
return csrfAuthenticationStrategy.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
||||
+17
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -56,6 +56,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.annotation.AnnotationConfigurationException;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
@@ -1103,6 +1104,21 @@ public class PrePostMethodSecurityConfigurationTests {
|
||||
verifyNoInteractions(handler);
|
||||
}
|
||||
|
||||
// gh-16819
|
||||
@Test
|
||||
void autowireWhenDefaultsThenAdvisorAnnotationsAreSorted() {
|
||||
this.spring.register(MethodSecurityServiceConfig.class).autowire();
|
||||
AuthorizationAdvisorProxyFactory proxyFactory = this.spring.getContext()
|
||||
.getBean(AuthorizationAdvisorProxyFactory.class);
|
||||
AnnotationAwareOrderComparator comparator = AnnotationAwareOrderComparator.INSTANCE;
|
||||
AuthorizationAdvisor previous = null;
|
||||
for (AuthorizationAdvisor advisor : proxyFactory) {
|
||||
boolean ordered = previous == null || comparator.compare(previous, advisor) < 0;
|
||||
assertThat(ordered).isTrue();
|
||||
previous = advisor;
|
||||
}
|
||||
}
|
||||
|
||||
private static Consumer<ConfigurableWebApplicationContext> disallowBeanOverriding() {
|
||||
return (context) -> ((AnnotationConfigWebApplicationContext) context).setAllowBeanDefinitionOverriding(false);
|
||||
}
|
||||
|
||||
+4
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -1560,12 +1560,15 @@ public class OAuth2ResourceServerConfigurerTests {
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
DefaultBearerTokenResolver defaultBearerTokenResolver = new DefaultBearerTokenResolver();
|
||||
defaultBearerTokenResolver.setAllowUriQueryParameter(true);
|
||||
http
|
||||
.authorizeRequests()
|
||||
.requestMatchers("/requires-read-scope").access("hasAuthority('SCOPE_message:read')")
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.oauth2ResourceServer()
|
||||
.bearerTokenResolver(defaultBearerTokenResolver)
|
||||
.jwt()
|
||||
.jwkSetUri(this.jwkSetUri);
|
||||
return http.build();
|
||||
|
||||
@@ -336,6 +336,43 @@ public class CsrfConfigTests {
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postWhenUsingCsrfAndXorCsrfTokenRequestAttributeHandlerThenCsrfAuthenticationStrategyUses()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("WithXorCsrfTokenRequestAttributeHandler"), this.xml("shared-controllers"))
|
||||
.autowire();
|
||||
// @formatter:off
|
||||
MvcResult mvcResult1 = this.mvc.perform(get("/csrf"))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
MockHttpServletRequest request1 = mvcResult1.getRequest();
|
||||
MockHttpSession session = (MockHttpSession) request1.getSession();
|
||||
CsrfTokenRepository repository = WebTestUtils.getCsrfTokenRepository(request1);
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder login = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.session(session)
|
||||
.with(csrf());
|
||||
this.mvc.perform(login)
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:on
|
||||
assertThat(repository.loadToken(request1)).isNull();
|
||||
// @formatter:off
|
||||
MvcResult mvcResult2 = this.mvc.perform(get("/csrf").session(session))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
MockHttpServletRequest request2 = mvcResult2.getRequest();
|
||||
CsrfToken csrfToken = repository.loadToken(request2);
|
||||
CsrfToken csrfTokenAttribute = (CsrfToken) request2.getAttribute(CsrfToken.class.getName());
|
||||
assertThat(csrfTokenAttribute).isNotNull();
|
||||
assertThat(csrfTokenAttribute.getToken()).isNotBlank();
|
||||
assertThat(csrfTokenAttribute.getToken()).isNotEqualTo(csrfToken.getToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postWhenHasCsrfTokenButSessionExpiresThenRequestIsCancelledAfterSuccessfulAuthentication()
|
||||
throws Exception {
|
||||
|
||||
+6
-1
@@ -25,10 +25,15 @@
|
||||
|
||||
<c:property-placeholder local-override="true"/>
|
||||
|
||||
<b:bean id="bearerTokenResolver"
|
||||
class="org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver">
|
||||
<b:property name="allowUriQueryParameter" value="true"/>
|
||||
</b:bean>
|
||||
|
||||
<http>
|
||||
<intercept-url pattern="/**" access="authenticated"/>
|
||||
<intercept-url pattern="/requires-read-scope" access="hasAuthority('SCOPE_message:read')"/>
|
||||
<oauth2-resource-server>
|
||||
<oauth2-resource-server bearer-token-resolver-ref="bearerTokenResolver">
|
||||
<jwt jwk-set-uri="${jwk-set-uri:https://idp.example.org}"/>
|
||||
</oauth2-resource-server>
|
||||
</http>
|
||||
|
||||
+14
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -47,6 +47,7 @@ import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.framework.AopInfrastructureBean;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.security.authorization.AuthorizationProxyFactory;
|
||||
@@ -79,8 +80,8 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Josh Cummings
|
||||
* @since 6.3
|
||||
*/
|
||||
public final class AuthorizationAdvisorProxyFactory
|
||||
implements AuthorizationProxyFactory, Iterable<AuthorizationAdvisor>, AopInfrastructureBean {
|
||||
public final class AuthorizationAdvisorProxyFactory implements AuthorizationProxyFactory,
|
||||
Iterable<AuthorizationAdvisor>, AopInfrastructureBean, SmartInitializingSingleton {
|
||||
|
||||
private static final boolean isReactivePresent = ClassUtils.isPresent("reactor.core.publisher.Mono", null);
|
||||
|
||||
@@ -125,6 +126,7 @@ public final class AuthorizationAdvisorProxyFactory
|
||||
advisors.add(new PostFilterAuthorizationMethodInterceptor());
|
||||
AuthorizationAdvisorProxyFactory proxyFactory = new AuthorizationAdvisorProxyFactory(advisors);
|
||||
proxyFactory.addAdvisor(new AuthorizeReturnObjectMethodInterceptor(proxyFactory));
|
||||
AnnotationAwareOrderComparator.sort(proxyFactory.advisors);
|
||||
return proxyFactory;
|
||||
}
|
||||
|
||||
@@ -142,9 +144,15 @@ public final class AuthorizationAdvisorProxyFactory
|
||||
advisors.add(new PostFilterAuthorizationReactiveMethodInterceptor());
|
||||
AuthorizationAdvisorProxyFactory proxyFactory = new AuthorizationAdvisorProxyFactory(advisors);
|
||||
proxyFactory.addAdvisor(new AuthorizeReturnObjectMethodInterceptor(proxyFactory));
|
||||
AnnotationAwareOrderComparator.sort(proxyFactory.advisors);
|
||||
return proxyFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
AnnotationAwareOrderComparator.sort(this.advisors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy an object to enforce authorization advice.
|
||||
*
|
||||
@@ -165,7 +173,6 @@ public final class AuthorizationAdvisorProxyFactory
|
||||
*/
|
||||
@Override
|
||||
public Object proxy(Object target) {
|
||||
AnnotationAwareOrderComparator.sort(this.advisors);
|
||||
if (target == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -178,9 +185,9 @@ public final class AuthorizationAdvisorProxyFactory
|
||||
}
|
||||
ProxyFactory factory = new ProxyFactory(target);
|
||||
factory.addAdvisors(this.authorizationProxy);
|
||||
for (Advisor advisor : this.advisors) {
|
||||
factory.addAdvisors(advisor);
|
||||
}
|
||||
List<Advisor> advisors = new ArrayList<>(this.advisors);
|
||||
AnnotationAwareOrderComparator.sort(advisors);
|
||||
factory.addAdvisors(advisors);
|
||||
factory.addInterface(AuthorizationProxy.class);
|
||||
factory.setOpaque(true);
|
||||
factory.setProxyTargetClass(!Modifier.isFinal(target.getClass().getModifiers()));
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -48,7 +48,7 @@ public final class AuthorizeReturnObjectMethodInterceptor implements Authorizati
|
||||
private int order = AuthorizationInterceptorsOrder.SECURE_RESULT.getOrder();
|
||||
|
||||
public AuthorizeReturnObjectMethodInterceptor(AuthorizationProxyFactory authorizationProxyFactory) {
|
||||
Assert.notNull(authorizationProxyFactory, "authorizationManager cannot be null");
|
||||
Assert.notNull(authorizationProxyFactory, "authorizationProxyFactory cannot be null");
|
||||
this.authorizationProxyFactory = authorizationProxyFactory;
|
||||
}
|
||||
|
||||
|
||||
+28
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -40,6 +40,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.authentication.TestAuthentication;
|
||||
@@ -360,6 +361,32 @@ public class AuthorizationAdvisorProxyFactoryTests {
|
||||
assertThat(target).isSameAs(this.flight);
|
||||
}
|
||||
|
||||
// gh-16819
|
||||
@Test
|
||||
void advisorsWhenWithDefaultsThenAreSorted() {
|
||||
AuthorizationAdvisorProxyFactory proxyFactory = AuthorizationAdvisorProxyFactory.withDefaults();
|
||||
AnnotationAwareOrderComparator comparator = AnnotationAwareOrderComparator.INSTANCE;
|
||||
AuthorizationAdvisor previous = null;
|
||||
for (AuthorizationAdvisor advisor : proxyFactory) {
|
||||
boolean ordered = previous == null || comparator.compare(previous, advisor) < 0;
|
||||
assertThat(ordered).isTrue();
|
||||
previous = advisor;
|
||||
}
|
||||
}
|
||||
|
||||
// gh-16819
|
||||
@Test
|
||||
void advisorsWhenWithReactiveDefaultsThenAreSorted() {
|
||||
AuthorizationAdvisorProxyFactory proxyFactory = AuthorizationAdvisorProxyFactory.withReactiveDefaults();
|
||||
AnnotationAwareOrderComparator comparator = AnnotationAwareOrderComparator.INSTANCE;
|
||||
AuthorizationAdvisor previous = null;
|
||||
for (AuthorizationAdvisor advisor : proxyFactory) {
|
||||
boolean ordered = previous == null || comparator.compare(previous, advisor) < 0;
|
||||
assertThat(ordered).isTrue();
|
||||
previous = advisor;
|
||||
}
|
||||
}
|
||||
|
||||
private Authentication authenticated(String user, String... authorities) {
|
||||
return TestAuthentication.authenticated(TestAuthentication.withUsername(user).authorities(authorities).build());
|
||||
}
|
||||
|
||||
@@ -611,7 +611,8 @@ public class BCrypt {
|
||||
int rounds, off;
|
||||
StringBuilder rs = new StringBuilder();
|
||||
|
||||
if (passwordb.length > 72) {
|
||||
// Enforce max length for new passwords only
|
||||
if (!for_check && passwordb.length > 72) {
|
||||
throw new IllegalArgumentException("password cannot be more than 72 bytes");
|
||||
}
|
||||
if (salt == null) {
|
||||
|
||||
+26
-5
@@ -223,13 +223,34 @@ public class BCryptPasswordEncoderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enforcePasswordLength() {
|
||||
public void encodeWhenPasswordOverMaxLengthThenThrowIllegalArgumentException() {
|
||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||
|
||||
String password72chars = "123456789012345678901234567890123456789012345678901234567890123456789012";
|
||||
assertThat(encoder.matches(password72chars, encoder.encode(password72chars))).isTrue();
|
||||
String password73chars = password72chars.concat("a");
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> encoder.matches(password73chars, encoder.encode(password73chars)));
|
||||
encoder.encode(password72chars);
|
||||
|
||||
String password73chars = password72chars + "3";
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> encoder.encode(password73chars));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesWhenPasswordOverMaxLengthThenAllowToMatch() {
|
||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||
|
||||
String password71chars = "12345678901234567890123456789012345678901234567890123456789012345678901";
|
||||
String encodedPassword71chars = "$2a$10$jx3x2FaF.iX5QZ9i3O424Os2Ou5P5JrnedmWYHuDyX8JKA4Unp4xq";
|
||||
assertThat(encoder.matches(password71chars, encodedPassword71chars)).isTrue();
|
||||
|
||||
String password72chars = password71chars + "2";
|
||||
String encodedPassword72chars = "$2a$10$oXYO6/UvbsH5rQEraBkl6uheccBqdB3n.RaWbrimog9hS2GX4lo/O";
|
||||
assertThat(encoder.matches(password72chars, encodedPassword72chars)).isTrue();
|
||||
|
||||
// Max length is 72 bytes, however, we need to ensure backwards compatibility
|
||||
// for previously encoded passwords that are greater than 72 bytes and allow the
|
||||
// match to be performed.
|
||||
String password73chars = password72chars + "3";
|
||||
String encodedPassword73chars = "$2a$10$1l9.kvQTsqNLiCYFqmKtQOHkp.BrgIrwsnTzWo9jdbQRbuBYQ/AVK";
|
||||
assertThat(encoder.matches(password73chars, encodedPassword73chars)).isTrue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
*** xref:servlet/appendix/faq.adoc[FAQ]
|
||||
* xref:reactive/index.adoc[Reactive Applications]
|
||||
** xref:reactive/getting-started.adoc[Getting Started]
|
||||
** Authentication
|
||||
** xref:reactive/authentication/index.adoc[Authentication]
|
||||
*** xref:reactive/authentication/x509.adoc[X.509 Authentication]
|
||||
*** xref:reactive/authentication/logout.adoc[Logout]
|
||||
*** Session Management
|
||||
|
||||
@@ -8,4 +8,4 @@ Once authentication is performed we know the identity and can perform authorizat
|
||||
|
||||
Spring Security provides built-in support for authenticating users.
|
||||
This section is dedicated to generic authentication support that applies in both Servlet and WebFlux environments.
|
||||
Refer to the sections on authentication for xref:servlet/authentication/index.adoc#servlet-authentication[Servlet] and xref:servlet/authentication/index.adoc[WebFlux] for details on what is supported for each stack.
|
||||
Refer to the sections on authentication for xref:servlet/authentication/index.adoc[Servlet] and xref:reactive/authentication/index.adoc[WebFlux] for details on what is supported for each stack.
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
= Spring Security
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Spring Security's documentation can be https://docs.spring.io/spring-security/reference/spring-security-docs.zip[downloaded] as a zip file.
|
||||
====
|
||||
|
||||
Spring Security is a framework that provides xref:features/authentication/index.adoc[authentication], xref:features/authorization/index.adoc[authorization], and xref:features/exploits/index.adoc[protection against common attacks].
|
||||
With first class support for securing both xref:servlet/index.adoc[imperative] and xref:reactive/index.adoc[reactive] applications, it is the de-facto standard for securing Spring-based applications.
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[[webflux-authentication]]
|
||||
= Authentication
|
||||
:page-section-summary-toc: 1
|
||||
@@ -34,7 +34,7 @@ The attributes on the `<http>` element control some of the properties on the cor
|
||||
Use AuthorizationManager API instead of SecurityMetadataSource (defaults to true)
|
||||
|
||||
[[nsa-http-authorization-manager-ref]]
|
||||
* **access-decision-manager-ref**
|
||||
* **use-authorization-manager**
|
||||
Use this AuthorizationManager instead of deriving one from <intercept-url> elements
|
||||
|
||||
[[nsa-http-access-decision-manager-ref]]
|
||||
|
||||
@@ -1048,8 +1048,8 @@ public class SecurityConfig {
|
||||
http
|
||||
.securityMatcher("/api/**") <1>
|
||||
.authorizeHttpRequests(authorize -> authorize
|
||||
.requestMatchers("/user/**").hasRole("USER") <2>
|
||||
.requestMatchers("/admin/**").hasRole("ADMIN") <3>
|
||||
.requestMatchers("/api/user/**").hasRole("USER") <2>
|
||||
.requestMatchers("/api/admin/**").hasRole("ADMIN") <3>
|
||||
.anyRequest().authenticated() <4>
|
||||
)
|
||||
.formLogin(withDefaults());
|
||||
@@ -1071,8 +1071,8 @@ open class SecurityConfig {
|
||||
http {
|
||||
securityMatcher("/api/**") <1>
|
||||
authorizeHttpRequests {
|
||||
authorize("/user/**", hasRole("USER")) <2>
|
||||
authorize("/admin/**", hasRole("ADMIN")) <3>
|
||||
authorize("/api/user/**", hasRole("USER")) <2>
|
||||
authorize("/api/admin/**", hasRole("ADMIN")) <3>
|
||||
authorize(anyRequest, authenticated) <4>
|
||||
}
|
||||
}
|
||||
@@ -1084,8 +1084,8 @@ open class SecurityConfig {
|
||||
======
|
||||
|
||||
<1> Configure `HttpSecurity` to only be applied to URLs that start with `/api/`
|
||||
<2> Allow access to URLs that start with `/user/` to users with the `USER` role
|
||||
<3> Allow access to URLs that start with `/admin/` to users with the `ADMIN` role
|
||||
<2> Allow access to URLs that start with `/api/user/` to users with the `USER` role
|
||||
<3> Allow access to URLs that start with `/api/admin/` to users with the `ADMIN` role
|
||||
<4> Any other request that doesn't match the rules above, will require authentication
|
||||
|
||||
The `securityMatcher(s)` and `requestMatcher(s)` methods will decide which `RequestMatcher` implementation fits best for your application: If {spring-framework-reference-url}web.html#spring-web[Spring MVC] is in the classpath, then javadoc:org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher[] will be used, otherwise, javadoc:org.springframework.security.web.util.matcher.AntPathRequestMatcher[] will be used.
|
||||
@@ -1111,8 +1111,8 @@ public class SecurityConfig {
|
||||
http
|
||||
.securityMatcher(antMatcher("/api/**")) <2>
|
||||
.authorizeHttpRequests(authorize -> authorize
|
||||
.requestMatchers(antMatcher("/user/**")).hasRole("USER") <3>
|
||||
.requestMatchers(regexMatcher("/admin/.*")).hasRole("ADMIN") <4>
|
||||
.requestMatchers(antMatcher("/api/user/**")).hasRole("USER") <3>
|
||||
.requestMatchers(regexMatcher("/api/admin/.*")).hasRole("ADMIN") <4>
|
||||
.requestMatchers(new MyCustomRequestMatcher()).hasRole("SUPERVISOR") <5>
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
@@ -1146,8 +1146,8 @@ open class SecurityConfig {
|
||||
http {
|
||||
securityMatcher(antMatcher("/api/**")) <2>
|
||||
authorizeHttpRequests {
|
||||
authorize(antMatcher("/user/**"), hasRole("USER")) <3>
|
||||
authorize(regexMatcher("/admin/**"), hasRole("ADMIN")) <4>
|
||||
authorize(antMatcher("/api/user/**"), hasRole("USER")) <3>
|
||||
authorize(regexMatcher("/api/admin/**"), hasRole("ADMIN")) <4>
|
||||
authorize(MyCustomRequestMatcher(), hasRole("SUPERVISOR")) <5>
|
||||
authorize(anyRequest, authenticated)
|
||||
}
|
||||
@@ -1161,8 +1161,8 @@ open class SecurityConfig {
|
||||
|
||||
<1> Import the static factory methods from `AntPathRequestMatcher` and `RegexRequestMatcher` to create `RequestMatcher` instances.
|
||||
<2> Configure `HttpSecurity` to only be applied to URLs that start with `/api/`, using `AntPathRequestMatcher`
|
||||
<3> Allow access to URLs that start with `/user/` to users with the `USER` role, using `AntPathRequestMatcher`
|
||||
<4> Allow access to URLs that start with `/admin/` to users with the `ADMIN` role, using `RegexRequestMatcher`
|
||||
<3> Allow access to URLs that start with `/api/user/` to users with the `USER` role, using `AntPathRequestMatcher`
|
||||
<4> Allow access to URLs that start with `/api/admin/` to users with the `ADMIN` role, using `RegexRequestMatcher`
|
||||
<5> Allow access to URLs that match the `MyCustomRequestMatcher` to users with the `SUPERVISOR` role, using a custom `RequestMatcher`
|
||||
|
||||
== Further Reading
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
= Spring MVC Test Integration
|
||||
:page-section-summary-toc: 1
|
||||
|
||||
Spring Security provides comprehensive integration with https://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html#spring-mvc-test-framework[Spring MVC Test]
|
||||
Spring Security provides comprehensive integration with {spring-framework-reference-url}testing/mockmvc.html[Spring MVC Test]
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
springBootVersion=3.3.3
|
||||
version=6.4.4
|
||||
version=6.4.5
|
||||
samplesBranch=main
|
||||
org.gradle.jvmargs=-Xmx3g -XX:+HeapDumpOnOutOfMemoryError
|
||||
org.gradle.parallel=true
|
||||
|
||||
@@ -6,18 +6,18 @@ io-spring-nohttp = "0.0.11"
|
||||
jakarta-websocket = "2.2.0"
|
||||
org-apache-directory-server = "1.5.5"
|
||||
org-apache-maven-resolver = "1.9.22"
|
||||
org-aspectj = "1.9.22.1"
|
||||
org-aspectj = "1.9.24"
|
||||
org-bouncycastle = "1.79"
|
||||
org-eclipse-jetty = "11.0.24"
|
||||
org-eclipse-jetty = "11.0.25"
|
||||
org-jetbrains-kotlin = "1.9.25"
|
||||
org-jetbrains-kotlinx = "1.9.0"
|
||||
org-mockito = "5.14.2"
|
||||
org-opensaml = "4.3.2"
|
||||
org-opensaml5 = "5.1.2"
|
||||
org-springframework = "6.2.4"
|
||||
org-springframework = "6.2.6"
|
||||
|
||||
[libraries]
|
||||
ch-qos-logback-logback-classic = "ch.qos.logback:logback-classic:1.5.17"
|
||||
ch-qos-logback-logback-classic = "ch.qos.logback:logback-classic:1.5.18"
|
||||
com-fasterxml-jackson-jackson-bom = "com.fasterxml.jackson:jackson-bom:2.18.3"
|
||||
com-google-inject-guice = "com.google.inject:guice:3.0"
|
||||
com-netflix-nebula-nebula-project-plugin = "com.netflix.nebula:nebula-project-plugin:8.2.0"
|
||||
@@ -28,15 +28,15 @@ com-squareup-okhttp3-okhttp = { module = "com.squareup.okhttp3:okhttp", version.
|
||||
com-unboundid-unboundid-ldapsdk = "com.unboundid:unboundid-ldapsdk:6.0.11"
|
||||
com-unboundid-unboundid-ldapsdk7 = "com.unboundid:unboundid-ldapsdk:7.0.1"
|
||||
commons-collections = "commons-collections:commons-collections:3.2.2"
|
||||
io-micrometer-micrometer-observation = "io.micrometer:micrometer-observation:1.14.5"
|
||||
io-micrometer-micrometer-observation = "io.micrometer:micrometer-observation:1.14.6"
|
||||
io-mockk = "io.mockk:mockk:1.13.17"
|
||||
io-projectreactor-reactor-bom = "io.projectreactor:reactor-bom:2023.0.16"
|
||||
io-projectreactor-reactor-bom = "io.projectreactor:reactor-bom:2023.0.17"
|
||||
io-rsocket-rsocket-bom = { module = "io.rsocket:rsocket-bom", version.ref = "io-rsocket" }
|
||||
io-spring-javaformat-spring-javaformat-checkstyle = { module = "io.spring.javaformat:spring-javaformat-checkstyle", version.ref = "io-spring-javaformat" }
|
||||
io-spring-javaformat-spring-javaformat-gradle-plugin = { module = "io.spring.javaformat:spring-javaformat-gradle-plugin", version.ref = "io-spring-javaformat" }
|
||||
io-spring-nohttp-nohttp-checkstyle = { module = "io.spring.nohttp:nohttp-checkstyle", version.ref = "io-spring-nohttp" }
|
||||
io-spring-nohttp-nohttp-gradle = { module = "io.spring.nohttp:nohttp-gradle", version.ref = "io-spring-nohttp" }
|
||||
io-spring-security-release-plugin = "io.spring.gradle:spring-security-release-plugin:1.0.3"
|
||||
io-spring-security-release-plugin = "io.spring.gradle:spring-security-release-plugin:1.0.4"
|
||||
jakarta-annotation-jakarta-annotation-api = "jakarta.annotation:jakarta.annotation-api:2.1.1"
|
||||
jakarta-inject-jakarta-inject-api = "jakarta.inject:jakarta.inject-api:2.0.1"
|
||||
jakarta-persistence-jakarta-persistence-api = "jakarta.persistence:jakarta.persistence-api:3.1.0"
|
||||
@@ -70,7 +70,7 @@ org-bouncycastle-bcprov-jdk15on = { module = "org.bouncycastle:bcprov-jdk18on",
|
||||
org-eclipse-jetty-jetty-server = { module = "org.eclipse.jetty:jetty-server", version.ref = "org-eclipse-jetty" }
|
||||
org-eclipse-jetty-jetty-servlet = { module = "org.eclipse.jetty:jetty-servlet", version.ref = "org-eclipse-jetty" }
|
||||
org-hamcrest = "org.hamcrest:hamcrest:2.2"
|
||||
org-hibernate-orm-hibernate-core = "org.hibernate.orm:hibernate-core:6.6.11.Final"
|
||||
org-hibernate-orm-hibernate-core = "org.hibernate.orm:hibernate-core:6.6.13.Final"
|
||||
org-hsqldb = "org.hsqldb:hsqldb:2.7.4"
|
||||
org-jetbrains-kotlin-kotlin-bom = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "org-jetbrains-kotlin" }
|
||||
org-jetbrains-kotlin-kotlin-gradle-plugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.25"
|
||||
@@ -89,7 +89,7 @@ org-skyscreamer-jsonassert = "org.skyscreamer:jsonassert:1.5.3"
|
||||
org-slf4j-log4j-over-slf4j = "org.slf4j:log4j-over-slf4j:1.7.36"
|
||||
org-slf4j-slf4j-api = "org.slf4j:slf4j-api:2.0.17"
|
||||
org-springframework-data-spring-data-bom = "org.springframework.data:spring-data-bom:2024.1.4"
|
||||
org-springframework-ldap-spring-ldap-core = "org.springframework.ldap:spring-ldap-core:3.2.11"
|
||||
org-springframework-ldap-spring-ldap-core = "org.springframework.ldap:spring-ldap-core:3.2.12"
|
||||
org-springframework-spring-framework-bom = { module = "org.springframework:spring-framework-bom", version.ref = "org-springframework" }
|
||||
org-synchronoss-cloud-nio-multipart-parser = "org.synchronoss.cloud:nio-multipart-parser:1.1.0"
|
||||
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+2
-2
@@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=8d97a97984f6cbd2b85fe4c60a743440a347544bf18818048e611f5288d46c94
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
|
||||
distributionSha256Sum=20f1b1176237254a6fc204d8434196fa11a4cfb387567519c61556e8710aed78
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -86,8 +86,7 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
@@ -206,7 +205,7 @@ fi
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -245,7 +245,7 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements
|
||||
* be used to create an Authentication for saving.</li>
|
||||
* </ul>
|
||||
* @param authorizedClient the {@link OAuth2AuthorizedClient} to use.
|
||||
* @return the {@link Consumer} to populate the
|
||||
* @return the {@link Consumer} to populate the attributes
|
||||
*/
|
||||
public static Consumer<Map<String, Object>> oauth2AuthorizedClient(OAuth2AuthorizedClient authorizedClient) {
|
||||
return (attributes) -> attributes.put(OAUTH2_AUTHORIZED_CLIENT_ATTR_NAME, authorizedClient);
|
||||
|
||||
+65
-60
@@ -52,26 +52,77 @@ public final class DefaultBearerTokenResolver implements BearerTokenResolver {
|
||||
|
||||
@Override
|
||||
public String resolve(final HttpServletRequest request) {
|
||||
final String authorizationHeaderToken = resolveFromAuthorizationHeader(request);
|
||||
final String parameterToken = isParameterTokenSupportedForRequest(request)
|
||||
? resolveFromRequestParameters(request) : null;
|
||||
if (authorizationHeaderToken != null) {
|
||||
if (parameterToken != null) {
|
||||
// @formatter:off
|
||||
return resolveToken(
|
||||
resolveFromAuthorizationHeader(request),
|
||||
resolveAccessTokenFromQueryString(request),
|
||||
resolveAccessTokenFromBody(request)
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static String resolveToken(String... accessTokens) {
|
||||
if (accessTokens == null || accessTokens.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String accessToken = null;
|
||||
for (String token : accessTokens) {
|
||||
if (accessToken == null) {
|
||||
accessToken = token;
|
||||
}
|
||||
else if (token != null) {
|
||||
BearerTokenError error = BearerTokenErrors
|
||||
.invalidRequest("Found multiple bearer tokens in the request");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return authorizationHeaderToken;
|
||||
}
|
||||
if (parameterToken != null && isParameterTokenEnabledForRequest(request)) {
|
||||
if (!StringUtils.hasText(parameterToken)) {
|
||||
BearerTokenError error = BearerTokenErrors
|
||||
.invalidRequest("The requested token parameter is an empty string");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return parameterToken;
|
||||
|
||||
if (accessToken != null && accessToken.isBlank()) {
|
||||
BearerTokenError error = BearerTokenErrors
|
||||
.invalidRequest("The requested token parameter is an empty string");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return null;
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
private String resolveFromAuthorizationHeader(HttpServletRequest request) {
|
||||
String authorization = request.getHeader(this.bearerTokenHeaderName);
|
||||
if (!StringUtils.startsWithIgnoreCase(authorization, "bearer")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Matcher matcher = authorizationPattern.matcher(authorization);
|
||||
if (!matcher.matches()) {
|
||||
BearerTokenError error = BearerTokenErrors.invalidToken("Bearer token is malformed");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
return matcher.group("token");
|
||||
}
|
||||
|
||||
private String resolveAccessTokenFromQueryString(HttpServletRequest request) {
|
||||
if (!this.allowUriQueryParameter || !HttpMethod.GET.name().equals(request.getMethod())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return resolveToken(request.getParameterValues(ACCESS_TOKEN_PARAMETER_NAME));
|
||||
}
|
||||
|
||||
private String resolveAccessTokenFromBody(HttpServletRequest request) {
|
||||
if (!this.allowFormEncodedBodyParameter
|
||||
|| !MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType())
|
||||
|| HttpMethod.GET.name().equals(request.getMethod())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String queryString = request.getQueryString();
|
||||
if (queryString != null && queryString.contains(ACCESS_TOKEN_PARAMETER_NAME)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return resolveToken(request.getParameterValues(ACCESS_TOKEN_PARAMETER_NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,50 +160,4 @@ public final class DefaultBearerTokenResolver implements BearerTokenResolver {
|
||||
this.bearerTokenHeaderName = bearerTokenHeaderName;
|
||||
}
|
||||
|
||||
private String resolveFromAuthorizationHeader(HttpServletRequest request) {
|
||||
String authorization = request.getHeader(this.bearerTokenHeaderName);
|
||||
if (!StringUtils.startsWithIgnoreCase(authorization, "bearer")) {
|
||||
return null;
|
||||
}
|
||||
Matcher matcher = authorizationPattern.matcher(authorization);
|
||||
if (!matcher.matches()) {
|
||||
BearerTokenError error = BearerTokenErrors.invalidToken("Bearer token is malformed");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return matcher.group("token");
|
||||
}
|
||||
|
||||
private static String resolveFromRequestParameters(HttpServletRequest request) {
|
||||
String[] values = request.getParameterValues(ACCESS_TOKEN_PARAMETER_NAME);
|
||||
if (values == null || values.length == 0) {
|
||||
return null;
|
||||
}
|
||||
if (values.length == 1) {
|
||||
return values[0];
|
||||
}
|
||||
BearerTokenError error = BearerTokenErrors.invalidRequest("Found multiple bearer tokens in the request");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
private boolean isParameterTokenSupportedForRequest(final HttpServletRequest request) {
|
||||
return isFormEncodedRequest(request) || isGetRequest(request);
|
||||
}
|
||||
|
||||
private static boolean isGetRequest(HttpServletRequest request) {
|
||||
return HttpMethod.GET.name().equals(request.getMethod());
|
||||
}
|
||||
|
||||
private static boolean isFormEncodedRequest(HttpServletRequest request) {
|
||||
return MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType());
|
||||
}
|
||||
|
||||
private static boolean hasAccessTokenInQueryString(HttpServletRequest request) {
|
||||
return (request.getQueryString() != null) && request.getQueryString().contains(ACCESS_TOKEN_PARAMETER_NAME);
|
||||
}
|
||||
|
||||
private boolean isParameterTokenEnabledForRequest(HttpServletRequest request) {
|
||||
return ((this.allowFormEncodedBodyParameter && isFormEncodedRequest(request) && !isGetRequest(request)
|
||||
&& !hasAccessTokenInQueryString(request)) || (this.allowUriQueryParameter && isGetRequest(request)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -77,18 +77,18 @@ public class ServerBearerTokenAuthenticationConverter implements ServerAuthentic
|
||||
}
|
||||
return authorizationHeaderToken;
|
||||
}
|
||||
if (parameterToken != null && isParameterTokenSupportedForRequest(request)) {
|
||||
if (!StringUtils.hasText(parameterToken)) {
|
||||
BearerTokenError error = BearerTokenErrors
|
||||
.invalidRequest("The requested token parameter is an empty string");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return parameterToken;
|
||||
if (parameterToken != null && !StringUtils.hasText(parameterToken)) {
|
||||
BearerTokenError error = BearerTokenErrors
|
||||
.invalidRequest("The requested token parameter is an empty string");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return null;
|
||||
return parameterToken;
|
||||
}
|
||||
|
||||
private static String resolveAccessTokenFromRequest(ServerHttpRequest request) {
|
||||
private String resolveAccessTokenFromRequest(ServerHttpRequest request) {
|
||||
if (!isParameterTokenSupportedForRequest(request)) {
|
||||
return null;
|
||||
}
|
||||
List<String> parameterTokens = request.getQueryParams().get("access_token");
|
||||
if (CollectionUtils.isEmpty(parameterTokens)) {
|
||||
return null;
|
||||
|
||||
+37
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -110,6 +110,7 @@ public class DefaultBearerTokenResolverTests {
|
||||
|
||||
@Test
|
||||
public void resolveWhenValidHeaderIsPresentTogetherWithFormParameterThenAuthenticationExceptionIsThrown() {
|
||||
this.resolver.setAllowFormEncodedBodyParameter(true);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Bearer " + TEST_TOKEN);
|
||||
request.setMethod("POST");
|
||||
@@ -121,6 +122,7 @@ public class DefaultBearerTokenResolverTests {
|
||||
|
||||
@Test
|
||||
public void resolveWhenValidHeaderIsPresentTogetherWithQueryParameterThenAuthenticationExceptionIsThrown() {
|
||||
this.resolver.setAllowUriQueryParameter(true);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Authorization", "Bearer " + TEST_TOKEN);
|
||||
request.setMethod("GET");
|
||||
@@ -133,6 +135,7 @@ public class DefaultBearerTokenResolverTests {
|
||||
// gh-10326
|
||||
@Test
|
||||
public void resolveWhenRequestContainsTwoAccessTokenQueryParametersThenAuthenticationExceptionIsThrown() {
|
||||
this.resolver.setAllowUriQueryParameter(true);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
request.addParameter("access_token", "token1", "token2");
|
||||
@@ -143,6 +146,7 @@ public class DefaultBearerTokenResolverTests {
|
||||
// gh-10326
|
||||
@Test
|
||||
public void resolveWhenRequestContainsTwoAccessTokenFormParametersThenAuthenticationExceptionIsThrown() {
|
||||
this.resolver.setAllowFormEncodedBodyParameter(true);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContentType("application/x-www-form-urlencoded");
|
||||
@@ -233,6 +237,19 @@ public class DefaultBearerTokenResolverTests {
|
||||
assertThat(this.resolver.resolve(request)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveWhenPostAndQueryParameterIsSupportedAndFormParameterIsPresentThenTokenIsNotResolved() {
|
||||
this.resolver.setAllowUriQueryParameter(true);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContentType("application/x-www-form-urlencoded");
|
||||
request.setQueryString("access_token=" + TEST_TOKEN);
|
||||
request.addParameter("access_token", TEST_TOKEN);
|
||||
|
||||
assertThat(this.resolver.resolve(request)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveWhenFormParameterIsPresentAndNotSupportedThenTokenIsNotResolved() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
@@ -261,6 +278,25 @@ public class DefaultBearerTokenResolverTests {
|
||||
assertThat(this.resolver.resolve(request)).isNull();
|
||||
}
|
||||
|
||||
// gh-16038
|
||||
@Test
|
||||
public void resolveWhenRequestContainsTwoAccessTokenFormParametersAndSupportIsDisabledThenTokenIsNotResolved() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContentType("application/x-www-form-urlencoded");
|
||||
request.addParameter("access_token", "token1", "token2");
|
||||
assertThat(this.resolver.resolve(request)).isNull();
|
||||
}
|
||||
|
||||
// gh-16038
|
||||
@Test
|
||||
public void resolveWhenRequestContainsTwoAccessTokenQueryParametersAndSupportIsDisabledThenTokenIsNotResolved() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
request.addParameter("access_token", "token1", "token2");
|
||||
assertThat(this.resolver.resolve(request)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveWhenQueryParameterIsPresentAndEmptyStringThenTokenIsNotResolved() {
|
||||
this.resolver.setAllowUriQueryParameter(true);
|
||||
|
||||
+11
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -157,6 +157,7 @@ public class ServerBearerTokenAuthenticationConverterTests {
|
||||
@Test
|
||||
public void resolveWhenValidHeaderIsPresentTogetherWithQueryParameterThenAuthenticationExceptionIsThrown() {
|
||||
// @formatter:off
|
||||
this.converter.setAllowUriQueryParameter(true);
|
||||
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest.get("/")
|
||||
.queryParam("access_token", TEST_TOKEN)
|
||||
.header(HttpHeaders.AUTHORIZATION, "Bearer " + TEST_TOKEN);
|
||||
@@ -205,6 +206,7 @@ public class ServerBearerTokenAuthenticationConverterTests {
|
||||
|
||||
@Test
|
||||
void resolveWhenQueryParameterHasMultipleAccessTokensThenOAuth2AuthenticationException() {
|
||||
this.converter.setAllowUriQueryParameter(true);
|
||||
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest.get("/")
|
||||
.queryParam("access_token", TEST_TOKEN, TEST_TOKEN);
|
||||
assertThatExceptionOfType(OAuth2AuthenticationException.class).isThrownBy(() -> convertToToken(request))
|
||||
@@ -217,6 +219,14 @@ public class ServerBearerTokenAuthenticationConverterTests {
|
||||
|
||||
}
|
||||
|
||||
// gh-16038
|
||||
@Test
|
||||
void resolveWhenRequestContainsTwoAccessTokenQueryParametersAndSupportIsDisabledThenTokenIsNotResolved() {
|
||||
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest.get("/")
|
||||
.queryParam("access_token", TEST_TOKEN, TEST_TOKEN);
|
||||
assertThat(convertToToken(request)).isNull();
|
||||
}
|
||||
|
||||
private BearerTokenAuthenticationToken convertToToken(MockServerHttpRequest.BaseBuilder<?> request) {
|
||||
return convertToToken(request.build());
|
||||
}
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml4Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+59
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -386,6 +386,24 @@ public class OpenSaml4AuthenticationProviderTests {
|
||||
this.provider.authenticate(token);
|
||||
}
|
||||
|
||||
// gh-16367
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAssertionWithSignatureThenEncryptedAssertionStillAvailable() {
|
||||
Response response = response();
|
||||
Assertion assertion = TestOpenSamlObjects.signed(assertion(),
|
||||
TestSaml2X509Credentials.assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID);
|
||||
EncryptedAssertion encryptedAssertion = TestOpenSamlObjects.encrypted(assertion,
|
||||
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
|
||||
response.getEncryptedAssertions().add(encryptedAssertion);
|
||||
Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
|
||||
OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
|
||||
provider.setResponseValidator((t) -> {
|
||||
assertThat(t.getResponse().getEncryptedAssertions()).isNotEmpty();
|
||||
return Saml2ResponseValidatorResult.success();
|
||||
});
|
||||
provider.authenticate(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAssertionWithResponseSignatureThenItSucceeds() {
|
||||
Response response = response();
|
||||
@@ -410,6 +428,26 @@ public class OpenSaml4AuthenticationProviderTests {
|
||||
this.provider.authenticate(token);
|
||||
}
|
||||
|
||||
// gh-16367
|
||||
@Test
|
||||
public void authenticateWhenEncryptedNameIdWithSignatureThenEncryptedNameIdStillAvailable() {
|
||||
Response response = response();
|
||||
Assertion assertion = assertion();
|
||||
NameID nameId = assertion.getSubject().getNameID();
|
||||
EncryptedID encryptedID = TestOpenSamlObjects.encrypted(nameId,
|
||||
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
|
||||
assertion.getSubject().setNameID(null);
|
||||
assertion.getSubject().setEncryptedID(encryptedID);
|
||||
response.getAssertions().add(signed(assertion));
|
||||
Saml2AuthenticationToken token = token(response, decrypting(verifying(registration())));
|
||||
OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
|
||||
provider.setAssertionValidator((t) -> {
|
||||
assertThat(t.getAssertion().getSubject().getEncryptedID()).isNotNull();
|
||||
return Saml2ResponseValidatorResult.success();
|
||||
});
|
||||
provider.authenticate(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAttributeThenDecrypts() {
|
||||
Response response = response();
|
||||
@@ -426,6 +464,26 @@ public class OpenSaml4AuthenticationProviderTests {
|
||||
assertThat(principal.getAttribute("name")).containsExactly("value");
|
||||
}
|
||||
|
||||
// gh-16367
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAttributeThenEncryptedAttributesStillAvailable() {
|
||||
Response response = response();
|
||||
Assertion assertion = assertion();
|
||||
EncryptedAttribute attribute = TestOpenSamlObjects.encrypted("name", "value",
|
||||
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
|
||||
AttributeStatement statement = build(AttributeStatement.DEFAULT_ELEMENT_NAME);
|
||||
statement.getEncryptedAttributes().add(attribute);
|
||||
assertion.getAttributeStatements().add(statement);
|
||||
response.getAssertions().add(assertion);
|
||||
Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
|
||||
OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
|
||||
provider.setAssertionValidator((t) -> {
|
||||
assertThat(t.getAssertion().getAttributeStatements().get(0).getEncryptedAttributes()).isNotEmpty();
|
||||
return Saml2ResponseValidatorResult.success();
|
||||
});
|
||||
provider.authenticate(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenDecryptionKeysAreMissingThenThrowAuthenticationException() {
|
||||
Response response = response();
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+1
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -482,7 +482,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptResponse(Response response) {
|
||||
Collection<Assertion> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAssertion> encrypteds = new ArrayList<>();
|
||||
|
||||
int count = 0;
|
||||
int size = response.getEncryptedAssertions().size();
|
||||
@@ -492,7 +491,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
try {
|
||||
Assertion decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
count++;
|
||||
@@ -502,7 +500,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
}
|
||||
}
|
||||
|
||||
response.getEncryptedAssertions().removeAll(encrypteds);
|
||||
response.getAssertions().addAll(decrypteds);
|
||||
|
||||
// Re-marshall the response so that any ID attributes within the decrypted
|
||||
@@ -534,7 +531,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
d.setNameID(decrypted);
|
||||
d.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
@@ -548,12 +544,10 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
|
||||
private void decryptAttributes(AttributeStatement statement) {
|
||||
Collection<Attribute> decrypteds = new ArrayList<>();
|
||||
Collection<EncryptedAttribute> encrypteds = new ArrayList<>();
|
||||
for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
|
||||
try {
|
||||
Attribute decrypted = this.decrypter.decrypt(encrypted);
|
||||
if (decrypted != null) {
|
||||
encrypteds.add(encrypted);
|
||||
decrypteds.add(decrypted);
|
||||
}
|
||||
}
|
||||
@@ -561,7 +555,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
throw new Saml2Exception(ex);
|
||||
}
|
||||
}
|
||||
statement.getEncryptedAttributes().removeAll(encrypteds);
|
||||
statement.getAttributes().addAll(decrypteds);
|
||||
}
|
||||
|
||||
@@ -572,7 +565,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
subject.setNameID(decrypted);
|
||||
subject.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -586,7 +578,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
sc.setNameID(decrypted);
|
||||
sc.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (final DecryptionException ex) {
|
||||
@@ -603,7 +594,6 @@ final class OpenSaml5Template implements OpenSamlOperations {
|
||||
NameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());
|
||||
if (decrypted != null) {
|
||||
request.setNameID(decrypted);
|
||||
request.setEncryptedID(null);
|
||||
}
|
||||
}
|
||||
catch (DecryptionException ex) {
|
||||
|
||||
+59
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -386,6 +386,24 @@ public class OpenSaml5AuthenticationProviderTests {
|
||||
this.provider.authenticate(token);
|
||||
}
|
||||
|
||||
// gh-16367
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAssertionWithSignatureThenEncryptedAssertionStillAvailable() {
|
||||
Response response = response();
|
||||
Assertion assertion = TestOpenSamlObjects.signed(assertion(),
|
||||
TestSaml2X509Credentials.assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID);
|
||||
EncryptedAssertion encryptedAssertion = TestOpenSamlObjects.encrypted(assertion,
|
||||
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
|
||||
response.getEncryptedAssertions().add(encryptedAssertion);
|
||||
Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
|
||||
OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
|
||||
provider.setResponseValidator((t) -> {
|
||||
assertThat(t.getResponse().getEncryptedAssertions()).isNotEmpty();
|
||||
return Saml2ResponseValidatorResult.success();
|
||||
});
|
||||
provider.authenticate(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAssertionWithResponseSignatureThenItSucceeds() {
|
||||
Response response = response();
|
||||
@@ -410,6 +428,26 @@ public class OpenSaml5AuthenticationProviderTests {
|
||||
this.provider.authenticate(token);
|
||||
}
|
||||
|
||||
// gh-16367
|
||||
@Test
|
||||
public void authenticateWhenEncryptedNameIdWithSignatureThenEncryptedNameIdStillAvailable() {
|
||||
Response response = response();
|
||||
Assertion assertion = assertion();
|
||||
NameID nameId = assertion.getSubject().getNameID();
|
||||
EncryptedID encryptedID = TestOpenSamlObjects.encrypted(nameId,
|
||||
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
|
||||
assertion.getSubject().setNameID(null);
|
||||
assertion.getSubject().setEncryptedID(encryptedID);
|
||||
response.getAssertions().add(signed(assertion));
|
||||
Saml2AuthenticationToken token = token(response, decrypting(verifying(registration())));
|
||||
OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
|
||||
provider.setAssertionValidator((t) -> {
|
||||
assertThat(t.getAssertion().getSubject().getEncryptedID()).isNotNull();
|
||||
return Saml2ResponseValidatorResult.success();
|
||||
});
|
||||
provider.authenticate(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAttributeThenDecrypts() {
|
||||
Response response = response();
|
||||
@@ -426,6 +464,26 @@ public class OpenSaml5AuthenticationProviderTests {
|
||||
assertThat(principal.getAttribute("name")).containsExactly("value");
|
||||
}
|
||||
|
||||
// gh-16367
|
||||
@Test
|
||||
public void authenticateWhenEncryptedAttributeThenEncryptedAttributesStillAvailable() {
|
||||
Response response = response();
|
||||
Assertion assertion = assertion();
|
||||
EncryptedAttribute attribute = TestOpenSamlObjects.encrypted("name", "value",
|
||||
TestSaml2X509Credentials.assertingPartyEncryptingCredential());
|
||||
AttributeStatement statement = build(AttributeStatement.DEFAULT_ELEMENT_NAME);
|
||||
statement.getEncryptedAttributes().add(attribute);
|
||||
assertion.getAttributeStatements().add(statement);
|
||||
response.getAssertions().add(assertion);
|
||||
Saml2AuthenticationToken token = token(signed(response), decrypting(verifying(registration())));
|
||||
OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
|
||||
provider.setAssertionValidator((t) -> {
|
||||
assertThat(t.getAssertion().getAttributeStatements().get(0).getEncryptedAttributes()).isNotEmpty();
|
||||
return Saml2ResponseValidatorResult.success();
|
||||
});
|
||||
provider.authenticate(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenDecryptionKeysAreMissingThenThrowAuthenticationException() {
|
||||
Response response = response();
|
||||
|
||||
+11
-3
@@ -29,6 +29,9 @@ public interface WebInvocationPrivilegeEvaluator {
|
||||
/**
|
||||
* Determines whether the user represented by the supplied <tt>Authentication</tt>
|
||||
* object is allowed to invoke the supplied URI.
|
||||
* <p>
|
||||
* Note this will only match authorization rules that don't require a certain
|
||||
* {@code HttpMethod}.
|
||||
* @param uri the URI excluding the context path (a default context path setting will
|
||||
* be used)
|
||||
*/
|
||||
@@ -36,13 +39,18 @@ public interface WebInvocationPrivilegeEvaluator {
|
||||
|
||||
/**
|
||||
* Determines whether the user represented by the supplied <tt>Authentication</tt>
|
||||
* object is allowed to invoke the supplied URI, with the given .
|
||||
* object is allowed to invoke the supplied URI, with the given parameters.
|
||||
* <p>
|
||||
* Note the default implementation of <tt>FilterInvocationSecurityMetadataSource</tt>
|
||||
* Note:
|
||||
* <ul>
|
||||
* <li>The default implementation of <tt>FilterInvocationSecurityMetadataSource</tt>
|
||||
* disregards the <code>contextPath</code> when evaluating which secure object
|
||||
* metadata applies to a given request URI, so generally the <code>contextPath</code>
|
||||
* is unimportant unless you are using a custom
|
||||
* <code>FilterInvocationSecurityMetadataSource</code>.
|
||||
* <code>FilterInvocationSecurityMetadataSource</code>.</li>
|
||||
* <li>this will only match authorization rules that don't require a certain
|
||||
* {@code HttpMethod}.</li>
|
||||
* </ul>
|
||||
* @param uri the URI excluding the context path
|
||||
* @param contextPath the context path (may be null).
|
||||
* @param method the HTTP method (or null, for any method)
|
||||
|
||||
+1
-1
@@ -452,7 +452,7 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
||||
<div class="login-form">
|
||||
<h2>Login with Passkeys</h2>
|
||||
<button id="passkey-signin" type="submit" class="primary">Sign in with a passkey</button>
|
||||
</form>
|
||||
</div>
|
||||
""";
|
||||
|
||||
private static final String LOGIN_PAGE_TEMPLATE = """
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -84,7 +84,7 @@ public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRep
|
||||
*/
|
||||
public static CookieServerCsrfTokenRepository withHttpOnlyFalse() {
|
||||
CookieServerCsrfTokenRepository result = new CookieServerCsrfTokenRepository();
|
||||
result.setCookieCustomizer((cookie) -> cookie.httpOnly(false));
|
||||
result.cookieHttpOnly = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+13
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -333,9 +333,7 @@ public class Webauthn4JRelyingPartyOperations implements WebAuthnRelyingPartyOpe
|
||||
public PublicKeyCredentialRequestOptions createCredentialRequestOptions(
|
||||
PublicKeyCredentialRequestOptionsRequest request) {
|
||||
Authentication authentication = request.getAuthentication();
|
||||
// FIXME: do not load credentialRecords if anonymous
|
||||
PublicKeyCredentialUserEntity userEntity = findUserEntityOrCreateAndSave(authentication.getName());
|
||||
List<CredentialRecord> credentialRecords = this.userCredentials.findByUserId(userEntity.getId());
|
||||
List<CredentialRecord> credentialRecords = findCredentialRecords(authentication);
|
||||
return PublicKeyCredentialRequestOptions.builder()
|
||||
.allowCredentials(credentialDescriptors(credentialRecords))
|
||||
.challenge(Bytes.random())
|
||||
@@ -346,6 +344,17 @@ public class Webauthn4JRelyingPartyOperations implements WebAuthnRelyingPartyOpe
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<CredentialRecord> findCredentialRecords(Authentication authentication) {
|
||||
if (!this.trustResolver.isAuthenticated(authentication)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
PublicKeyCredentialUserEntity userEntity = this.userEntities.findByUsername(authentication.getName());
|
||||
if (userEntity == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return this.userCredentials.findByUserId(userEntity.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PublicKeyCredentialUserEntity authenticate(RelyingPartyAuthenticationRequest request) {
|
||||
PublicKeyCredentialRequestOptions requestOptions = request.getRequestOptions();
|
||||
|
||||
+16
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -290,6 +290,21 @@ class CookieServerCsrfTokenRepositoryTests {
|
||||
loadAndAssertExpectedValues();
|
||||
}
|
||||
|
||||
// gh-16820
|
||||
@Test
|
||||
void withHttpOnlyFalseWhenCookieCustomizerThenStillDefaultsToFalse() {
|
||||
CookieServerCsrfTokenRepository repository = CookieServerCsrfTokenRepository.withHttpOnlyFalse();
|
||||
repository.setCookieCustomizer((customizer) -> customizer.maxAge(1000));
|
||||
MockServerHttpRequest.BaseBuilder<?> request = MockServerHttpRequest.get("/dummy");
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
CsrfToken csrfToken = repository.generateToken(exchange).block();
|
||||
repository.saveToken(exchange, csrfToken).block();
|
||||
ResponseCookie cookie = exchange.getResponse().getCookies().getFirst("XSRF-TOKEN");
|
||||
assertThat(cookie).isNotNull();
|
||||
assertThat(cookie.getMaxAge().getSeconds()).isEqualTo(1000);
|
||||
assertThat(cookie.isHttpOnly()).isEqualTo(Boolean.FALSE);
|
||||
}
|
||||
|
||||
private void setExpectedHeaderName(String expectedHeaderName) {
|
||||
this.csrfTokenRepository.setHeaderName(expectedHeaderName);
|
||||
this.expectedHeaderName = expectedHeaderName;
|
||||
|
||||
+48
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -42,6 +42,8 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.PasswordEncodedUser;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticatorAttestationResponse;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticatorAttestationResponse.AuthenticatorAttestationResponseBuilder;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticatorSelectionCriteria;
|
||||
@@ -66,6 +68,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatRuntimeException;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class Webauthn4jRelyingPartyOperationsTests {
|
||||
@@ -536,6 +539,50 @@ class Webauthn4jRelyingPartyOperationsTests {
|
||||
.isEqualTo(creationOptions.getAuthenticatorSelection().getUserVerification());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createCredentialRequestOptionsWhenAnonymousAuthentication() {
|
||||
AnonymousAuthenticationToken authentication = new AnonymousAuthenticationToken("key", "anonymousUser",
|
||||
Set.of(() -> "ROLE_ANONYMOUS"));
|
||||
PublicKeyCredentialRequestOptionsRequest createRequest = new ImmutablePublicKeyCredentialRequestOptionsRequest(
|
||||
authentication);
|
||||
PublicKeyCredentialRequestOptions credentialRequestOptions = this.rpOperations
|
||||
.createCredentialRequestOptions(createRequest);
|
||||
|
||||
assertThat(credentialRequestOptions.getAllowCredentials()).isEmpty();
|
||||
// verify anonymous user not saved
|
||||
verifyNoInteractions(this.userEntities);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createCredentialRequestOptionsWhenNullAuthentication() {
|
||||
PublicKeyCredentialRequestOptionsRequest createRequest = new ImmutablePublicKeyCredentialRequestOptionsRequest(
|
||||
null);
|
||||
PublicKeyCredentialRequestOptions credentialRequestOptions = this.rpOperations
|
||||
.createCredentialRequestOptions(createRequest);
|
||||
|
||||
assertThat(credentialRequestOptions.getAllowCredentials()).isEmpty();
|
||||
// verify anonymous user not saved
|
||||
verifyNoInteractions(this.userEntities);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createCredentialRequestOptionsWhenAuthenticated() {
|
||||
UserDetails user = PasswordEncodedUser.user();
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, null,
|
||||
user.getAuthorities());
|
||||
PublicKeyCredentialUserEntity userEntity = TestPublicKeyCredentialUserEntity.userEntity().build();
|
||||
CredentialRecord credentialRecord = TestCredentialRecord.userCredential().build();
|
||||
given(this.userEntities.findByUsername(user.getUsername())).willReturn(userEntity);
|
||||
given(this.userCredentials.findByUserId(userEntity.getId())).willReturn(Arrays.asList(credentialRecord));
|
||||
PublicKeyCredentialRequestOptionsRequest createRequest = new ImmutablePublicKeyCredentialRequestOptionsRequest(
|
||||
auth);
|
||||
PublicKeyCredentialRequestOptions credentialRequestOptions = this.rpOperations
|
||||
.createCredentialRequestOptions(createRequest);
|
||||
|
||||
assertThat(credentialRequestOptions.getAllowCredentials()).extracting(PublicKeyCredentialDescriptor::getId)
|
||||
.containsExactly(credentialRecord.getCredentialId());
|
||||
}
|
||||
|
||||
private static AuthenticatorAttestationResponse setFlag(byte... flags) throws Exception {
|
||||
AuthenticatorAttestationResponseBuilder authAttResponseBldr = TestAuthenticatorAttestationResponse
|
||||
.createAuthenticatorAttestationResponse();
|
||||
|
||||
Reference in New Issue
Block a user