1+ package com .chensoul .config ;
2+
3+ import com .chensoul .support .AccessTokenResponseHandler ;
4+ import com .chensoul .support .FederatedIdentityAuthenticationSuccessHandler ;
5+ import org .springframework .boot .autoconfigure .security .oauth2 .server .servlet .OAuth2AuthorizationServerAutoConfiguration ;
6+ import org .springframework .boot .autoconfigure .security .oauth2 .server .servlet .OAuth2AuthorizationServerJwtAutoConfiguration ;
7+ import org .springframework .context .annotation .Bean ;
8+ import org .springframework .context .annotation .Configuration ;
9+ import org .springframework .core .Ordered ;
10+ import org .springframework .core .annotation .Order ;
11+ import org .springframework .http .MediaType ;
12+ import org .springframework .security .config .Customizer ;
13+ import org .springframework .security .config .annotation .web .builders .HttpSecurity ;
14+ import org .springframework .security .core .session .SessionRegistry ;
15+ import org .springframework .security .core .session .SessionRegistryImpl ;
16+ import org .springframework .security .core .userdetails .User ;
17+ import org .springframework .security .core .userdetails .UserDetails ;
18+ import org .springframework .security .core .userdetails .UserDetailsService ;
19+ import org .springframework .security .oauth2 .core .AuthorizationGrantType ;
20+ import org .springframework .security .oauth2 .core .ClientAuthenticationMethod ;
21+ import org .springframework .security .oauth2 .core .oidc .OidcScopes ;
22+ import org .springframework .security .oauth2 .server .authorization .InMemoryOAuth2AuthorizationConsentService ;
23+ import org .springframework .security .oauth2 .server .authorization .InMemoryOAuth2AuthorizationService ;
24+ import org .springframework .security .oauth2 .server .authorization .OAuth2AuthorizationConsentService ;
25+ import org .springframework .security .oauth2 .server .authorization .OAuth2AuthorizationService ;
26+ import org .springframework .security .oauth2 .server .authorization .client .InMemoryRegisteredClientRepository ;
27+ import org .springframework .security .oauth2 .server .authorization .client .RegisteredClient ;
28+ import org .springframework .security .oauth2 .server .authorization .client .RegisteredClientRepository ;
29+ import org .springframework .security .oauth2 .server .authorization .config .annotation .web .configurers .OAuth2AuthorizationServerConfigurer ;
30+ import org .springframework .security .oauth2 .server .authorization .settings .AuthorizationServerSettings ;
31+ import org .springframework .security .oauth2 .server .authorization .settings .ClientSettings ;
32+ import org .springframework .security .oauth2 .server .authorization .settings .OAuth2TokenFormat ;
33+ import org .springframework .security .oauth2 .server .authorization .settings .TokenSettings ;
34+ import org .springframework .security .provisioning .InMemoryUserDetailsManager ;
35+ import org .springframework .security .web .SecurityFilterChain ;
36+ import org .springframework .security .web .authentication .AuthenticationSuccessHandler ;
37+ import org .springframework .security .web .authentication .LoginUrlAuthenticationEntryPoint ;
38+ import org .springframework .security .web .session .HttpSessionEventPublisher ;
39+ import org .springframework .security .web .util .matcher .MediaTypeRequestMatcher ;
40+
41+ import java .util .UUID ;
42+
43+ import static org .springframework .security .oauth2 .server .authorization .config .annotation .web .configurers .OAuth2AuthorizationServerConfigurer .authorizationServer ;
44+
45+ /**
46+ * @see OAuth2AuthorizationServerAutoConfiguration
47+ * @see OAuth2AuthorizationServerJwtAutoConfiguration
48+ */
49+ @ Configuration
50+ public class SecurityConfig {
51+ private static final String CUSTOM_CONSENT_PAGE_URI = "/oauth2/consent" ;
52+
53+ @ Bean
54+ @ Order (Ordered .HIGHEST_PRECEDENCE )
55+ SecurityFilterChain authorizationServerSecurityFilterChain (HttpSecurity http ) throws Exception {
56+ OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = authorizationServer ();
57+
58+ http .securityMatcher (authorizationServerConfigurer .getEndpointsMatcher ())
59+ .with (authorizationServerConfigurer , (authorizationServer ) ->
60+ authorizationServer
61+ .authorizationEndpoint (authorizationEndpoint ->
62+ authorizationEndpoint .consentPage (CUSTOM_CONSENT_PAGE_URI ))
63+ .tokenEndpoint (token ->
64+ token .accessTokenResponseHandler (new AccessTokenResponseHandler ()))
65+ .oidc (Customizer .withDefaults ()) // Enable OpenID Connect 1.0
66+ )
67+ // Redirect to the login page when not authenticated from the
68+ // authorization endpoint
69+ .exceptionHandling ((exceptions ) -> exceptions
70+ .defaultAuthenticationEntryPointFor (
71+ new LoginUrlAuthenticationEntryPoint ("/login" ),
72+ new MediaTypeRequestMatcher (MediaType .TEXT_HTML )
73+ )
74+ );
75+
76+ return http .build ();
77+ }
78+
79+ @ Bean
80+ public SecurityFilterChain defaultSecurityFilterChain (HttpSecurity http ) throws Exception {
81+ http
82+ .authorizeHttpRequests (authorize ->
83+ authorize
84+ .requestMatchers ("/webjars/**" , "/assets/**" , "/login" , "/logged-out" ).permitAll ()
85+ .anyRequest ().authenticated ()
86+ )
87+ .formLogin (formLogin ->
88+ formLogin
89+ .loginPage ("/login" )
90+ )
91+ .oauth2Login (oauth2Login ->
92+ oauth2Login
93+ .loginPage ("/login" )
94+ .successHandler (authenticationSuccessHandler ())
95+ );
96+
97+ return http .build ();
98+ }
99+
100+ private AuthenticationSuccessHandler authenticationSuccessHandler () {
101+ return new FederatedIdentityAuthenticationSuccessHandler ();
102+ }
103+
104+ // @formatter:off
105+ @ Bean
106+ public UserDetailsService users () {
107+ UserDetails user = User .withDefaultPasswordEncoder ()
108+ .username ("user" )
109+ .password ("password" )
110+ .roles ("USER" )
111+ .build ();
112+ return new InMemoryUserDetailsManager (user );
113+ }
114+
115+ @ Bean
116+ public RegisteredClientRepository registeredClientRepository () {
117+ // @formatter:off
118+ RegisteredClient oidcClient = RegisteredClient .withId (UUID .randomUUID ().toString ())
119+ .clientId ("oidc-client" )
120+ .clientSecret ("{noop}oidc-client" )
121+ .clientAuthenticationMethod (ClientAuthenticationMethod .CLIENT_SECRET_BASIC )
122+ .clientAuthenticationMethod (ClientAuthenticationMethod .CLIENT_SECRET_POST )
123+ .authorizationGrantType (AuthorizationGrantType .AUTHORIZATION_CODE )
124+ .authorizationGrantType (AuthorizationGrantType .REFRESH_TOKEN )
125+ .redirectUri ("https://oidcdebugger.com/debug" )
126+ .redirectUri ("https://oauthdebugger.com/debug" )
127+ .redirectUri ("http://127.0.0.1:8080/login/oauth2/code/oidc-client" )
128+ .postLogoutRedirectUri ("http://127.0.0.1:8080/" )
129+ .scope (OidcScopes .OPENID )
130+ .scope (OidcScopes .ADDRESS )
131+ .scope (OidcScopes .EMAIL )
132+ .scope (OidcScopes .PHONE )
133+ .scope (OidcScopes .PROFILE )
134+ .scope ("read" )
135+ .scope ("write" )
136+ .clientSettings (ClientSettings .builder ().requireAuthorizationConsent (true ).build ())
137+ .build ();
138+
139+ RegisteredClient credentialsClient = RegisteredClient .withId (UUID .randomUUID ().toString ())
140+ .clientId ("credentials-client" )
141+ .clientSecret ("{noop}credentials-client" )
142+ .clientAuthenticationMethod (ClientAuthenticationMethod .CLIENT_SECRET_BASIC )
143+ .clientAuthenticationMethod (ClientAuthenticationMethod .CLIENT_SECRET_POST )
144+ .authorizationGrantType (AuthorizationGrantType .CLIENT_CREDENTIALS )
145+ .scope (OidcScopes .OPENID )
146+ .scope (OidcScopes .PROFILE )
147+ .scope ("read" )
148+ .scope ("write" )
149+ .scope ("client.create" )
150+ .scope ("client.read" )
151+ .build ();
152+
153+ RegisteredClient pkceClient = RegisteredClient .withId (UUID .randomUUID ().toString ())
154+ .clientId ("pkce-client" )
155+ .clientAuthenticationMethod (ClientAuthenticationMethod .NONE )
156+ .clientAuthenticationMethod (ClientAuthenticationMethod .CLIENT_SECRET_BASIC )
157+ .clientAuthenticationMethod (ClientAuthenticationMethod .CLIENT_SECRET_POST )
158+ .authorizationGrantType (AuthorizationGrantType .AUTHORIZATION_CODE )
159+ .authorizationGrantType (AuthorizationGrantType .REFRESH_TOKEN )
160+ .redirectUri ("http://127.0.0.1:4200" )
161+ .redirectUri ("https://oidcdebugger.com/debug" )
162+ .redirectUri ("https://oauthdebugger.com/debug" )
163+ .redirectUri ("http://127.0.0.1:8080/login/oauth2/code/pkce-client" )
164+ .postLogoutRedirectUri ("http://127.0.0.1:8080/" )
165+ .scope (OidcScopes .OPENID )
166+ .scope (OidcScopes .PROFILE )
167+ .clientSettings (ClientSettings .builder ()
168+ .requireAuthorizationConsent (true )
169+ .requireProofKey (true )
170+ .build ()
171+ )
172+ .build ();
173+
174+ RegisteredClient opaqueClient = RegisteredClient .withId (UUID .randomUUID ().toString ())
175+ .clientId ("opaque-client" )
176+ .clientSecret ("{noop}opaque-client" )
177+ .clientAuthenticationMethod (ClientAuthenticationMethod .CLIENT_SECRET_BASIC )
178+ .authorizationGrantType (AuthorizationGrantType .CLIENT_CREDENTIALS )
179+ .scope (OidcScopes .OPENID )
180+ .scope (OidcScopes .PROFILE )
181+ .tokenSettings (TokenSettings .builder ().accessTokenFormat (OAuth2TokenFormat .REFERENCE ).build ()
182+ ).build ();
183+
184+ // @formatter:on
185+ return new InMemoryRegisteredClientRepository (oidcClient , credentialsClient , pkceClient , opaqueClient );
186+ }
187+
188+ @ Bean
189+ public AuthorizationServerSettings authorizationServerSettings () {
190+ return AuthorizationServerSettings .builder ().build ();
191+ }
192+
193+ @ Bean
194+ public OAuth2AuthorizationService authorizationService () {
195+ return new InMemoryOAuth2AuthorizationService ();
196+ }
197+
198+ @ Bean
199+ public OAuth2AuthorizationConsentService authorizationConsentService () {
200+ return new InMemoryOAuth2AuthorizationConsentService ();
201+ }
202+
203+
204+ @ Bean
205+ public SessionRegistry sessionRegistry () {
206+ return new SessionRegistryImpl ();
207+ }
208+
209+ @ Bean
210+ public HttpSessionEventPublisher httpSessionEventPublisher () {
211+ return new HttpSessionEventPublisher ();
212+ }
213+ }
0 commit comments