Explorar el Código

Fix CNF exception if oauth2-jose dependency not included

Fixes gh-4753
Joe Grandja hace 8 años
padre
commit
aa9e057ba8

+ 56 - 11
config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java

@@ -18,12 +18,16 @@ package org.springframework.security.config.annotation.web.configurers.oauth2.cl
 import org.springframework.beans.factory.BeanFactoryUtils;
 import org.springframework.context.ApplicationContext;
 import org.springframework.core.ResolvableType;
+import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
 import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
 import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService;
 import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
 import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationProvider;
+import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationToken;
 import org.springframework.security.oauth2.client.endpoint.NimbusAuthorizationCodeTokenResponseClient;
 import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
 import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
@@ -40,13 +44,17 @@ import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
 import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository;
 import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter;
 import org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter;
+import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
+import org.springframework.security.oauth2.core.OAuth2Error;
 import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
+import org.springframework.security.oauth2.core.oidc.OidcScopes;
 import org.springframework.security.oauth2.core.oidc.user.OidcUser;
 import org.springframework.security.oauth2.core.user.OAuth2User;
 import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
 import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 import org.springframework.security.web.util.matcher.RequestMatcher;
 import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -246,19 +254,25 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>> exten
 		}
 		http.authenticationProvider(this.postProcess(oauth2LoginAuthenticationProvider));
 
-		OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService = this.userInfoEndpointConfig.oidcUserService;
-		if (oidcUserService == null) {
-			oidcUserService = new OidcUserService();
-		}
+		boolean oidcAuthenticationProviderEnabled = ClassUtils.isPresent(
+			"org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader());
 
-		OidcAuthorizationCodeAuthenticationProvider oidcAuthorizationCodeAuthenticationProvider =
-			new OidcAuthorizationCodeAuthenticationProvider(
-				accessTokenResponseClient, oidcUserService);
-		if (this.userInfoEndpointConfig.userAuthoritiesMapper != null) {
-			oidcAuthorizationCodeAuthenticationProvider.setAuthoritiesMapper(
-				this.userInfoEndpointConfig.userAuthoritiesMapper);
+		if (oidcAuthenticationProviderEnabled) {
+			OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService = this.userInfoEndpointConfig.oidcUserService;
+			if (oidcUserService == null) {
+				oidcUserService = new OidcUserService();
+			}
+
+			OidcAuthorizationCodeAuthenticationProvider oidcAuthorizationCodeAuthenticationProvider =
+				new OidcAuthorizationCodeAuthenticationProvider(accessTokenResponseClient, oidcUserService);
+			if (this.userInfoEndpointConfig.userAuthoritiesMapper != null) {
+				oidcAuthorizationCodeAuthenticationProvider.setAuthoritiesMapper(
+					this.userInfoEndpointConfig.userAuthoritiesMapper);
+			}
+			http.authenticationProvider(this.postProcess(oidcAuthorizationCodeAuthenticationProvider));
+		} else {
+			http.authenticationProvider(new OidcAuthenticationRequestChecker());
 		}
-		http.authenticationProvider(this.postProcess(oidcAuthorizationCodeAuthenticationProvider));
 
 		this.initDefaultLoginFilter(http);
 	}
@@ -359,4 +373,35 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>> exten
 		loginPageGeneratingFilter.setLoginPageUrl(this.getLoginPage());
 		loginPageGeneratingFilter.setFailureUrl(this.getFailureUrl());
 	}
+
+	private static class OidcAuthenticationRequestChecker implements AuthenticationProvider {
+
+		@Override
+		public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+			OAuth2LoginAuthenticationToken authorizationCodeAuthentication =
+				(OAuth2LoginAuthenticationToken) authentication;
+
+			// Section 3.1.2.1 Authentication Request - http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
+			// scope
+			// 		REQUIRED. OpenID Connect requests MUST contain the "openid" scope value.
+			if (authorizationCodeAuthentication.getAuthorizationExchange()
+				.getAuthorizationRequest().getScopes().contains(OidcScopes.OPENID)) {
+
+				OAuth2Error oauth2Error = new OAuth2Error(
+					"oidc_provider_not_configured",
+					"An OpenID Connect Authentication Provider has not been configured. " +
+						"Check to ensure you include the dependency 'spring-security-oauth2-jose'.",
+					null);
+				throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
+			}
+
+			return null;
+		}
+
+		@Override
+		public boolean supports(Class<?> authentication) {
+			return OAuth2LoginAuthenticationToken.class.isAssignableFrom(authentication);
+		}
+	}
+
 }