OAuth 2.0 con SpringBoot

COMPARTIR EN REDES SOCIALES

En esta entrada vamos a integrar OAuth 2.0 con SpringBoot de forma que podremos proteger nuestras APIS mediante JSON Web Tokens. OAuth 2.0 se compone de varios actores siendo los más importantes:

  • Authorization Server. Será el encargado de autenticar a los usuarios, así como de proporcionar los tokens de acceso a las APIS.
  • Resource Server. Será el servidor donde tendremos nuestras APIS expuestas y protegidas mediante OAuth.

La idea es muy sencilla, crearemos un proyecto en SpringBoot que nos servirá de Servidor de Autorizaciones y otro para el Resource Server.

El flujo que implementaremos será el flujo «authorization_code», que podemos apreciar en el siguiente diagrama:

Flujo Authorization Code en OAuth 2.0 con Spring Boot
Flujo Authorization Code en OAuth 2.0 con Spring Boot

La idea consiste en:

  1. La aplicación del usuario realiza una petición de autorización el servicio de autorización de OAuth.
  2. Este le devuelve el formulario de Login.
  3. El usuario introduce su usuario y contraseña.
  4. El servidor de autorizaciones realiza una redirección a la URL de callback y en sus query params se encuentra el code.
  5. La aplicación del usuario intercambia el code por un token de acceso a las APIS con unos scopes determinados.

El Authorization Server o Servidor de Autorizaciones

Las dependencias que necesitaremos de Maven serán:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
	<version>2.5.4</version>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
	<version>2.5.4</version>
</dependency>
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-oauth2-authorization-server</artifactId>
	<version>0.2.3</version>
</dependency>

Veamos el código fuente y luego explicaremos cada uno de los Beans:

La clase AuthorizationServerConfig

package as;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.time.Duration;
import java.util.UUID;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
import org.springframework.security.web.SecurityFilterChain;

import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;

@Configuration
public class AuthorizationServerConfig {
	@Bean
	public RegisteredClientRepository registeredClientRepository() {

		RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString()).clientId("client1")
				.clientSecret("{noop}myClientSecretValue")
				.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
				.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
				.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN).tokenSettings(tokenSettings())
				.redirectUri("http://127.0.0.1:8080/login/oauth2/code/users-client-oidc")
				.redirectUri("http://127.0.0.1:8080/authorized").scope(OidcScopes.OPENID).scope("read")
				// .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
				.build();

		return new InMemoryRegisteredClientRepository(registeredClient);
	}

	@Bean
	public TokenSettings tokenSettings() {
		return TokenSettings.builder()
				.accessTokenTimeToLive(Duration.ofMinutes(60L))
				.build();
	}

	@Bean
	@Order(Ordered.HIGHEST_PRECEDENCE)
	public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
		OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
		return http.formLogin(Customizer.withDefaults()).build();
	}

	@Bean
	public ProviderSettings providerSettings() {
		return ProviderSettings.builder().issuer("http://127.0.0.1:9000").build();
	}

	@Bean
	public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
		return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
	}

	@Bean
	public JWKSource<SecurityContext> jwkSource() throws NoSuchAlgorithmException {
		RSAKey rsaKey = generateRsa();
		JWKSet jwkSet = new JWKSet(rsaKey);
		return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
	}

	private static RSAKey generateRsa() throws NoSuchAlgorithmException {
		KeyPair keyPair = generateRsaKey();
		RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
		RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
		return new RSAKey.Builder(publicKey).privateKey(privateKey).keyID(UUID.randomUUID().toString()).build();
	}

	private static KeyPair generateRsaKey() throws NoSuchAlgorithmException {
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
		keyPairGenerator.initialize(2048);
		return keyPairGenerator.generateKeyPair();
	}

}

En esta clase configuramos nuestro servidor de autorizaciones encargándonos de los siguientes puntos:

  1. Registraremos un cliente al cuál le configuraremos el tipo de flujo de OAuth, que client_id debe tener y que client secret debe tener. También le configuraremos parámetros acerca del token como el tiempo de expiración.
  2. Crearemos las claves RSA necesarias para poder firmar el token que emite nuestro servidor de autorizaciones.

El registro del cliente de OAuth

