2323
2424import  org .springframework .context .ApplicationContext ;
2525import  org .springframework .http .HttpMethod ;
26- import  org .springframework .security .authentication .AuthenticationManager ;
2726import  org .springframework .security .authentication .AuthenticationProvider ;
2827import  org .springframework .security .authentication .ott .GenerateOneTimeTokenRequest ;
2928import  org .springframework .security .authentication .ott .InMemoryOneTimeTokenService ;
3231import  org .springframework .security .authentication .ott .OneTimeTokenService ;
3332import  org .springframework .security .config .Customizer ;
3433import  org .springframework .security .config .annotation .web .HttpSecurityBuilder ;
34+ import  org .springframework .security .config .annotation .web .builders .HttpSecurity ;
35+ import  org .springframework .security .config .annotation .web .configuration .EnableWebSecurity ;
36+ import  org .springframework .security .config .annotation .web .configurers .AbstractAuthenticationFilterConfigurer ;
3537import  org .springframework .security .config .annotation .web .configurers .AbstractHttpConfigurer ;
3638import  org .springframework .security .core .Authentication ;
3739import  org .springframework .security .core .userdetails .UserDetailsService ;
4951import  org .springframework .security .web .authentication .ui .DefaultLoginPageGeneratingFilter ;
5052import  org .springframework .security .web .authentication .ui .DefaultOneTimeTokenSubmitPageGeneratingFilter ;
5153import  org .springframework .security .web .authentication .ui .DefaultResourcesFilter ;
52- import  org .springframework .security .web .context .HttpSessionSecurityContextRepository ;
53- import  org .springframework .security .web .context .SecurityContextRepository ;
5454import  org .springframework .security .web .csrf .CsrfToken ;
55+ import  org .springframework .security .web .util .matcher .RequestMatcher ;
5556import  org .springframework .util .Assert ;
5657import  org .springframework .util .StringUtils ;
5758
5859import  static  org .springframework .security .web .util .matcher .AntPathRequestMatcher .antMatcher ;
5960
60- public  final  class  OneTimeTokenLoginConfigurer <H  extends  HttpSecurityBuilder <H >>
61- 		extends  AbstractHttpConfigurer <OneTimeTokenLoginConfigurer <H >, H > {
61+ /** 
62+  * An {@link AbstractHttpConfigurer} for One-Time Token Login. 
63+  * 
64+  * <p> 
65+  * One-Time Token Login provides an application with the capability to have users log in 
66+  * by obtaining a single-use token out of band, for example through email. 
67+  * 
68+  * <p> 
69+  * Defaults are provided for all configuration options, with the only required 
70+  * configuration being 
71+  * {@link #tokenGenerationSuccessHandler(OneTimeTokenGenerationSuccessHandler)}. 
72+  * Alternatively, a {@link OneTimeTokenGenerationSuccessHandler} {@code @Bean} may be 
73+  * registered instead. 
74+  * 
75+  * <h2>Security Filters</h2> 
76+  * 
77+  * The following {@code Filter}s are populated: 
78+  * 
79+  * <ul> 
80+  * <li>{@link DefaultOneTimeTokenSubmitPageGeneratingFilter}</li> 
81+  * <li>{@link GenerateOneTimeTokenFilter}</li> 
82+  * <li>{@link OneTimeTokenAuthenticationFilter}</li> 
83+  * </ul> 
84+  * 
85+  * <h2>Shared Objects Used</h2> 
86+  * 
87+  * The following shared objects are used: 
88+  * 
89+  * <ul> 
90+  * <li>{@link DefaultLoginPageGeneratingFilter} - if {@link #loginPage(String)} is not 
91+  * configured and {@code DefaultLoginPageGeneratingFilter} is available, then a default 
92+  * login page will be made available</li> 
93+  * </ul> 
94+  * 
95+  * @author Marcus Da Coregio 
96+  * @author Daniel Garnier-Moiroux 
97+  * @since 6.4 
98+  * @see HttpSecurity#oneTimeTokenLogin(Customizer) 
99+  * @see DefaultOneTimeTokenSubmitPageGeneratingFilter 
100+  * @see GenerateOneTimeTokenFilter 
101+  * @see OneTimeTokenAuthenticationFilter 
102+  * @see AbstractAuthenticationFilterConfigurer 
103+  */ 
104+ public  final  class  OneTimeTokenLoginConfigurer <H  extends  HttpSecurityBuilder <H >> extends 
105+ 		AbstractAuthenticationFilterConfigurer <H , OneTimeTokenLoginConfigurer <H >, OneTimeTokenAuthenticationFilter > {
62106
63107	private  final  ApplicationContext  context ;
64108
65109	private  OneTimeTokenService  oneTimeTokenService ;
66110
67- 	private  AuthenticationConverter  authenticationConverter  = new  OneTimeTokenAuthenticationConverter ();
68- 
69- 	private  AuthenticationFailureHandler  authenticationFailureHandler ;
70- 
71- 	private  AuthenticationSuccessHandler  authenticationSuccessHandler  = new  SavedRequestAwareAuthenticationSuccessHandler ();
72- 
73- 	private  String  defaultSubmitPageUrl  = "/login/ott" ;
111+ 	private  String  defaultSubmitPageUrl  = DefaultOneTimeTokenSubmitPageGeneratingFilter .DEFAULT_SUBMIT_PAGE_URL ;
74112
75113	private  boolean  submitPageEnabled  = true ;
76114
77115	private  String  loginProcessingUrl  = OneTimeTokenAuthenticationFilter .DEFAULT_LOGIN_PROCESSING_URL ;
78116
79- 	private  String  tokenGeneratingUrl  = "/ott/generate" ;
117+ 	private  String  tokenGeneratingUrl  = GenerateOneTimeTokenFilter . DEFAULT_GENERATE_URL ;
80118
81119	private  OneTimeTokenGenerationSuccessHandler  oneTimeTokenGenerationSuccessHandler ;
82120
@@ -85,58 +123,41 @@ public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>>
85123	private  GenerateOneTimeTokenRequestResolver  requestResolver ;
86124
87125	public  OneTimeTokenLoginConfigurer (ApplicationContext  context ) {
126+ 		super (new  OneTimeTokenAuthenticationFilter (), OneTimeTokenAuthenticationFilter .DEFAULT_LOGIN_PROCESSING_URL );
88127		this .context  = context ;
89128	}
90129
91130	@ Override 
92- 	public  void  init (H  http ) {
131+ 	public  void  init (H  http ) throws  Exception  {
132+ 		super .init (http );
93133		AuthenticationProvider  authenticationProvider  = getAuthenticationProvider ();
94134		http .authenticationProvider (postProcess (authenticationProvider ));
95- 		configureDefaultLoginPage (http );
135+ 		intiDefaultLoginFilter (http );
96136	}
97137
98- 	private  void  configureDefaultLoginPage (H  http ) {
138+ 	private  void  intiDefaultLoginFilter (H  http ) {
99139		DefaultLoginPageGeneratingFilter  loginPageGeneratingFilter  = http 
100140			.getSharedObject (DefaultLoginPageGeneratingFilter .class );
101- 		if  (loginPageGeneratingFilter  == null ) {
141+ 		if  (loginPageGeneratingFilter  == null  ||  isCustomLoginPage () ) {
102142			return ;
103143		}
104144		loginPageGeneratingFilter .setOneTimeTokenEnabled (true );
105145		loginPageGeneratingFilter .setOneTimeTokenGenerationUrl (this .tokenGeneratingUrl );
106- 		if  (this .authenticationFailureHandler  == null 
107- 				&& StringUtils .hasText (loginPageGeneratingFilter .getLoginPageUrl ())) {
108- 			this .authenticationFailureHandler  = new  SimpleUrlAuthenticationFailureHandler (
109- 					loginPageGeneratingFilter .getLoginPageUrl () + "?error" );
146+ 
147+ 		if  (!StringUtils .hasText (loginPageGeneratingFilter .getLoginPageUrl ())) {
148+ 			loginPageGeneratingFilter .setLoginPageUrl (DefaultLoginPageGeneratingFilter .DEFAULT_LOGIN_PAGE_URL );
149+ 			loginPageGeneratingFilter .setFailureUrl (DefaultLoginPageGeneratingFilter .DEFAULT_LOGIN_PAGE_URL  + "?" 
150+ 					+ DefaultLoginPageGeneratingFilter .ERROR_PARAMETER_NAME );
151+ 			loginPageGeneratingFilter 
152+ 				.setLogoutSuccessUrl (DefaultLoginPageGeneratingFilter .DEFAULT_LOGIN_PAGE_URL  + "?logout" );
110153		}
111154	}
112155
113156	@ Override 
114- 	public  void  configure (H  http ) {
157+ 	public  void  configure (H  http ) throws  Exception  {
158+ 		super .configure (http );
115159		configureSubmitPage (http );
116160		configureOttGenerateFilter (http );
117- 		configureOttAuthenticationFilter (http );
118- 	}
119- 
120- 	private  void  configureOttAuthenticationFilter (H  http ) {
121- 		AuthenticationManager  authenticationManager  = http .getSharedObject (AuthenticationManager .class );
122- 		OneTimeTokenAuthenticationFilter  oneTimeTokenAuthenticationFilter  = new  OneTimeTokenAuthenticationFilter ();
123- 		oneTimeTokenAuthenticationFilter .setAuthenticationManager (authenticationManager );
124- 		if  (this .loginProcessingUrl  != null ) {
125- 			oneTimeTokenAuthenticationFilter 
126- 				.setRequiresAuthenticationRequestMatcher (antMatcher (HttpMethod .POST , this .loginProcessingUrl ));
127- 		}
128- 		oneTimeTokenAuthenticationFilter .setAuthenticationSuccessHandler (this .authenticationSuccessHandler );
129- 		oneTimeTokenAuthenticationFilter .setAuthenticationFailureHandler (getAuthenticationFailureHandler ());
130- 		oneTimeTokenAuthenticationFilter .setSecurityContextRepository (getSecurityContextRepository (http ));
131- 		http .addFilter (postProcess (oneTimeTokenAuthenticationFilter ));
132- 	}
133- 
134- 	private  SecurityContextRepository  getSecurityContextRepository (H  http ) {
135- 		SecurityContextRepository  securityContextRepository  = http .getSharedObject (SecurityContextRepository .class );
136- 		if  (securityContextRepository  != null ) {
137- 			return  securityContextRepository ;
138- 		}
139- 		return  new  HttpSessionSecurityContextRepository ();
140161	}
141162
142163	private  void  configureOttGenerateFilter (H  http ) {
@@ -170,7 +191,7 @@ private void configureSubmitPage(H http) {
170191		DefaultOneTimeTokenSubmitPageGeneratingFilter  submitPage  = new  DefaultOneTimeTokenSubmitPageGeneratingFilter ();
171192		submitPage .setResolveHiddenInputs (this ::hiddenInputs );
172193		submitPage .setRequestMatcher (antMatcher (HttpMethod .GET , this .defaultSubmitPageUrl ));
173- 		submitPage .setLoginProcessingUrl (this .loginProcessingUrl );
194+ 		submitPage .setLoginProcessingUrl (this .getLoginProcessingUrl () );
174195		http .addFilter (postProcess (submitPage ));
175196	}
176197
@@ -184,6 +205,11 @@ private AuthenticationProvider getAuthenticationProvider() {
184205		return  this .authenticationProvider ;
185206	}
186207
208+ 	@ Override 
209+ 	protected  RequestMatcher  createLoginProcessingUrlMatcher (String  loginProcessingUrl ) {
210+ 		return  antMatcher (HttpMethod .POST , loginProcessingUrl );
211+ 	}
212+ 
187213	/** 
188214	 * Specifies the {@link AuthenticationProvider} to use when authenticating the user. 
189215	 * @param authenticationProvider 
@@ -221,14 +247,25 @@ public OneTimeTokenLoginConfigurer<H> tokenGenerationSuccessHandler(
221247	 * Only POST requests are processed, for that reason make sure that you pass a valid 
222248	 * CSRF token if CSRF protection is enabled. 
223249	 * @param loginProcessingUrl 
224- 	 * @see org.springframework.security.config.annotation.web.builders. HttpSecurity#csrf(Customizer) 
250+ 	 * @see HttpSecurity#csrf(Customizer) 
225251	 */ 
226252	public  OneTimeTokenLoginConfigurer <H > loginProcessingUrl (String  loginProcessingUrl ) {
227253		Assert .hasText (loginProcessingUrl , "loginProcessingUrl cannot be null or empty" );
228- 		this .loginProcessingUrl  =  loginProcessingUrl ;
254+ 		super .loginProcessingUrl ( loginProcessingUrl ) ;
229255		return  this ;
230256	}
231257
258+ 	/** 
259+ 	 * Specifies the URL to send users to if login is required. If used with 
260+ 	 * {@link EnableWebSecurity} a default login page will be generated when this 
261+ 	 * attribute is not specified. 
262+ 	 * @param loginPage 
263+ 	 */ 
264+ 	@ Override 
265+ 	public  OneTimeTokenLoginConfigurer <H > loginPage (String  loginPage ) {
266+ 		return  super .loginPage (loginPage );
267+ 	}
268+ 
232269	/** 
233270	 * Configures whether the default one-time token submit page should be shown. This 
234271	 * will prevent the {@link DefaultOneTimeTokenSubmitPageGeneratingFilter} to be 
@@ -273,7 +310,7 @@ public OneTimeTokenLoginConfigurer<H> tokenService(OneTimeTokenService oneTimeTo
273310	 */ 
274311	public  OneTimeTokenLoginConfigurer <H > authenticationConverter (AuthenticationConverter  authenticationConverter ) {
275312		Assert .notNull (authenticationConverter , "authenticationConverter cannot be null" );
276- 		this .authenticationConverter  =  authenticationConverter ;
313+ 		this .getAuthenticationFilter (). setAuthenticationConverter ( authenticationConverter ) ;
277314		return  this ;
278315	}
279316
@@ -283,11 +320,13 @@ public OneTimeTokenLoginConfigurer<H> authenticationConverter(AuthenticationConv
283320	 * {@link SimpleUrlAuthenticationFailureHandler} 
284321	 * @param authenticationFailureHandler the {@link AuthenticationFailureHandler} to use 
285322	 * when authentication fails. 
323+ 	 * @deprecated Use {@link #failureHandler(AuthenticationFailureHandler)} instead 
286324	 */ 
325+ 	@ Deprecated (since  = "6.5" )
287326	public  OneTimeTokenLoginConfigurer <H > authenticationFailureHandler (
288327			AuthenticationFailureHandler  authenticationFailureHandler ) {
289328		Assert .notNull (authenticationFailureHandler , "authenticationFailureHandler cannot be null" );
290- 		this . authenticationFailureHandler  =  authenticationFailureHandler ;
329+ 		super . failureHandler ( authenticationFailureHandler ) ;
291330		return  this ;
292331	}
293332
@@ -296,22 +335,16 @@ public OneTimeTokenLoginConfigurer<H> authenticationFailureHandler(
296335	 * {@link SavedRequestAwareAuthenticationSuccessHandler} with no additional properties 
297336	 * set. 
298337	 * @param authenticationSuccessHandler the {@link AuthenticationSuccessHandler}. 
338+ 	 * @deprecated Use {@link #successHandler(AuthenticationSuccessHandler)} instead 
299339	 */ 
340+ 	@ Deprecated (since  = "6.5" )
300341	public  OneTimeTokenLoginConfigurer <H > authenticationSuccessHandler (
301342			AuthenticationSuccessHandler  authenticationSuccessHandler ) {
302343		Assert .notNull (authenticationSuccessHandler , "authenticationSuccessHandler cannot be null" );
303- 		this . authenticationSuccessHandler  =  authenticationSuccessHandler ;
344+ 		super . successHandler ( authenticationSuccessHandler ) ;
304345		return  this ;
305346	}
306347
307- 	private  AuthenticationFailureHandler  getAuthenticationFailureHandler () {
308- 		if  (this .authenticationFailureHandler  != null ) {
309- 			return  this .authenticationFailureHandler ;
310- 		}
311- 		this .authenticationFailureHandler  = new  SimpleUrlAuthenticationFailureHandler ("/login?error" );
312- 		return  this .authenticationFailureHandler ;
313- 	}
314- 
315348	/** 
316349	 * Use this {@link GenerateOneTimeTokenRequestResolver} when resolving 
317350	 * {@link GenerateOneTimeTokenRequest} from {@link HttpServletRequest}. By default, 
0 commit comments