example ejemplo spring oauth spring-security

ejemplo - spring security oauth2 spring boot



Spring Security OAuth2 Resource Server siempre devuelve token no vĂ¡lido (3)

Estoy intentando que un servidor OAuth2 en memoria básico se ejecute utilizando las bibliotecas Spring. He estado siguiendo el ejemplo brillante .

Actualmente, he configurado el servidor y casi todo funciona, sin embargo, no puedo acceder a mi recurso restringido desde el servidor de recursos.

Mi flujo de trabajo de prueba:

  1. Acceda al URI autorizado de oauth para iniciar el flujo de OAuth2: http://localhost:8080/server/oauth/authorize?response_type=code&client_id=client

  2. Redirigir a la página de inicio de sesión: http://localhost:8080/server/login

  3. Maneje la aprobación y redirija a mi página de redirección configurada con un parámetro de código: http://localhost:8080/client?code=HMJO4K

  4. Construya una solicitud GET usando la Autenticación Básica usando el ID y el secreto del cliente junto con el tipo y el código de la concesión: http://localhost:8080/server/oauth/token?grant_type=authorization_code&code=HMJO4K

  5. Recibe un access_token y actualiza el objeto token a cambio

    {access_token: "f853bcc5-7801-42d3-9cb8-303fc67b0453" token_type: "bearer" refresh_token: "57100377-dea9-4df0-adab-62e33f2a1b49" expires_in: 299 alcance: 299 en el alcance: "

  6. Intente acceder a un recurso restringido utilizando access_token: http://localhost:8080/server/me?access_token=f853bcc5-7801-42d3-9cb8-303fc67b0453

  7. Recibir una respuesta de token no válida

    {error: "invalid_token" error_description: "Token de acceso no válido: f853bcc5-7801-42d3-9cb8-303fc67b0453"}

  8. Publique el token uri nuevamente para actualizar el token: http://localhost:8080/server/oauth/token?grant_type=refresh_token&refresh_token=57100377-dea9-4df0-adab-62e33f2a1b49

  9. Recibe un nuevo token

    {access_token: "ed104994-899c-4cd9-8860-43d5689a9420" token_type: "bearer" refresh_token: "57100377-dea9-4df0-adab-62e33f2a1b49" expires_in: 300 scope: "read write"}

Realmente no estoy seguro de lo que estoy haciendo mal, pero parece que todo lo que no sea acceder al uri restringido está funcionando. Aquí está mi configuración:

@Configuration public class Oauth2ServerConfiguration { private static final String SERVER_RESOURCE_ID = "oauth2-server"; @Configuration @EnableResourceServer protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @Override public void configure(ResourceServerSecurityConfigurer resources) { resources.resourceId(SERVER_RESOURCE_ID); } @Override public void configure(HttpSecurity http) throws Exception { http .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .and().requestMatchers() .antMatchers("/me") .and().authorizeRequests() .antMatchers("/me").access("#oauth2.clientHasRole(''ROLE_CLIENT'')") ; } } @Configuration @EnableAuthorizationServer protected static class AuthotizationServerConfiguration extends AuthorizationServerConfigurerAdapter { @Autowired private ClientDetailsService clientDetailsService; @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("client") .resourceIds(SERVER_RESOURCE_ID) .secret("secret") .authorizedGrantTypes("authorization_code", "refresh_token") .authorities("ROLE_CLIENT") .scopes("read","write") .redirectUris("http://localhost:8080/client") .accessTokenValiditySeconds(300) .autoApprove(true) ; } @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .tokenStore(tokenStore()) .userApprovalHandler(userApprovalHandler()) .authenticationManager(authenticationManager) ; } @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.realm("oauth"); } @Bean public ApprovalStore approvalStore() throws Exception { TokenApprovalStore store = new TokenApprovalStore(); store.setTokenStore(tokenStore()); return store; } @Bean public UserApprovalHandler userApprovalHandler() throws Exception { TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler(); handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService)); handler.setClientDetailsService(clientDetailsService); handler.setTokenStore(tokenStore()); return handler; } } }

¿Hay algo que me falta o me estoy acercando a esto incorrectamente? Cualquier ayuda sería muy apreciada.


El problema terminó siendo que el servidor de recursos y el servidor de autorizaciones no obtenían la misma referencia de almacén de token. No estoy seguro de cómo el cableado no funcionaba correctamente, pero usar un objeto fijo en la clase de configuración funcionó a la perfección. En última instancia, me moveré a una tienda de tokens respaldada por persistencia, que probablemente no habría tenido ningún problema.

¡Gracias a @OhadR por la respuesta y la ayuda!

En última instancia, simplifiqué la configuración, pasé por el mismo flujo de trabajo y funcionó

@Configuration public class Oauth2ServerConfiguration { private static final String SERVER_RESOURCE_ID = "oauth2-server"; private static InMemoryTokenStore tokenStore = new InMemoryTokenStore(); @Configuration @EnableResourceServer protected static class ResourceServer extends ResourceServerConfigurerAdapter { @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.tokenStore(tokenStore).resourceId(SERVER_RESOURCE_ID); } @Override public void configure(HttpSecurity http) throws Exception { http.requestMatchers().antMatchers("/me").and().authorizeRequests().antMatchers("/me").access("#oauth2.hasScope(''read'')"); } } @Configuration @EnableAuthorizationServer protected static class AuthConfig extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore).approvalStoreDisabled(); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("client") .authorizedGrantTypes("authorization_code","refresh_token") .authorities("ROLE_CLIENT") .scopes("read") .resourceIds(SERVER_RESOURCE_ID) .secret("secret") ; } } }

Cualquiera que se tope con este post, recomiendo mirar más las pruebas de unidad, por ejemplo, en lugar del ejemplo completo de sparklr / tonr, ya que tiene una gran cantidad de configuraciones adicionales que no son necesariamente necesarias para comenzar.


Esto funciona para mí:

@Configuration public class Oauth2ServerConfiguration { private static final String SERVER_RESOURCE_ID = "oauth2-server"; @Autowired private TokenStore tokenStore; @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); } @Configuration @EnableResourceServer protected static class ResourceServer extends ResourceServerConfigurerAdapter { @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.tokenStore(tokenStore).resourceId(SERVER_RESOURCE_ID); } @Override public void configure(HttpSecurity http) throws Exception { // ... Not important at this stage } } @Configuration @EnableAuthorizationServer protected static class AuthConfig extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore).approvalStoreDisabled(); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { //... Not important at this stage } } }


Su paso # 6 es incorrecto: el token de acceso no debe enviarse en la URL, ya que es vulnerable de esta manera. rathen than GET, usa POST.

Además, no entiendo su paso # 1: ¿por qué llama / auth / autoriza? debe hacerse de forma implícita cuando intenta obtener un recurso protegido. Quiero decir, tu flujo debe comenzar con:

Intente acceder a un recurso restringido utilizando access_token: http://localhost:8080/server/me

Luego, la negociación comenzará "detrás de escena": una redirección a "/ oauth / authorize", etc.

Además, en el paso # 8, tenga en cuenta que no está solicitando "otro token de acceso", sino que es una solicitud de "token de actualización". Como si su token de acceso haya caducado.

Nota : ¡El proveedor de identidad y el servidor de recursos deben compartir tokenStore! Lea aquí: Spring Security OAuth2 servidor de recursos puros

HTH