@Bean
public RegisteredClientRepository registeredClientRepository() {

	RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString()).clientId("client1")
			.clientSecret("{noop}myClientSecretValue")
			.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
			.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
			.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN).tokenSettings(tokenSettings())
			.redirectUri("http://127.0.0.1:8080/login/oauth2/code/users-client-oidc")
			.redirectUri("http://127.0.0.1:8080/authorized").scope(OidcScopes.OPENID).scope("read")
			// .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
			.build();

	return new InMemoryRegisteredClientRepository(registeredClient);
}

Los Beans necesarios para firmar y verificar la firma de nuestro JSON Web Tokens

@Bean
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
	return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}

@Bean
public JWKSource<SecurityContext> jwkSource() throws NoSuchAlgorithmException {
	RSAKey rsaKey = generateRsa();
	JWKSet jwkSet = new JWKSet(rsaKey);
	return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
}

private static RSAKey generateRsa() throws NoSuchAlgorithmException {
	KeyPair keyPair = generateRsaKey();
	RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
	RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
	return new RSAKey.Builder(publicKey).privateKey(privateKey).keyID(UUID.randomUUID().toString()).build();
}

private static KeyPair generateRsaKey() throws NoSuchAlgorithmException {
	KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
	keyPairGenerator.initialize(2048);
	return keyPairGenerator.generateKeyPair();
}

Ahora configuraremos nuestra «security chain» para mostrar el formulario de Login, así como el usuario y password de autenticación.

La clase DefaultSecurityConfig

package as;

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@EnableWebSecurity
public class DefaultSecurityConfig {

    @Bean
    SecurityFilterChain configureSecurityFilterChain(HttpSecurity http) throws Exception {
        
        http
        .authorizeHttpRequests(authorizeRequests -> authorizeRequests.anyRequest().authenticated())
        .formLogin(Customizer.withDefaults());
        
        return http.build();
        
    }
    

    @Bean
    public UserDetailsService users() {
        
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        
        UserDetails user = User.withUsername("user")
                .password(encoder.encode("password"))
                .roles("USER")
                .build();
        
        return new InMemoryUserDetailsManager(user);
        
    }
    
}

En esta clase configuramos como se mostrará nuestro formulario de Login y el usuario y password de autenticación.

Por último solo nos queda configurar nuestro «application.yml»:

server:
  port: 9000

Este será el puerto donde correrá nuestro Tomcat con nuestro Servidor de Autorizaciones de OAuth 2.0

Con todo esto hecho ya podemos lanzar nuestra aplicación y probarla.

Nuestra clase Principal de SpringBoot

package as;
import java.util.Arrays;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

}

Las pruebas del Authorization Server

Lo primero será abrir nuestro navegador web y navegar a la siguiente URL:

http://127.0.0.1:9000/oauth2/authorize?response_type=code&client_id=client1&redirect_uri=http://127.0.0.1:8080/authorized&scope=openid%20read

Esto nos mostrará la siguiente pantalla de Login:

Formulario de Login de OAuth 2.0 por defecto de SpringBoot
Formulario de Login de OAuth 2.0 por defecto de SpringBoot

Introduciremos nuestro usuario y contraseña:

Formulario de Login con usuario y contraseña definidos.

Al darle al botón de «Sign in» OAuth nos redireccionará a la URL de callback, en este caso es:

http://127.0.0.1:8080/authorized?code=5haaKNGhtcVYA6NG2lENVkYJS_5-5c3Tg20TBUXbr5_8YHWrRIM0fuTekqnjCVk70B1kKWpz7TnQqy98f39SpR3x8T7FvAql12a33m5gKhMhyigwDe8Kwc6igdFgVICx

Como podéis apreciar en la URL de callback tenemos el code que nos ha generado OAuth tras la autenticación exitosa.

El último paso será intercambiar nuestro code por un token, el curl sería el siguiente:

