|
25 | 25 | import java.util.Arrays;
|
26 | 26 | import java.util.Base64;
|
27 | 27 | import java.util.Collection;
|
| 28 | +import java.util.Collections; |
| 29 | +import java.util.LinkedHashSet; |
28 | 30 | import java.util.List;
|
| 31 | +import java.util.Set; |
29 | 32 | import java.util.function.Consumer;
|
30 | 33 | import javax.servlet.http.HttpServletRequest;
|
31 | 34 | import javax.servlet.http.HttpServletResponse;
|
|
46 | 49 | import org.springframework.security.core.context.SecurityContextHolder;
|
47 | 50 | import org.springframework.security.core.userdetails.User;
|
48 | 51 | import org.springframework.security.core.userdetails.UserDetails;
|
| 52 | +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; |
| 53 | +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; |
| 54 | +import org.springframework.security.oauth2.client.registration.ClientRegistration; |
| 55 | +import org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizedClientRepository; |
| 56 | +import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository; |
| 57 | +import org.springframework.security.oauth2.core.AuthorizationGrantType; |
| 58 | +import org.springframework.security.oauth2.core.OAuth2AccessToken; |
| 59 | +import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames; |
| 60 | +import org.springframework.security.oauth2.core.oidc.OidcIdToken; |
| 61 | +import org.springframework.security.oauth2.core.oidc.OidcUserInfo; |
| 62 | +import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser; |
| 63 | +import org.springframework.security.oauth2.core.oidc.user.OidcUser; |
| 64 | +import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority; |
49 | 65 | import org.springframework.security.oauth2.jwt.Jwt;
|
50 | 66 | import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
|
51 | 67 | import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
|
@@ -314,6 +330,11 @@ public static RequestPostProcessor httpBasic(String username, String password) {
|
314 | 330 | return new HttpBasicRequestPostProcessor(username, password);
|
315 | 331 | }
|
316 | 332 |
|
| 333 | + public static OidcLoginRequestPostProcessor oidcLogin() { |
| 334 | + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", null, null, Collections.singleton("user")); |
| 335 | + return new OidcLoginRequestPostProcessor(accessToken); |
| 336 | + } |
| 337 | + |
317 | 338 | /**
|
318 | 339 | * Populates the X509Certificate instances onto the request
|
319 | 340 | */
|
@@ -1024,6 +1045,161 @@ public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request)
|
1024 | 1045 |
|
1025 | 1046 | }
|
1026 | 1047 |
|
| 1048 | + /** |
| 1049 | + * @author Josh Cummings |
| 1050 | + * @since 5.3 |
| 1051 | + */ |
| 1052 | + public final static class OidcLoginRequestPostProcessor implements RequestPostProcessor { |
| 1053 | + private ClientRegistration clientRegistration; |
| 1054 | + private OAuth2AccessToken accessToken; |
| 1055 | + private OidcIdToken idToken; |
| 1056 | + private OidcUserInfo userInfo; |
| 1057 | + private OidcUser oidcUser; |
| 1058 | + private Collection<GrantedAuthority> authorities; |
| 1059 | + |
| 1060 | + private OidcLoginRequestPostProcessor(OAuth2AccessToken accessToken) { |
| 1061 | + this.accessToken = accessToken; |
| 1062 | + this.clientRegistration = clientRegistrationBuilder().build(); |
| 1063 | + } |
| 1064 | + |
| 1065 | + /** |
| 1066 | + * Use the provided authorities in the {@link Authentication} |
| 1067 | + * |
| 1068 | + * @param authorities the authorities to use |
| 1069 | + * @return the {@link OidcLoginRequestPostProcessor} for further configuration |
| 1070 | + */ |
| 1071 | + public OidcLoginRequestPostProcessor authorities(Collection<GrantedAuthority> authorities) { |
| 1072 | + Assert.notNull(authorities, "authorities cannot be null"); |
| 1073 | + this.authorities = authorities; |
| 1074 | + return this; |
| 1075 | + } |
| 1076 | + |
| 1077 | + /** |
| 1078 | + * Use the provided authorities in the {@link Authentication} |
| 1079 | + * |
| 1080 | + * @param authorities the authorities to use |
| 1081 | + * @return the {@link OidcLoginRequestPostProcessor} for further configuration |
| 1082 | + */ |
| 1083 | + public OidcLoginRequestPostProcessor authorities(GrantedAuthority... authorities) { |
| 1084 | + Assert.notNull(authorities, "authorities cannot be null"); |
| 1085 | + this.authorities = Arrays.asList(authorities); |
| 1086 | + return this; |
| 1087 | + } |
| 1088 | + |
| 1089 | + /** |
| 1090 | + * Use the provided {@link OidcIdToken} when constructing the authenticated user |
| 1091 | + * |
| 1092 | + * @param idTokenBuilderConsumer a {@link Consumer} of a {@link OidcIdToken.Builder} |
| 1093 | + * @return the {@link OidcLoginRequestPostProcessor} for further configuration |
| 1094 | + */ |
| 1095 | + public OidcLoginRequestPostProcessor idToken(Consumer<OidcIdToken.Builder> idTokenBuilderConsumer) { |
| 1096 | + OidcIdToken.Builder builder = OidcIdToken.withTokenValue("id-token"); |
| 1097 | + builder.subject("test-subject"); |
| 1098 | + idTokenBuilderConsumer.accept(builder); |
| 1099 | + this.idToken = builder.build(); |
| 1100 | + return this; |
| 1101 | + } |
| 1102 | + |
| 1103 | + /** |
| 1104 | + * Use the provided {@link OidcUserInfo} when constructing the authenticated user |
| 1105 | + * |
| 1106 | + * @param userInfoBuilderConsumer a {@link Consumer} of a {@link OidcUserInfo.Builder} |
| 1107 | + * @return the {@link OidcLoginRequestPostProcessor} for further configuration |
| 1108 | + */ |
| 1109 | + public OidcLoginRequestPostProcessor userInfoToken(Consumer<OidcUserInfo.Builder> userInfoBuilderConsumer) { |
| 1110 | + OidcUserInfo.Builder builder = OidcUserInfo.builder(); |
| 1111 | + userInfoBuilderConsumer.accept(builder); |
| 1112 | + this.userInfo = builder.build(); |
| 1113 | + return this; |
| 1114 | + } |
| 1115 | + |
| 1116 | + /** |
| 1117 | + * Use the provided {@link OidcUser} as the authenticated user. |
| 1118 | + * |
| 1119 | + * Supplying an {@link OidcUser} will take precedence over {@link #idToken}, {@link #userInfo}, |
| 1120 | + * and list of {@link GrantedAuthority}s to use. |
| 1121 | + * |
| 1122 | + * @param oidcUser the {@link OidcUser} to use |
| 1123 | + * @return the {@link OidcLoginRequestPostProcessor} for further configuration |
| 1124 | + */ |
| 1125 | + public OidcLoginRequestPostProcessor oidcUser(OidcUser oidcUser) { |
| 1126 | + this.oidcUser = oidcUser; |
| 1127 | + return this; |
| 1128 | + } |
| 1129 | + |
| 1130 | + /** |
| 1131 | + * Use the provided {@link ClientRegistration} as the client to authorize. |
| 1132 | + * |
| 1133 | + * The supplied {@link ClientRegistration} will be registered into an |
| 1134 | + * {@link HttpSessionOAuth2AuthorizedClientRepository}. Tests relying on |
| 1135 | + * {@link org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient} |
| 1136 | + * annotations should register a {@link HttpSessionOAuth2AuthorizedClientRepository} bean |
| 1137 | + * to the application context. |
| 1138 | + * |
| 1139 | + * The client registration must be a valid {@link ClientRegistration} from the |
| 1140 | + * {@link org.springframework.security.oauth2.client.registration.ClientRegistrationRepository} |
| 1141 | + * in the application context. |
| 1142 | + * |
| 1143 | + * @param clientRegistration the {@link ClientRegistration} to use |
| 1144 | + * @return the {@link OidcLoginRequestPostProcessor} for further configuration |
| 1145 | + */ |
| 1146 | + public OidcLoginRequestPostProcessor clientRegistration(ClientRegistration clientRegistration) { |
| 1147 | + this.clientRegistration = clientRegistration; |
| 1148 | + return this; |
| 1149 | + } |
| 1150 | + |
| 1151 | + @Override |
| 1152 | + public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { |
| 1153 | + OidcUser oidcUser = getOidcUser(); |
| 1154 | + OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(oidcUser, oidcUser.getAuthorities(), this.clientRegistration.getRegistrationId()); |
| 1155 | + OAuth2AuthorizedClient client = new OAuth2AuthorizedClient(this.clientRegistration, token.getName(), this.accessToken); |
| 1156 | + OAuth2AuthorizedClientRepository authorizedClientRepository = new HttpSessionOAuth2AuthorizedClientRepository(); |
| 1157 | + authorizedClientRepository.saveAuthorizedClient(client, token, request, new MockHttpServletResponse()); |
| 1158 | + |
| 1159 | + return new AuthenticationRequestPostProcessor(token).postProcessRequest(request); |
| 1160 | + } |
| 1161 | + |
| 1162 | + private ClientRegistration.Builder clientRegistrationBuilder() { |
| 1163 | + return ClientRegistration.withRegistrationId("test") |
| 1164 | + .authorizationGrantType(AuthorizationGrantType.PASSWORD) |
| 1165 | + .clientId("test-client") |
| 1166 | + .tokenUri("https://token-uri.example.org"); |
| 1167 | + } |
| 1168 | + |
| 1169 | + private Collection<GrantedAuthority> getAuthorities() { |
| 1170 | + if (this.authorities == null) { |
| 1171 | + Set<GrantedAuthority> authorities = new LinkedHashSet<>(); |
| 1172 | + authorities.add(new OidcUserAuthority(getOidcIdToken(), getOidcUserInfo())); |
| 1173 | + for (String authority : this.accessToken.getScopes()) { |
| 1174 | + authorities.add(new SimpleGrantedAuthority("SCOPE_" + authority)); |
| 1175 | + } |
| 1176 | + return authorities; |
| 1177 | + } else { |
| 1178 | + return this.authorities; |
| 1179 | + } |
| 1180 | + } |
| 1181 | + |
| 1182 | + private OidcIdToken getOidcIdToken() { |
| 1183 | + if (this.idToken == null) { |
| 1184 | + return new OidcIdToken("id-token", null, null, Collections.singletonMap(IdTokenClaimNames.SUB, "test-subject")); |
| 1185 | + } else { |
| 1186 | + return this.idToken; |
| 1187 | + } |
| 1188 | + } |
| 1189 | + |
| 1190 | + private OidcUserInfo getOidcUserInfo() { |
| 1191 | + return this.userInfo; |
| 1192 | + } |
| 1193 | + |
| 1194 | + private OidcUser getOidcUser() { |
| 1195 | + if (this.oidcUser == null) { |
| 1196 | + return new DefaultOidcUser(getAuthorities(), getOidcIdToken(), this.userInfo); |
| 1197 | + } else { |
| 1198 | + return this.oidcUser; |
| 1199 | + } |
| 1200 | + } |
| 1201 | + } |
| 1202 | + |
1027 | 1203 | private SecurityMockMvcRequestPostProcessors() {
|
1028 | 1204 | }
|
1029 | 1205 | }
|
0 commit comments