7
7
import io .github .patternhelloworld .securityhelper .oauth2 .api .config .security .response .error .dto .EasyPlusErrorMessages ;
8
8
import io .github .patternhelloworld .securityhelper .oauth2 .api .config .security .response .error .exception .EasyPlusOauth2AuthenticationException ;
9
9
import io .github .patternhelloworld .securityhelper .oauth2 .api .config .security .serivce .persistence .authorization .OAuth2AuthorizationServiceImpl ;
10
+ import io .github .patternhelloworld .securityhelper .oauth2 .api .config .security .validator .endpoint .authorization .CodeValidationResult ;
11
+ import io .github .patternhelloworld .securityhelper .oauth2 .api .config .util .EasyPlusErrorCodeConstants ;
10
12
import io .github .patternhelloworld .securityhelper .oauth2 .api .config .util .EasyPlusOAuth2EndpointUtils ;
11
- import io .github .patternhelloworld .securityhelper .oauth2 .api .config .util .ErrorCodeConstants ;
12
13
import jakarta .servlet .http .HttpServletRequest ;
13
14
import lombok .RequiredArgsConstructor ;
14
15
import org .springframework .http .HttpMethod ;
15
- import org .springframework .security .authentication .AnonymousAuthenticationToken ;
16
16
import org .springframework .security .core .Authentication ;
17
- import org .springframework .security .core .authority .AuthorityUtils ;
18
17
import org .springframework .security .core .context .SecurityContextHolder ;
19
18
import org .springframework .security .oauth2 .core .ClientAuthenticationMethod ;
20
19
import org .springframework .security .oauth2 .core .endpoint .OAuth2ParameterNames ;
21
20
import org .springframework .security .oauth2 .core .oidc .OidcScopes ;
22
21
import org .springframework .security .oauth2 .server .authorization .OAuth2Authorization ;
23
22
import org .springframework .security .oauth2 .server .authorization .OAuth2TokenType ;
24
23
import org .springframework .security .oauth2 .server .authorization .authentication .OAuth2AuthorizationCodeAuthenticationToken ;
24
+ import org .springframework .security .oauth2 .server .authorization .authentication .OAuth2AuthorizationCodeRequestAuthenticationToken ;
25
25
import org .springframework .security .oauth2 .server .authorization .authentication .OAuth2ClientAuthenticationToken ;
26
26
import org .springframework .security .oauth2 .server .authorization .client .RegisteredClient ;
27
- import org .springframework .security .oauth2 .server .authorization .client .RegisteredClientRepository ;
28
27
import org .springframework .security .web .authentication .AuthenticationConverter ;
29
28
import org .springframework .security .web .util .matcher .AndRequestMatcher ;
30
29
import org .springframework .security .web .util .matcher .RequestMatcher ;
30
+ import org .springframework .util .Assert ;
31
31
import org .springframework .util .MultiValueMap ;
32
32
import org .springframework .util .StringUtils ;
33
33
34
- import java .util .*;
34
+ import java .util .Map ;
35
+ import java .util .function .Function ;
35
36
36
37
@ RequiredArgsConstructor
37
- public final class AuthorizationCodeAuthorizationRequestConverter implements AuthenticationConverter {
38
+ public final class CodeAuthorizationConditionalConverter implements AuthenticationConverter {
39
+
40
+ private Function <MultiValueMap <String , String >, CodeValidationResult > authenticationValidator ;
38
41
39
- private final RegisteredClientRepository registeredClientRepository ;
40
42
private final EasyPlusAuthorizationConsentRepository easyPlusAuthorizationConsentRepository ;
41
43
private final OAuth2AuthorizationServiceImpl oAuth2AuthorizationService ;
42
44
43
45
private final ISecurityUserExceptionMessageService iSecurityUserExceptionMessageService ;
44
46
45
47
private final String consentYN ;
46
48
47
- private static final Authentication ANONYMOUS_AUTHENTICATION = new AnonymousAuthenticationToken ("anonymous" ,
48
- "anonymousUser" , AuthorityUtils .createAuthorityList ("ROLE_ANONYMOUS" ));
49
-
50
- private static final RequestMatcher OIDC_REQUEST_MATCHER = createOidcRequestMatcher ();
51
-
52
49
/*
53
50
* Why is the validation check done here?
54
51
* - Because if an OAuth2AuthenticationException is thrown in the CustomizedProvider,
@@ -62,56 +59,19 @@ public Authentication convert(HttpServletRequest request) {
62
59
63
60
MultiValueMap <String , String > parameters = EasyPlusOAuth2EndpointUtils .getWebParametersContainingEasyPlusHeaders (request );
64
61
65
- String clientId = parameters .getFirst (OAuth2ParameterNames .CLIENT_ID );
66
- if (!StringUtils .hasText (clientId )) {
67
- throw new EasyPlusOauth2AuthenticationException (iSecurityUserExceptionMessageService .getUserMessage (DefaultSecurityUserExceptionMessage .AUTHENTICATION_CLIENT_ID_MISSING ));
68
- }
69
- String redirectUri = parameters .getFirst (OAuth2ParameterNames .REDIRECT_URI );
70
- if (!StringUtils .hasText (redirectUri )) {
71
- throw new EasyPlusOauth2AuthenticationException (iSecurityUserExceptionMessageService .getUserMessage (DefaultSecurityUserExceptionMessage .AUTHENTICATION_REDIRECT_URI_MISSING ));
72
- }
73
-
74
- Map <String , Object > additionalParameters = new HashMap <>();
62
+ CodeValidationResult codeValidationResult = this .authenticationValidator .apply (parameters );
75
63
76
- parameters .forEach ((key , value ) -> {
77
- additionalParameters .put (key , (value .size () == 1 ) ? value .get (0 ) : value .toArray (new String [0 ]));
78
- });
79
-
80
-
81
- String state = parameters .getFirst (OAuth2ParameterNames .STATE );
82
- if (!StringUtils .hasText (state )) {
83
- throw new EasyPlusOauth2AuthenticationException (iSecurityUserExceptionMessageService .getUserMessage (DefaultSecurityUserExceptionMessage .AUTHENTICATION_STATE_MISSING ));
84
- }
85
-
86
- Set <String > requestedScopes = new HashSet <>(parameters .getOrDefault (OAuth2ParameterNames .SCOPE , Collections .emptyList ()));
64
+ Map <String , Object > additionalParameters = EasyPlusOAuth2EndpointUtils .convertMultiValueMapToMap (parameters );
87
65
88
66
Authentication principal = SecurityContextHolder .getContext ().getAuthentication ();
89
67
if (principal == null ) {
90
- setClientAuthenticationContext (clientId );
68
+ setClientAuthenticationContext (codeValidationResult . getRegisteredClient () );
91
69
principal = SecurityContextHolder .getContext ().getAuthentication ();
92
70
}
93
71
94
- RegisteredClient registeredClient = ((OAuth2ClientAuthenticationToken ) principal ).getRegisteredClient ();
95
-
96
- if (registeredClient == null ) {
97
- throw new EasyPlusOauth2AuthenticationException (iSecurityUserExceptionMessageService .getUserMessage (DefaultSecurityUserExceptionMessage .AUTHENTICATION_REGISTERED_CLIENT_NOT_FOUND ));
98
- }
99
-
100
- if (!registeredClient .getRedirectUris ().contains (redirectUri )) {
101
- throw new EasyPlusOauth2AuthenticationException (iSecurityUserExceptionMessageService .getUserMessage (DefaultSecurityUserExceptionMessage .AUTHENTICATION_INVALID_REDIRECT_URI ));
102
- }
103
-
104
- Set <String > registeredScopes = registeredClient .getScopes (); // Scopes from the RegisteredClient
105
-
106
- if (!registeredScopes .containsAll (requestedScopes )) {
107
- throw new EasyPlusOauth2AuthenticationException (EasyPlusErrorMessages .builder ().userMessage (iSecurityUserExceptionMessageService .getUserMessage (DefaultSecurityUserExceptionMessage .AUTHENTICATION_LOGIN_ERROR ))
108
- .message ("Invalid scopes: " + requestedScopes + ". Allowed scopes: " + registeredScopes ).build ());
109
- }
110
-
111
72
String code = parameters .getFirst (OAuth2ParameterNames .CODE );
112
73
if (!StringUtils .hasText (code )) {
113
- throw new EasyPlusOauth2AuthenticationException (EasyPlusErrorMessages .builder ().userMessage (iSecurityUserExceptionMessageService .getUserMessage (DefaultSecurityUserExceptionMessage .AUTHENTICATION_AUTHORIZATION_CODE_MISSING ))
114
- .errorCode (ErrorCodeConstants .REDIRECT_TO_LOGIN ).build ());
74
+ return new OAuth2AuthorizationCodeRequestAuthenticationToken (request .getRequestURL ().toString (), codeValidationResult .getClientId (), principal , codeValidationResult .getRedirectUri (), codeValidationResult .getState (), codeValidationResult .getScope (), additionalParameters );
115
75
}
116
76
117
77
// Check Consent
@@ -129,15 +89,15 @@ public Authentication convert(HttpServletRequest request) {
129
89
} else {
130
90
// This means the user should check authorization consent OK
131
91
throw new EasyPlusOauth2AuthenticationException (EasyPlusErrorMessages .builder ().userMessage (iSecurityUserExceptionMessageService .getUserMessage (DefaultSecurityUserExceptionMessage .AUTHENTICATION_AUTHORIZATION_CODE_MISSING ))
132
- .errorCode (ErrorCodeConstants .REDIRECT_TO_CONSENT ).build ());
92
+ .errorCode (EasyPlusErrorCodeConstants .REDIRECT_TO_CONSENT ).build ());
133
93
}
134
94
}
135
95
}
136
96
137
97
return new OAuth2AuthorizationCodeAuthenticationToken (
138
98
code ,
139
99
principal ,
140
- redirectUri ,
100
+ codeValidationResult . getRedirectUri () ,
141
101
additionalParameters
142
102
);
143
103
}
@@ -153,12 +113,7 @@ private static RequestMatcher createOidcRequestMatcher() {
153
113
return new AndRequestMatcher (postMethodMatcher , responseTypeParameterMatcher , openidScopeMatcher );
154
114
}
155
115
156
- public void setClientAuthenticationContext (String clientId ) {
157
- RegisteredClient registeredClient = registeredClientRepository .findByClientId (clientId );
158
- if (registeredClient == null ) {
159
- throw new IllegalArgumentException ("Invalid client ID" );
160
- }
161
-
116
+ public void setClientAuthenticationContext (RegisteredClient registeredClient ) {
162
117
OAuth2ClientAuthenticationToken clientAuthenticationToken = new OAuth2ClientAuthenticationToken (
163
118
registeredClient ,
164
119
ClientAuthenticationMethod .CLIENT_SECRET_BASIC ,
@@ -168,5 +123,9 @@ public void setClientAuthenticationContext(String clientId) {
168
123
SecurityContextHolder .getContext ().setAuthentication (clientAuthenticationToken );
169
124
}
170
125
126
+ public void setAuthenticationValidator (Function <MultiValueMap <String , String >, CodeValidationResult > authenticationValidator ) {
127
+ Assert .notNull (authenticationValidator , "authenticationValidator cannot be null" );
128
+ this .authenticationValidator = authenticationValidator ;
129
+ }
171
130
}
172
131
0 commit comments