curl --location --request POST 'http://localhost:9000/oauth2/token' \
--header 'Origin: http://127.0.0.1:4200' \
--header 'Access-Control-Request-Method: POST' \
--header 'Access-Control-Request-Headers: Content-Type' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cookie: JSESSIONID=5EB881585842F45EE7EA7DA404E383BB' \
--data-urlencode 'client_id=client1' \
--data-urlencode 'client_secret=myClientSecretValue' \
--data-urlencode 'code=5haaKNGhtcVYA6NG2lENVkYJS_5-5c3Tg20TBUXbr5_8YHWrRIM0fuTekqnjCVk70B1kKWpz7TnQqy98f39SpR3x8T7FvAql12a33m5gKhMhyigwDe8Kwc6igdFgVICx' \
--data-urlencode 'redirect_uri=http://127.0.0.1:8080/authorized' \
--data-urlencode 'grant_type=authorization_code'

Podéis utilizar un programa como Postman para realizar la petición:

Petición al servicio de Generación de Tokens de OAuth 2.0
Petición al servicio de Generación de Tokens de OAuth 2.0

La salida de la petición será:

{
    "access_token": "eyJraWQiOiI0NTAyOTA5NS1kODYyLTRkNmMtOWU4ZC0wNzE5ODkxZmI0MjIiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiYXVkIjoiY2xpZW50MSIsIm5iZiI6MTY1NDQ3MjQxNCwic2NvcGUiOlsicmVhZCIsIm9wZW5pZCJdLCJpc3MiOiJodHRwOlwvXC8xMjcuMC4wLjE6OTAwMCIsImV4cCI6MTY1NDQ3NjAxNCwiaWF0IjoxNjU0NDcyNDE0fQ.MqJYSO3D2Duq1Wt92BzsQbaqqoBcq52z8GEkLRGny5Tx3WKFfYV4lJ58ZevM9YOLWEM40lleKcm08o4BCypgL-dBGR_wHVKEH7TycDphuc6jNcSC7Oi_5_8k0V_TaTDoJJXBbod8ycBfTGTg-ze0B1KQoKrnSASKzfZaAIEanT2JlfmBhMLcSyeUaAQ78i2ekr_MhN2wb_QZ5ShSGKUBaXbHxegahwU0A_f2amlz5SkiFmbxnl15nlGZqHIrF9ShBKQHFJvQazzZcFC_F2vdMDS3Npbq-PPawTKr2uq4sIiyhdUR9-LnSnGPu7cUG8SeODxrMu6OlpoE_4oB08Pxhg",
    "refresh_token": "-LxNaIjQsbQTGBqkUR5D35c8WWzsoSYMbQnPjC9EpB_YanblFyVQorTV5XOcm0bclUmeF45mQHBY1QoFPk88wbrusPKL0KfHL3wIqS75TuXe3YqvYoyGepTKQyQIxZND",
    "scope": "read openid",
    "id_token": "eyJraWQiOiI0NTAyOTA5NS1kODYyLTRkNmMtOWU4ZC0wNzE5ODkxZmI0MjIiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiYXVkIjoiY2xpZW50MSIsImF6cCI6ImNsaWVudDEiLCJpc3MiOiJodHRwOlwvXC8xMjcuMC4wLjE6OTAwMCIsImV4cCI6MTY1NDQ3NDIxNCwiaWF0IjoxNjU0NDcyNDE0fQ.UQybdU212M_wWj4qyUlOnBDSO06xTmHNky9TsMBKnjsb9w2_6XcFFIwYwmulsMKqZeBncRrnmdO-Nq2ZLVCkadDtjbYKjd2KYWboESJsC5R1QC_aARzoXfSxwxozU8-rFYUjjr2eAOTMDSGCH4735D4Dx1cCDOBfXhjg1V-Z0bqbexz2DRBgHxppu5Bu5wOoVfoW9kFlV79ZkSJZzqKhaCPy_XQ8OamCPya87ix440QgNrzR4e-EIyCBhhdvl2vtJofL2Q6Pmjgt228FYPBCpdmJw_qBQLHzzEsGMXq4QP2aQu802ASR782NvlPOvqZbAEWAhGSVlwiUbk5E7D4Rzw",
    "token_type": "Bearer",
    "expires_in": 3599
}

Como podéis apreciar tenemos un «access_token», un «refresh_token», un «id_token» e información acerca de los scopes que nos ha dado el servidor, el tipo de token y el tiempo de expiración del mismo en segundos. En este caso el token durará una hora. 3600 segundos.

