Skip to content

Commit e78616e

Browse files
Remove internal Optional usage in favor of null checks
Fixes spring-projectsgh-7155
1 parent 0209fba commit e78616e

File tree

11 files changed

+109
-83
lines changed

11 files changed

+109
-83
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfiguration.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,17 @@ static class OAuth2ClientWebMvcSecurityConfiguration implements WebMvcConfigurer
7171
@Override
7272
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
7373
if (this.clientRegistrationRepository != null && this.authorizedClientRepository != null) {
74-
OAuth2AuthorizedClientProvider authorizedClientProvider =
74+
OAuth2AuthorizedClientProviderBuilder authorizedClientProviderBuilder =
7575
OAuth2AuthorizedClientProviderBuilder.builder()
7676
.authorizationCode()
77-
.refreshToken()
78-
.clientCredentials(configurer ->
79-
Optional.ofNullable(this.accessTokenResponseClient).ifPresent(configurer::accessTokenResponseClient))
80-
.build();
77+
.refreshToken();
78+
79+
if (this.accessTokenResponseClient != null) {
80+
authorizedClientProviderBuilder.clientCredentials(configurer ->
81+
configurer.accessTokenResponseClient(this.accessTokenResponseClient));
82+
}
83+
OAuth2AuthorizedClientProvider authorizedClientProvider = authorizedClientProviderBuilder.build();
84+
8185
DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(
8286
this.clientRegistrationRepository, this.authorizedClientRepository);
8387
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import java.util.HashMap;
2828
import java.util.List;
2929
import java.util.Map;
30-
import java.util.Optional;
3130
import java.util.UUID;
3231
import java.util.function.Function;
3332
import java.util.function.Supplier;
@@ -2665,10 +2664,10 @@ public ServerHttpSecurity disable() {
26652664
}
26662665

26672666
protected void configure(ServerHttpSecurity http) {
2668-
Optional.ofNullable(this.csrfTokenRepository).ifPresent(serverCsrfTokenRepository -> {
2669-
this.filter.setCsrfTokenRepository(serverCsrfTokenRepository);
2670-
http.logout().addLogoutHandler(new CsrfServerLogoutHandler(serverCsrfTokenRepository));
2671-
});
2667+
if (this.csrfTokenRepository != null) {
2668+
this.filter.setCsrfTokenRepository(this.csrfTokenRepository);
2669+
http.logout().addLogoutHandler(new CsrfServerLogoutHandler(this.csrfTokenRepository));
2670+
}
26722671
http.addFilterAt(this.filter, SecurityWebFiltersOrder.CSRF);
26732672
}
26742673

@@ -3607,19 +3606,21 @@ public ServerHttpSecurity disable() {
36073606
return and();
36083607
}
36093608

3610-
private Optional<ServerLogoutHandler> createLogoutHandler() {
3609+
private ServerLogoutHandler createLogoutHandler() {
36113610
if (this.logoutHandlers.isEmpty()) {
3612-
return Optional.empty();
3613-
}
3614-
else if (this.logoutHandlers.size() == 1) {
3615-
return Optional.of(this.logoutHandlers.get(0));
3611+
return null;
3612+
} else if (this.logoutHandlers.size() == 1) {
3613+
return this.logoutHandlers.get(0);
3614+
} else {
3615+
return new DelegatingServerLogoutHandler(this.logoutHandlers);
36163616
}
3617-
3618-
return Optional.of(new DelegatingServerLogoutHandler(this.logoutHandlers));
36193617
}
36203618

36213619
protected void configure(ServerHttpSecurity http) {
3622-
createLogoutHandler().ifPresent(this.logoutWebFilter::setLogoutHandler);
3620+
ServerLogoutHandler logoutHandler = createLogoutHandler();
3621+
if (logoutHandler != null) {
3622+
this.logoutWebFilter.setLogoutHandler(logoutHandler);
3623+
}
36233624
http.addFilterAt(this.logoutWebFilter, SecurityWebFiltersOrder.LOGOUT);
36243625
}
36253626

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/web/logout/OidcClientInitiatedLogoutSuccessHandler.java

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import java.net.URI;
2020
import java.nio.charset.StandardCharsets;
21-
import java.util.Optional;
2221
import javax.servlet.http.HttpServletRequest;
2322
import javax.servlet.http.HttpServletResponse;
2423

@@ -52,25 +51,32 @@ public OidcClientInitiatedLogoutSuccessHandler(ClientRegistrationRepository clie
5251
@Override
5352
protected String determineTargetUrl(HttpServletRequest request,
5453
HttpServletResponse response, Authentication authentication) {
54+
String targetUrl = null;
55+
URI endSessionEndpoint;
56+
if (authentication instanceof OAuth2AuthenticationToken && authentication.getPrincipal() instanceof OidcUser) {
57+
endSessionEndpoint = this.endSessionEndpoint((OAuth2AuthenticationToken) authentication);
58+
if (endSessionEndpoint != null) {
59+
targetUrl = endpointUri(endSessionEndpoint, authentication);
60+
}
61+
}
62+
if (targetUrl == null) {
63+
targetUrl = super.determineTargetUrl(request, response);
64+
}
5565

56-
return Optional.of(authentication)
57-
.filter(OAuth2AuthenticationToken.class::isInstance)
58-
.filter(token -> authentication.getPrincipal() instanceof OidcUser)
59-
.map(OAuth2AuthenticationToken.class::cast)
60-
.flatMap(this::endSessionEndpoint)
61-
.map(endSessionEndpoint -> endpointUri(endSessionEndpoint, authentication))
62-
.orElseGet(() -> super.determineTargetUrl(request, response));
66+
return targetUrl;
6367
}
6468

65-
private Optional<URI> endSessionEndpoint(OAuth2AuthenticationToken token) {
69+
private URI endSessionEndpoint(OAuth2AuthenticationToken token) {
6670
String registrationId = token.getAuthorizedClientRegistrationId();
67-
return Optional.of(
68-
this.clientRegistrationRepository.findByRegistrationId(registrationId))
69-
.map(ClientRegistration::getProviderDetails)
70-
.map(ClientRegistration.ProviderDetails::getConfigurationMetadata)
71-
.map(configurationMetadata -> configurationMetadata.get("end_session_endpoint"))
72-
.map(Object::toString)
73-
.map(URI::create);
71+
ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(registrationId);
72+
Object endSessionEndpoint = clientRegistration.getProviderDetails().getConfigurationMetadata().get("end_session_endpoint");
73+
74+
URI result = null;
75+
if (endSessionEndpoint != null) {
76+
result = URI.create(endSessionEndpoint.toString());
77+
}
78+
79+
return result;
7480
}
7581

7682
private String endpointUri(URI endSessionEndpoint, Authentication authentication) {

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrations.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.util.LinkedHashMap;
2222
import java.util.List;
2323
import java.util.Map;
24-
import java.util.Optional;
2524

2625
import com.nimbusds.oauth2.sdk.GrantType;
2726
import com.nimbusds.oauth2.sdk.ParseException;
@@ -141,8 +140,11 @@ public static ClientRegistration.Builder fromIssuerLocation(String issuer) {
141140
Map<String, Object> configuration = getConfiguration(issuer, oidc(uri), oidcRfc8414(uri), oauth(uri));
142141
AuthorizationServerMetadata metadata = parse(configuration, AuthorizationServerMetadata::parse);
143142
ClientRegistration.Builder builder = withProviderConfiguration(metadata, issuer);
144-
return Optional.ofNullable((String) configuration.get("userinfo_endpoint"))
145-
.map(builder::userInfoUri).orElse(builder);
143+
String userinfoEndpoint = (String) configuration.get("userinfo_endpoint");
144+
if (userinfoEndpoint != null) {
145+
builder.userInfoUri(userinfoEndpoint);
146+
}
147+
return builder;
146148
}
147149

148150
private static URI oidc(URI issuer) {

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunction.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import java.time.Duration;
4646
import java.time.Instant;
4747
import java.util.Map;
48-
import java.util.Optional;
4948
import java.util.function.Consumer;
5049

5150
import static org.springframework.security.oauth2.core.web.reactive.function.OAuth2BodyExtractors.oauth2AccessTokenResponse;
@@ -291,8 +290,10 @@ private Mono<OAuth2AuthorizedClient> authorizeWithRefreshToken(ExchangeFunction
291290
return next.exchange(refreshRequest)
292291
.flatMap(refreshResponse -> refreshResponse.body(oauth2AccessTokenResponse()))
293292
.map(accessTokenResponse -> {
294-
OAuth2RefreshToken refreshToken = Optional.ofNullable(accessTokenResponse.getRefreshToken())
295-
.orElse(authorizedClient.getRefreshToken());
293+
OAuth2RefreshToken refreshToken = accessTokenResponse.getRefreshToken();
294+
if (refreshToken == null) {
295+
refreshToken = authorizedClient.getRefreshToken();
296+
}
296297
return new OAuth2AuthorizedClient(authorizedClient.getClientRegistration(), authorizedClient.getPrincipalName(), accessTokenResponse.getAccessToken(), refreshToken);
297298
})
298299
.flatMap(result -> this.authorizedClientRepository.saveAuthorizedClient(result, authentication, exchange)

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OAuth2IntrospectionAuthenticationProvider.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
package org.springframework.security.oauth2.server.resource.authentication;
1717

1818
import java.time.Instant;
19+
import java.util.ArrayList;
1920
import java.util.Collection;
2021
import java.util.Collections;
22+
import java.util.List;
2123
import java.util.Map;
22-
import java.util.Optional;
23-
import java.util.stream.Collectors;
2424

2525
import org.springframework.http.HttpStatus;
2626
import org.springframework.security.authentication.AbstractAuthenticationToken;
@@ -128,11 +128,12 @@ private AbstractAuthenticationToken convert(String token, Map<String, Object> cl
128128
}
129129

130130
private Collection<GrantedAuthority> extractAuthorities(Map<String, Object> claims) {
131-
Collection<String> scopes = (Collection<String>) claims.get(SCOPE);
132-
return Optional.ofNullable(scopes).orElse(Collections.emptyList())
133-
.stream()
134-
.map(authority -> new SimpleGrantedAuthority("SCOPE_" + authority))
135-
.collect(Collectors.toList());
131+
Collection<String> scopes = (Collection<String>) claims.getOrDefault(SCOPE, Collections.emptyList());
132+
List<GrantedAuthority> authorities = new ArrayList<>();
133+
for (String scope : scopes) {
134+
authorities.add(new SimpleGrantedAuthority("SCOPE_" + scope));
135+
}
136+
return authorities;
136137
}
137138

138139
private static BearerTokenError invalidToken(String message) {

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OAuth2IntrospectionReactiveAuthenticationManager.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
package org.springframework.security.oauth2.server.resource.authentication;
1818

1919
import java.time.Instant;
20+
import java.util.ArrayList;
2021
import java.util.Collection;
2122
import java.util.Collections;
23+
import java.util.List;
2224
import java.util.Map;
23-
import java.util.Optional;
24-
import java.util.stream.Collectors;
2525

2626
import org.springframework.security.oauth2.core.OAuth2TokenAttributes;
2727
import reactor.core.publisher.Mono;
@@ -108,11 +108,12 @@ private Mono<OAuth2IntrospectionAuthenticationToken> authenticate(String token)
108108
}
109109

110110
private Collection<GrantedAuthority> extractAuthorities(Map<String, Object> claims) {
111-
Collection<String> scopes = (Collection<String>) claims.get(SCOPE);
112-
return Optional.ofNullable(scopes).orElse(Collections.emptyList())
113-
.stream()
114-
.map(authority -> new SimpleGrantedAuthority("SCOPE_" + authority))
115-
.collect(Collectors.toList());
111+
Collection<String> scopes = (Collection<String>) claims.getOrDefault(SCOPE, Collections.emptyList());
112+
List<GrantedAuthority> authorities = new ArrayList<>();
113+
for (String scope : scopes) {
114+
authorities.add(new SimpleGrantedAuthority("SCOPE_" + scope));
115+
}
116+
return authorities;
116117
}
117118

118119
private static BearerTokenError invalidToken(String message) {

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospector.java

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import java.util.Collections;
2323
import java.util.List;
2424
import java.util.Map;
25-
import java.util.Optional;
2625
import java.util.stream.Collectors;
2726

2827
import com.nimbusds.oauth2.sdk.TokenIntrospectionResponse;
@@ -124,16 +123,22 @@ private MultiValueMap<String, String> requestBody(String token) {
124123
*/
125124
@Override
126125
public Map<String, Object> introspect(String token) {
127-
TokenIntrospectionSuccessResponse response = Optional.of(token)
128-
.map(this.requestEntityConverter::convert)
129-
.map(this::makeRequest)
130-
.map(this::adaptToNimbusResponse)
131-
.map(this::parseNimbusResponse)
132-
.map(this::castToNimbusSuccess)
133-
// relying solely on the authorization server to validate this token (not checking 'exp', for example)
134-
.filter(TokenIntrospectionSuccessResponse::isActive)
135-
.orElseThrow(() -> new OAuth2IntrospectionException("Provided token [" + token + "] isn't active"));
136-
return convertClaimsSet(response);
126+
RequestEntity<?> requestEntity = this.requestEntityConverter.convert(token);
127+
if (requestEntity == null) {
128+
throw new OAuth2IntrospectionException("Provided token [" + token + "] isn't active");
129+
}
130+
131+
ResponseEntity<String> responseEntity = makeRequest(requestEntity);
132+
HTTPResponse httpResponse = adaptToNimbusResponse(responseEntity);
133+
TokenIntrospectionResponse introspectionResponse = parseNimbusResponse(httpResponse);
134+
TokenIntrospectionSuccessResponse introspectionSuccessResponse = castToNimbusSuccess(introspectionResponse);
135+
136+
// relying solely on the authorization server to validate this token (not checking 'exp', for example)
137+
if (!introspectionSuccessResponse.isActive()) {
138+
throw new OAuth2IntrospectionException("Provided token [" + token + "] isn't active");
139+
}
140+
141+
return convertClaimsSet(introspectionSuccessResponse);
137142
}
138143

139144
/**

samples/boot/oauth2login/src/integration-test/java/org/springframework/security/samples/OAuth2LoginApplicationTests.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@
6767
import java.util.HashSet;
6868
import java.util.List;
6969
import java.util.Map;
70-
import java.util.Optional;
7170
import java.util.Set;
7271
import java.util.stream.Collectors;
7372

@@ -331,10 +330,14 @@ private void assertIndexPage(HtmlPage page) throws Exception {
331330
}
332331

333332
private HtmlAnchor getClientAnchorElement(HtmlPage page, ClientRegistration clientRegistration) {
334-
Optional<HtmlAnchor> clientAnchorElement = page.getAnchors().stream()
335-
.filter(e -> e.asText().equals(clientRegistration.getClientName())).findFirst();
336-
337-
return (clientAnchorElement.orElse(null));
333+
HtmlAnchor result = null;
334+
for (HtmlAnchor anchor: page.getAnchors()) {
335+
if (anchor.asText().equals(clientRegistration.getClientName())) {
336+
result = anchor;
337+
break;
338+
}
339+
}
340+
return result;
338341
}
339342

340343
private WebResponse followLinkDisableRedirects(HtmlAnchor anchorElement) throws Exception {

web/src/main/java/org/springframework/security/web/server/csrf/CookieServerCsrfTokenRepository.java

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

1717
package org.springframework.security.web.server.csrf;
1818

19-
import java.util.Optional;
2019
import java.util.UUID;
2120

2221
import org.springframework.http.HttpCookie;
@@ -69,14 +68,17 @@ public Mono<CsrfToken> generateToken(ServerWebExchange exchange) {
6968
@Override
7069
public Mono<Void> saveToken(ServerWebExchange exchange, CsrfToken token) {
7170
return Mono.fromRunnable(() -> {
72-
Optional<String> tokenValue = Optional.ofNullable(token).map(CsrfToken::getToken);
71+
String tokenValue = token != null ? token.getToken() : "";
72+
int maxAge = !tokenValue.isEmpty() ? -1 : 0;
73+
String path = this.cookiePath != null ? this.cookiePath : getRequestContext(exchange.getRequest());
74+
boolean secure = exchange.getRequest().getSslInfo() != null;
7375

74-
ResponseCookie cookie = ResponseCookie.from(this.cookieName, tokenValue.orElse(""))
76+
ResponseCookie cookie = ResponseCookie.from(this.cookieName, tokenValue)
7577
.domain(this.cookieDomain)
7678
.httpOnly(this.cookieHttpOnly)
77-
.maxAge(tokenValue.map(val -> -1).orElse(0))
78-
.path(Optional.ofNullable(this.cookiePath).orElseGet(() -> getRequestContext(exchange.getRequest())))
79-
.secure(Optional.ofNullable(exchange.getRequest().getSslInfo()).map(sslInfo -> true).orElse(false))
79+
.maxAge(maxAge)
80+
.path(path)
81+
.secure(secure)
8082
.build();
8183

8284
exchange.getResponse().addCookie(cookie);

web/src/main/java/org/springframework/security/web/server/transport/HttpsRedirectWebFilter.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@
1717
package org.springframework.security.web.server.transport;
1818

1919
import java.net.URI;
20-
import java.util.Optional;
2120

2221
import reactor.core.publisher.Mono;
2322

@@ -102,10 +101,11 @@ private URI createRedirectUri(ServerWebExchange exchange) {
102101
UriComponentsBuilder.fromUri(exchange.getRequest().getURI());
103102

104103
if (port > 0) {
105-
Optional.ofNullable(this.portMapper.lookupHttpsPort(port))
106-
.map(builder::port)
107-
.orElseThrow(() -> new IllegalStateException(
108-
"HTTP Port '" + port + "' does not have a corresponding HTTPS Port"));
104+
Integer httpsPort = this.portMapper.lookupHttpsPort(port);
105+
if (httpsPort == null) {
106+
throw new IllegalStateException("HTTP Port '" + port + "' does not have a corresponding HTTPS Port");
107+
}
108+
builder.port(httpsPort);
109109
}
110110

111111
return builder.scheme("https").build().toUri();

0 commit comments

Comments
 (0)