Skip to content

Commit dfbe909

Browse files
Additional changes based on Rob's feedback:
- Renamed OneTimeTokenAuthenticationRequestSuccessHandler to GeneratedOneTimeTokenSuccessHandler because there is no authentication request, it is a token generation request. - Renamed all classes containing AuthenticationRequest to Generate, for the same reasons above - Removed OneTimeTokenSender. While this interface seems reasonable, it is more useful to use the GeneratedOneTimeTokenSuccessHandler for sending the token because the API has access to more parameters (request, response) than just the OneTimeToken. - Updated the docs based on the changes
1 parent e5c338f commit dfbe909

File tree

18 files changed

+201
-306
lines changed

18 files changed

+201
-306
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterOrderRegistration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import org.springframework.security.web.authentication.AuthenticationFilter;
3131
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
3232
import org.springframework.security.web.authentication.logout.LogoutFilter;
33-
import org.springframework.security.web.authentication.ott.OneTimeTokenAuthenticationRequestFilter;
33+
import org.springframework.security.web.authentication.ott.OneTimeTokenGenerateFilter;
3434
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
3535
import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
3636
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter;
@@ -90,7 +90,7 @@ final class FilterOrderRegistration {
9090
this.filterToOrder.put(
9191
"org.springframework.security.saml2.provider.service.web.Saml2WebSsoAuthenticationRequestFilter",
9292
order.next());
93-
put(OneTimeTokenAuthenticationRequestFilter.class, order.next());
93+
put(OneTimeTokenGenerateFilter.class, order.next());
9494
put(X509AuthenticationFilter.class, order.next());
9595
put(AbstractPreAuthenticatedProcessingFilter.class, order.next());
9696
this.filterToOrder.put("org.springframework.security.cas.web.CasAuthenticationFilter", order.next());

config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3000,10 +3000,6 @@ public HttpSecurity oauth2ResourceServer(
30003000
* }
30013001
* }
30023002
* </pre>
3003-
*
3004-
* Note that a
3005-
* {@link org.springframework.security.authentication.ott.OneTimeTokenSender} is
3006-
* required to enable this support.
30073003
* @param oneTimeTokenLoginConfigurerCustomizer the {@link Customizer} to provide more
30083004
* options for the {@link OneTimeTokenLoginConfigurer}
30093005
* @return the {@link HttpSecurity} for further customizations

config/src/main/java/org/springframework/security/config/annotation/web/configurers/ott/OneTimeTokenLoginConfigurer.java