Con esto ya hemos probado nuestro Servidor de Autorizaciones de OAuth 2.0

Vamos ahora con el Resource Server

El Resource Server o Servidor de Recursos

Veamos el código fuente primero:

Las dependencias necesarias

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
	<version>2.5.4</version>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
	<version>2.5.4</version>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
	<version>2.5.4</version>
</dependency>

La clase ResourceServerConfig

package rs;

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@EnableWebSecurity
public class ResourceServerConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
        	  .mvcMatcher("/articles/**")
          .authorizeRequests()
          .mvcMatchers("/articles/**")
          .access("hasAuthority('SCOPE_read')")
          .and()
          .mvcMatcher("/usuarios/**")
          .authorizeRequests()
          .mvcMatchers("/usuarios/**")
          .access("hasAuthority('SCOPE_read')")
          .and()
          .mvcMatcher("/**")
          .authorizeRequests()
          .anyRequest()
          .denyAll()
          .and()
          .oauth2ResourceServer()
          .jwt();
        return http.build();
    }
}

Nuestro controlador de Articulos

package rs;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ArticulosController {

    @GetMapping("/articles")
    public String[] getArticles() {
        return new String[] { "Article 1", "Article 2", "Article 3" };
    }
}

Nuestro controlador de Usuarios

package rs;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UsuariosController {

    @GetMapping("/usuarios")
    public String[] getArticles() {
        return new String[] { "Usuario 1", "Usuario 2", "Usuario 3" };
    }
}

Nuestro YAML

server:
  port: 8080
  
spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: http://127.0.0.1:9000
          

Nuestra clase principal

package rs;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

}

Con respecto a los «controllers» hay poco que explicar, son simples clases con un único método y path que nos devuelven datos sencillos para la demostración del funcionamiento del Resource Server.

Lo que es realmente importante en este punto son la configuración de las autorizaciones de nuestro Resource Server y la configuración del YAML, veámoslas con detenimiento:

Nuestro YAML

server:
  port: 8080
  
spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: http://127.0.0.1:9000
          

Aquí configuramos el puerto donde se lanzará nuestro Resource Server(controladores incluidos) así como la información necesaria para que el Resource Server pueda comunicarse con lo Servidor de Autorizaciones para validar los tokens cuando los usuarios realicen peticiones a las APIS.

http://127.0.0.1:9000 es en este caso la URL de nuestro Servidor de Autorizaciones.

La clase ResourceServerConfig

package rs;

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@EnableWebSecurity
public class ResourceServerConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
          .mvcMatcher("/articles/**")
          .authorizeRequests()
          .mvcMatchers("/articles/**")
          .access("hasAuthority('SCOPE_read')")
          .and()
          .mvcMatcher("/usuarios/**")
          .authorizeRequests()
          .mvcMatchers("/usuarios/**")
          .access("hasAuthority('SCOPE_read')")
          .and()
          .mvcMatcher("/**")
          .authorizeRequests()
          .anyRequest()
          .denyAll()
          .and()
          .oauth2ResourceServer()
          .jwt();
        return http.build();
    }
}

Aquí realmente configuramos las reglas de acceso a nuestras APIS mediante patrones, así como los scopes necesarios de acceso a cada API/MÉTODO.

Muy importante la sección de:

.mvcMatcher("/**")
.authorizeRequests()
.anyRequest()
.denyAll()

Esta sección denegará toda petición que no haya sido declarada explícitamente en una regla antes de llegar a evaluar esta regla. De esta forma evitaremos probables problemas de Seguridad si se nos olvida configurar algún método o mapping de nuestros controllers.

Ya estamos en disposición de realizar las pruebas sobre nuestro Resource Server.

Las pruebas del Resource Server

Realizaremos las siguientes peticiones:

  1. Una petición a /articles sin token. Devolverá un 401
  2. Una petición a /usuarios sin token. Devolverá 401
  3. Una petición a /articles con token. Nos devolverá los resultados.
  4. Una petición a /usuarios con token. Nos devolverá los resultados.

Los curl serán los sioguientes:

