spring-projects / spring-projects/spring-security

Consider a `OneTimeToken` integration with Spring MVC

Open
#15,623 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

in: web type: enhancement
Dominant language
Java
Stars
9.6k
Forks
6.3k
Avg merge
2d 11h
Merged PRs (30d)
52

Description

This would simplify the resolution of an OneTimeToken. Currently, a OneTimeTokenService should be injected and a OneTimeTokenAuthenticationRequest must be created manually.

@GetMapping("/ott/generate")
public String generateOtt(Authentication authentication, Model model) {
	OneTimeTokenAuthenticationRequest request = new OneTimeTokenAuthenticationRequest(authentication.getName());
	OneTimeToken oneTimeToken = this.oneTimeTokenService.generate(request);
	model.addAttribute("oneTimeToken", oneTimeToken);
	return "ott-generate";
}

For example, authenticated users might want to generate a One-Time Token to log in from another device, let's say a TV, where it is very unlikely that they want to type their long passwords. This is also great to avoid typing your password into a device that might be public, like a hotel TV or a cybercafe computer.

One idea is to provide a HandlerMethodArgumentResolver that resolves the OneTimeToken parameter.

class OneTimeTokenRequestArgumentResolver implements HandlerMethodArgumentResolver {

	private final SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder.getContextHolderStrategy();

	private final AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();

	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		return OneTimeToken.class.equals(parameter.getParameterType());
	}

	@Override
	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
		OneTimeTokenService oneTimeTokenService = this.applicationContext.getBean(OneTimeTokenService.class);
		}
		Authentication authentication = this.securityContextHolderStrategy.getContext().getAuthentication();
		if (this.authenticationTrustResolver.isAnonymous(authentication)) {
			return null;
		}
		OneTimeTokenAuthenticationRequest request = new OneTimeTokenAuthenticationRequest(authentication.getName());
		return oneTimeTokenService.generate(request);
	}

}
@GetMapping("/ott/generate")
public String generateOtt(OneTimeToken oneTimeToken, Model model) {
	model.addAttribute("oneTimeToken", oneTimeToken);
	return "ott-generate";
}

We could also provide an additional annotation to allow customizing which OneTimeTokenService to use if the application has more than one.

@GetMapping("/ott/generate")
public String generateOtt(@GenerateOneTimeToken(oneTimeTokenServiceBeanName = "deviceOneTimeTokenService") OneTimeToken oneTimeToken, Model model) {
	model.addAttribute("oneTimeToken", oneTimeToken);
	return "ott-generate";
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the OneTimeTokenService flow and Spring MVC's HandlerMethodArgumentResolver entry point, using the proposed OneTimeTokenAuthenticationRequest examples. Define the controller-parameter API, anonymous-user behavior, and how multiple services are selected; done should include coverage for these behaviors.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
api, backend, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.