spring-authorization-server icon indicating copy to clipboard operation
spring-authorization-server copied to clipboard

How-to: Remember-me with a Single Page Application

Open clgraf opened this issue 4 years ago • 3 comments

I’m posting this issue based on the excellent new how-to's issues….

I’m struggling with the “remember-me” feature (SPA context) and I don’t know if such topic is appropriate to the Spring Authorization Server.

I tried to setup the remember-me feature in the SecurityFilterChain. The cookie is created in the browser and the authentication is done later in the server, but the login page (a custom one) is always showed, instead of just redirect the authorization to the client.

  1. Is the remember-me feature appropriate with OAuth2 in a SPA with PKCE?
  2. Does Spring Authorization Server supports the remember-me feature? Is it possible?
  3. Is it a good idea to use refresh tokens to setup the remember-me? (with a longer expiricy and conditional to a checkbox on the login page)
  4. Is it possible to have a how-to about the remember-me feature?

clgraf avatar Dec 28 '21 13:12 clgraf

Hi @clgraf!

Thanks for the questions. However, I'm going to go ahead and edit this to be a how-to guide request, relating to #4 above. As far as your other questions, I think they would be better suited to Stack Overflow. We prefer to use GitHub issues only for bugs and enhancements (in this case, how-to guides are enhancements for the docs). Feel free to update this issue with a link to the re-posted question(s) (so that other people can find it), and I'll be happy to take a look.

sjohnr avatar Jan 03 '22 19:01 sjohnr

Related #499

sjohnr avatar Jan 03 '22 19:01 sjohnr

I have a Idea.

To implement the “remember-me” feature , need to modify oauth2authorizationendpointconfigurer.class, put oauth2authorizationendpointfilter after remembermeauthenticationfilter.

Step1: modify OAuth2AuthorizationEndpointConfigurer.class's code of spring-authorization-server

// builder.addFilterBefore(postProcess(authorizationEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);

builder.addFilterBefore(postProcess(authorizationEndpointFilter), ExceptionTranslationFilter.class);

Step2: Modify the default-authorizationserver's code in samples and test it

  • Add rememberMe in AuthorizationServerConfig.class
public class AuthorizationServerConfig {

	@Bean
	@Order(Ordered.HIGHEST_PRECEDENCE)
	public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http, UserDetailsService users) throws Exception {

		OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
		// @formatter:off
		http
			.exceptionHandling(exceptions ->
				exceptions.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
			);
		http.rememberMe((rememberMe) -> {
			rememberMe.userDetailsService(users);
			rememberMe.key("123");
		});
		// @formatter:on
		return http.build();
	}
  • Add rememberMe in DefaultSecurityConfig.class
public class DefaultSecurityConfig {

	// @formatter:off
	@Bean
	SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http, UserDetailsService users) throws Exception {
		http
			.authorizeRequests(authorizeRequests ->
				authorizeRequests.anyRequest().authenticated()
			)
			.formLogin(withDefaults());

		http.rememberMe((rememberMe) -> {
			rememberMe.userDetailsService(users);
			rememberMe.key("123");
		});
		return http.build();
	}

Step3: Test

  • run application

    • run default-authorizationserver
    • run messages-resource
    • run messages-client
  • http://127.0.0.1:8080

fanhualei avatar Jun 09 '22 14:06 fanhualei

@clgraf User Authentication is not a concern for Spring Authorization Server as its sole focus is OAuth2 Authorization. Spring Security is where you would configure User Authentication with whatever underlying mechanism you require.

If you look at the default-authorizationserver sample, you can configure the Remember-Me feature in the DefaultSecurityConfig, which ultimately is the Spring Security filter chain.

Here is a link to a Remember-Me sample you can review further.

I'm going to close this issue based on the provided explanation.

jgrandja avatar Dec 21 '22 16:12 jgrandja

For what it's worth, we may be able to override the order from configuration instead of modifying the library, perhaps adding it after the LogoutFilter,

public class AuthorizationServerConfig {

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http, RememberMeAuthenticationFilter rememberMe) {
        http.
            ...
            .addFilterAfter(rememberMe, LogoutFilter.class)
            ....
        return http.build(); 
    }  

    @Bean
    public RememberMeAuthenticationFilter rememberMeAuthenticationFilter(AuthenticationManager authenticationManager, RememberMeServices rememberMeServices) throws Exception {
            return new RememberMeAuthenticationFilter(authenticationManager, rememberMeServices);
    }

countrogue avatar May 23 '23 05:05 countrogue