curl --location --request GET 'http://127.0.0.1:8080/articles'
curl --location --request GET 'http://127.0.0.1:8080/usuarios'
curl --location --request GET 'http://127.0.0.1:8080/articles' \
--header 'Authorization: Bearer eyJraWQiOiJhZWYzNTRlNC1kYzhiLTQ5MjMtOGNjNS01MDQ1MmEyZmNhZTQiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJpdmFuIiwiYXVkIjoiY2xpZW50MSIsIm5iZiI6MTY1NDQ2OTg3NCwic2NvcGUiOlsicmVhZCIsIm9wZW5pZCJdLCJpc3MiOiJodHRwOlwvXC8xMjcuMC4wLjE6OTAwMCIsImV4cCI6MTY1NDQ3MzQ3NCwiaWF0IjoxNjU0NDY5ODc0fQ.Wba8lxkPCXxJRNTvE-h1wWkLlQxewqKbrugEF7oY1l3vzyuapRqDeWqiSjXDGNVx0S20hFofA-9HkUW3s1DHnJmfUSeuCAR7CCGVPs_es7ou_y9hlKA0ORUGA6KXQQlo4t6wY8k5Xvlyohn_NzZwI14HT-kATZYv206AasHRxSLm0zYQ2UYjCRPPjNEBFRI-qOkVuMiOC6olAheyKZ0Wg4o_KeJxiwB0vJ8Iz4mAaqXlScJKsMEFdsUBOM7T2lfxqVq5FRttmll0Y3Uhe9bxd5OPXALuT3FDWYjGTIDjTefr4-kzxC1NB6r3kbJnMo82TYsVqIYg_Dhc1hlNGwLGqg'
curl --location --request GET 'http://127.0.0.1:8080/usuarios' \
--header 'Authorization: Bearer eyJraWQiOiJhZWYzNTRlNC1kYzhiLTQ5MjMtOGNjNS01MDQ1MmEyZmNhZTQiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJpdmFuIiwiYXVkIjoiY2xpZW50MSIsIm5iZiI6MTY1NDQ2OTg3NCwic2NvcGUiOlsicmVhZCIsIm9wZW5pZCJdLCJpc3MiOiJodHRwOlwvXC8xMjcuMC4wLjE6OTAwMCIsImV4cCI6MTY1NDQ3MzQ3NCwiaWF0IjoxNjU0NDY5ODc0fQ.Wba8lxkPCXxJRNTvE-h1wWkLlQxewqKbrugEF7oY1l3vzyuapRqDeWqiSjXDGNVx0S20hFofA-9HkUW3s1DHnJmfUSeuCAR7CCGVPs_es7ou_y9hlKA0ORUGA6KXQQlo4t6wY8k5Xvlyohn_NzZwI14HT-kATZYv206AasHRxSLm0zYQ2UYjCRPPjNEBFRI-qOkVuMiOC6olAheyKZ0Wg4o_KeJxiwB0vJ8Iz4mAaqXlScJKsMEFdsUBOM7T2lfxqVq5FRttmll0Y3Uhe9bxd5OPXALuT3FDWYjGTIDjTefr4-kzxC1NB6r3kbJnMo82TYsVqIYg_Dhc1hlNGwLGqg'

Podéis utilizar el Postman para realizar dichas peticiones o curl directamente:

Sin token

Petición a Artículos sin Token
Petición a Artículos sin Token
Petición a Usuarios sin Token
Petición a Usuarios sin Token

Con Token

Petición a Artículos con Token
Petición a Artículos con Token
Petición a Usuarios con Token
Petición a Usuarios con Token

Petición a una URL que no tenemos declarada

Petición a una URL que no tenemos declarada en nuestras reglas de Autorización
Petición a una URL que no tenemos declarada en nuestras reglas de Autorización

Y esto es todo, ya veis lo sencillo que es configurar OAuth con SpringBoot, tanto el Authorization Server como el Resource Server.

Os dejo un enlace a la RFC de OAuth 2.0 donde podéis obtener todos los detalles del protocolo.

Os dejo un enlace a la RFC de los JSON Web Tokens donde podéis indagar más sobre este tipo de tokens.

Os dejo también el código fuente.

Para el Authorization Server:

Para el Resource Server:

Un saludo


COMPARTIR EN REDES SOCIALES

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *