Spring Boot OAuth 2-истекающий срок действия токенов обновления при смене пароля



Я создал API, используя Spring Boot/OAuth. В настоящее время установлено так, что маркеры доступа действительны в течение 30 дней, и их сроком на 5 лет. Было предложено, чтобы OAuth работал таким образом, чтобы один refresh_token можно было использовать снова и снова. То, что нам также нужно сделать, это реализовать какой-то способ истечения срока действия токенов обновления, когда пользователь меняет свой пароль, это то, с чем я борюсь, поскольку мы не используем хранилище токенов, поскольку мы используем JWTs, поэтому нет необходимости хранить токены, и даже когда мы хранили их в базе данных, мы регулярно получали ошибки "недопустимый токен обновления", поэтому удалили хранилище токенов.



Мой вопрос заключается в том, как вы обрабатываете истекающие токены обновления, скажем, когда пользователь меняет свой пароль (как предлагает OAuth).



Мой клиент специально запросил, чтобы возвращаемый refresh_token был долговечным, но я обеспокоен тем, что маркер обновления с длительным сроком службы не очень безопасен, как будто кто-то получает доступ к этому маркеру, они могут получить доступ к пользователям счет до тех пор, пока этот токен не истечет естественным образом. Лично я бы предпочел установить более короткий срок действия на refresh_tokens, скажем, 45 дней, заставляя клиента хранить новый refresh_token каждые 45 дней, по крайней мере.



Вот некоторые из моих классов конфигурации для безопасности, чтобы показать, как у меня сейчас все настроено;



@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
private Environment env;

@Autowired
private CustomUserDetailsService userDetailsService;

@Autowired
private AccountAuthenticationProvider accountAuthenticationProvider;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(accountAuthenticationProvider);
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}

@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
final JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
jwtAccessTokenConverter.setSigningKey(env.getProperty("jwt.secret"));
return jwtAccessTokenConverter;
}

}



@Configuration
public class OAuth2ServerConfiguration {

private static final String RESOURCE_ID = "myapi";

@Autowired
DataSource dataSource;

@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}

@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

@Autowired
TokenStore tokenStore;

@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources
.resourceId(RESOURCE_ID)
.tokenStore(tokenStore);
}

@Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/oauth/**", "/view/**").permitAll()
.anyRequest().authenticated();
}
}

@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;

@Autowired
private DataSource dataSource;

@Autowired
private TokenStore tokenStore;

@Autowired
private CustomUserDetailsService userDetailsService;

@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
//.tokenStore(tokenStore)
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService)
.accessTokenConverter(jwtAccessTokenConverter);
}

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.jdbc(dataSource);
}
}

}
638   1  

1 ответ:

Отзыв токена не поддерживается, если используется JWT. Если вы хотите, чтобы эта функциональность была реализована, вы должны рассмотреть возможность использования JdbcTokenStore вместо этого.

@Bean
public TokenStore tokenStore() { 
    return new JdbcTokenStore(dataSource()); 
}

@Bean
public DataSource dataSource() { 
    DriverManagerDataSource jdbcdataSource =  new DriverManagerDataSource();
    jdbcdataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
    jdbcdataSource.setUrl(env.getProperty("jdbc.url"));//connection String
    jdbcdataSource.setUsername(env.getProperty("jdbc.user"));
    jdbcdataSource.setPassword(env.getProperty("jdbc.pass")); 
    return dataSource;
}

Когда пользователь меняет пароль, вы должны вызвать API revokeToken

@Resource(name="tokenServices")
ConsumerTokenServices tokenServices;

@RequestMapping(method = RequestMethod.POST, value = "/tokens/revoke/{tokenId:.*}")
@ResponseBody
public String revokeToken(@PathVariable String tokenId) {
    tokenServices.revokeToken(tokenId);
    return tokenId;
}

JDBCTokenStore также предоставляет метод, с помощью которого можно аннулировать маркер обновления

@RequestMapping(method = RequestMethod.POST, value = "/tokens/revokeRefreshToken/{tokenId:.*}")
@ResponseBody
public String revokeRefreshToken(@PathVariable String tokenId) {
    if (tokenStore instanceof JdbcTokenStore){
        ((JdbcTokenStore) tokenStore).removeRefreshToken(tokenId);
    }
    return tokenId;
}

Comments

    Ничего не найдено.