Lines changed: 56 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
import org.springframework.security.authentication.ott.InMemoryOneTimeTokenService;
3232
import org.springframework.security.authentication.ott.OneTimeToken;
3333
import org.springframework.security.authentication.ott.OneTimeTokenAuthenticationProvider;
34-
import org.springframework.security.authentication.ott.OneTimeTokenSender;
34+
import org.springframework.security.authentication.ott.OneTimeTokenGenerateRequest;
3535
import org.springframework.security.authentication.ott.OneTimeTokenService;
3636
import org.springframework.security.config.Customizer;
3737
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
@@ -44,12 +44,12 @@
4444
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
4545
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
4646
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
47+
import org.springframework.security.web.authentication.ott.GeneratedOneTimeTokenSuccessHandler;
4748
import org.springframework.security.web.authentication.ott.OneTimeTokenAuthenticationConverter;
48-
import org.springframework.security.web.authentication.ott.OneTimeTokenAuthenticationRequestFilter;
49-
import org.springframework.security.web.authentication.ott.OneTimeTokenAuthenticationRequestResolver;
50-
import org.springframework.security.web.authentication.ott.OneTimeTokenAuthenticationRequestSuccessHandler;
51-
import org.springframework.security.web.authentication.ott.RedirectOneTimeTokenAuthenticationRequestSuccessHandler;
52-
import org.springframework.security.web.authentication.ott.RequestParameterOneTimeTokenAuthenticationRequestResolver;
49+
import org.springframework.security.web.authentication.ott.OneTimeTokenGenerateFilter;
50+
import org.springframework.security.web.authentication.ott.OneTimeTokenGenerateRequestResolver;
51+
import org.springframework.security.web.authentication.ott.RedirectGeneratedOneTimeTokenSuccessHandler;
52+
import org.springframework.security.web.authentication.ott.RequestParameterOneTimeTokenGenerateRequestResolver;
5353
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
5454
import org.springframework.security.web.authentication.ui.DefaultOneTimeTokenSubmitPageGeneratingFilter;
5555
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
@@ -63,6 +63,9 @@
6363
public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>>
6464
extends AbstractHttpConfigurer<OneTimeTokenLoginConfigurer<H>, H> {
6565

66+
private static final RedirectGeneratedOneTimeTokenSuccessHandler DEFAULT_GENERATED_OTT_SUCCESS_HANDLER = new RedirectGeneratedOneTimeTokenSuccessHandler(
67+
"/login/ott");
68+
6669
private final Log logger = LogFactory.getLog(getClass());
6770

6871
private final ApplicationContext context;
@@ -75,22 +78,19 @@ public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>>
7578

7679
private AuthenticationSuccessHandler authenticationSuccessHandler = new SavedRequestAwareAuthenticationSuccessHandler();
7780

78-
private OneTimeTokenSender oneTimeTokenSender;
79-
8081
private String submitPageUrl = "/login/ott";
8182

8283
private boolean submitPageEnabled = true;
8384

8485
private String loginProcessingUrl = "/login/ott";
8586

86-
private String authenticationRequestUrl = "/ott/authenticate";
87+
private String generateUrl = "/ott/generate";
8788

88-
private OneTimeTokenAuthenticationRequestSuccessHandler authenticationRequestSuccessHandler = new RedirectOneTimeTokenAuthenticationRequestSuccessHandler(
89-
"/login/ott");
89+
private GeneratedOneTimeTokenSuccessHandler generatedOneTimeTokenSuccessHandler = DEFAULT_GENERATED_OTT_SUCCESS_HANDLER;
9090

9191
private AuthenticationProvider authenticationProvider;
9292

93-
private OneTimeTokenAuthenticationRequestResolver authenticationRequestResolver = new RequestParameterOneTimeTokenAuthenticationRequestResolver();
93+
private OneTimeTokenGenerateRequestResolver oneTimeTokenGenerateRequestResolver = new RequestParameterOneTimeTokenGenerateRequestResolver();
9494

9595
public OneTimeTokenLoginConfigurer(ApplicationContext context) {
9696
this.context = context;
@@ -110,7 +110,7 @@ private void configureDefaultLoginPage(H http) {
110110
return;
111111
}
112112
loginPageGeneratingFilter.setOneTimeTokenEnabled(true);
113-
loginPageGeneratingFilter.setOneTimeTokenAuthenticationRequestUrl(this.authenticationRequestUrl);
113+
loginPageGeneratingFilter.setOneTimeTokenAuthenticationRequestUrl(this.generateUrl);
114114
if (this.authenticationFailureHandler == null
115115
&& StringUtils.hasText(loginPageGeneratingFilter.getLoginPageUrl())) {
116116
this.authenticationFailureHandler = new SimpleUrlAuthenticationFailureHandler(
@@ -121,7 +121,7 @@ private void configureDefaultLoginPage(H http) {
121121
@Override
122122
public void configure(H http) {
123123
configureSubmitPage(http);
124-
configureOttAuthenticationRequestFilter(http);
124+
configureOttGenerateFilter(http);
125125
configureOttAuthenticationFilter(http);
126126
}
127127

@@ -144,13 +144,24 @@ private SecurityContextRepository getSecurityContextRepository(H http) {
144144
return new HttpSessionSecurityContextRepository();
145145
}
146146

147-
private void configureOttAuthenticationRequestFilter(H http) {
148-
OneTimeTokenAuthenticationRequestFilter authenticationRequestFilter = new OneTimeTokenAuthenticationRequestFilter(
149-
getOneTimeTokenService(http), getOneTimeTokenSender(http));
150-
authenticationRequestFilter.setAuthenticationRequestResolver(this.authenticationRequestResolver);
151-
authenticationRequestFilter.setAuthenticationRequestSuccessHandler(this.authenticationRequestSuccessHandler);
152-
authenticationRequestFilter.setRequestMatcher(antMatcher(HttpMethod.POST, this.authenticationRequestUrl));
153-
http.addFilter(postProcess(authenticationRequestFilter));
147+
private void configureOttGenerateFilter(H http) {
148+
OneTimeTokenGenerateFilter generateFilter = new OneTimeTokenGenerateFilter(getOneTimeTokenService(http));
149+
generateFilter.setOneTimeTokenGenerateRequestResolver(this.oneTimeTokenGenerateRequestResolver);
150+
generateFilter.setGeneratedOneTimeTokenSuccessHandler(getGeneratedOneTimeTokenSuccessHandler());
151+
generateFilter.setRequestMatcher(antMatcher(HttpMethod.POST, this.generateUrl));
152+
http.addFilter(postProcess(generateFilter));
153+
}
154+
155+
private GeneratedOneTimeTokenSuccessHandler getGeneratedOneTimeTokenSuccessHandler() {
156+
if (this.generatedOneTimeTokenSuccessHandler == DEFAULT_GENERATED_OTT_SUCCESS_HANDLER) {
157+
this.logger
158+
.debug("""
159+
Using RedirectGeneratedOneTimeTokenSuccessHandler as the default GeneratedOneTimeTokenSuccessHandler.
160+
Note that this implementation does not send the one-time token to the user, therefore, consider
161+
providing your own implementation.
162+
""");
163+
}
164+
return this.generatedOneTimeTokenSuccessHandler;
154165
}
155166

156167
private void configureSubmitPage(H http) {
@@ -175,15 +186,15 @@ private AuthenticationProvider getAuthenticationProvider(H http) {
175186
}
176187

177188
/**
178-
* Specifies the {@link OneTimeTokenAuthenticationRequestResolver} to use to resolve a
179-
* {@link org.springframework.security.authentication.ott.OneTimeTokenAuthenticationRequest}.
180-
* Defaults to {@link RequestParameterOneTimeTokenAuthenticationRequestResolver}
181-
* @param authenticationRequestResolver
189+
* Specifies the {@link OneTimeTokenGenerateRequestResolver} to use to resolve a
190+
* {@link OneTimeTokenGenerateRequest}. Defaults to
191+
* {@link RequestParameterOneTimeTokenGenerateRequestResolver}
192+
* @param oneTimeTokenGenerateRequestResolver
182193
*/
183-
public OneTimeTokenLoginConfigurer<H> authenticationRequestResolver(
184-
OneTimeTokenAuthenticationRequestResolver authenticationRequestResolver) {
185-
Assert.notNull(authenticationRequestResolver, "authenticationRequestResolver cannot be null");
186-
this.authenticationRequestResolver = authenticationRequestResolver;
194+
public OneTimeTokenLoginConfigurer<H> oneTimeTokenGenerationRequestResolver(
195+
OneTimeTokenGenerateRequestResolver oneTimeTokenGenerateRequestResolver) {
196+
Assert.notNull(oneTimeTokenGenerateRequestResolver, "oneTimeTokenGenerationRequestResolver cannot be null");
197+
this.oneTimeTokenGenerateRequestResolver = oneTimeTokenGenerateRequestResolver;
187198
return this;
188199
}
189200

@@ -198,26 +209,28 @@ public OneTimeTokenLoginConfigurer<H> authenticationProvider(AuthenticationProvi
198209
}
199210

200211
/**
201-
* Specifies the URL that a One-Time Token authentication request will be processed.
202-
* Defaults to {@code POST /ott/authenticate}.
203-
* @param authenticationRequestUrl
212+
* Specifies the URL that a One-Time Token generate request will be processed.
213+
* Defaults to {@code POST /ott/generate}.
214+
* @param generateUrl
204215
*/
205-
public OneTimeTokenLoginConfigurer<H> authenticationRequestUrl(String authenticationRequestUrl) {
206-
Assert.hasText(authenticationRequestUrl, "authenticationRequestUrl cannot be null or empty");
207-
this.authenticationRequestUrl = authenticationRequestUrl;
216+
public OneTimeTokenLoginConfigurer<H> generateUrl(String generateUrl) {
217+
Assert.hasText(generateUrl, "generateUrl cannot be null or empty");
218+
this.generateUrl = generateUrl;
208219
return this;
209220
}
210221

211222
/**
212-
* Specifies strategy to be used for successful one-time token authentication
213-
* requests. By default, a redirect will be performed to {@code POST /login/ott} using
214-
* the {@link RedirectOneTimeTokenAuthenticationRequestSuccessHandler}.
215-
* @param authenticationRequestSuccessHandler
223+
* Specifies strategy to be used for successful generated one-time tokens. By default,
224+
* a redirect will be performed to {@code POST /login/ott} using the
225+
* {@link RedirectGeneratedOneTimeTokenSuccessHandler}. It is often needed to provide
226+
* your own implementation of this interface so the one-time token is also delivered
227+
* to the user.
228+
* @param generatedOneTimeTokenSuccessHandler
216229
*/
217-
public OneTimeTokenLoginConfigurer<H> authenticationRequestSuccessHandler(
218-
OneTimeTokenAuthenticationRequestSuccessHandler authenticationRequestSuccessHandler) {
219-
Assert.notNull(authenticationRequestSuccessHandler, "authenticationRequestSuccessHandler cannot be null");
220-
this.authenticationRequestSuccessHandler = authenticationRequestSuccessHandler;
230+
public OneTimeTokenLoginConfigurer<H> generatedOneTimeTokenSuccessHandler(
231+
GeneratedOneTimeTokenSuccessHandler generatedOneTimeTokenSuccessHandler) {
232+
Assert.notNull(generatedOneTimeTokenSuccessHandler, "generatedOneTimeTokenSuccessHandler cannot be null");
233+
this.generatedOneTimeTokenSuccessHandler = generatedOneTimeTokenSuccessHandler;
221234
return this;
222235
}
223236

@@ -257,17 +270,6 @@ public OneTimeTokenLoginConfigurer<H> submitPageUrl(String submitPageUrl) {
257270
return this;
258271
}
259272

260-
/**
261-
* Specifies the {@link OneTimeTokenSender} to send the generated {@link OneTimeToken}
262-
* to the user
263-
* @param oneTimeTokenSender
264-
*/
265-
public OneTimeTokenLoginConfigurer<H> oneTimeTokenSender(OneTimeTokenSender oneTimeTokenSender) {
266-
Assert.notNull(oneTimeTokenSender, "oneTimeTokenSender cannot be null");
267-
this.oneTimeTokenSender = oneTimeTokenSender;
268-
return this;
269-
}
270-
271273
/**
272274
* Configures the {@link OneTimeTokenService} used to generate and consume
273275
* {@link OneTimeToken}
@@ -341,19 +343,6 @@ private OneTimeTokenService getOneTimeTokenService(H http) {
341343
return this.oneTimeTokenService;
342344
}
343345

344-
private OneTimeTokenSender getOneTimeTokenSender(H http) {
345-
if (this.oneTimeTokenSender != null) {
346-
return this.oneTimeTokenSender;
347-
}
348-
OneTimeTokenSender bean = getBeanOrNull(http, OneTimeTokenSender.class);
349-
if (bean == null) {
350-
throw new IllegalStateException("A OneTimeTokenSender is required for oneTimeTokenLogin(). "
351-
+ "Please define a bean or pass an instance to the DSL.");
352-
}
353-
this.oneTimeTokenSender = bean;
354-
return this.oneTimeTokenSender;
355-
}
356-
357346
private <C> C getBeanOrNull(H http, Class<C> clazz) {
358347
ApplicationContext context = http.getSharedObject(ApplicationContext.class);
359348
if (context == null) {

0 commit comments

Comments
 (0)