Ejemplo en Spring Boot 2.x

Spring Boot 2.x proporciona la capacidad de utilizar completamente la configuración automática para configurar el inicio de sesión a través de OAuth 2.0.

Esta sección muestra cómo configurar ejemplo de código para el inicio de sesión de OAuth 2.0, utilizando Google como proveedor de autenticación, y se tratan los siguientes temas:

  • Configuración inicial

  • Configurar el URI para la redirección

  • Configurar el archivo application.yml

  • Descargar la aplicación

Configuración inicial

Para utilizar el sistema de autenticación OAuth 2.0 de Google para iniciar sesión, debe configurar un proyecto en la consola API de Google para recibir OAuth 2.0. credenciales.

Siga las instrucciones en OpenID Connect, comenzando con la sección "Configurar OAuth 2.0".

Después de completar las instrucciones "Obtener credenciales de OAuth 2.0", se creará una nueva El cliente debe aparecer con las credenciales que consisten en un ID de cliente y un secreto de cliente.

Configuración de un URI de redireccionamiento

El URI de redireccionamiento es la ruta en la aplicación a la que se dirige el agente de usuario del usuario final. Se redirige después de autenticarse con Google y otorgar acceso al cliente OAuth (creado en el paso anterior) en la página de Consentimiento.

En la sección "Establecer URI de redireccionamiento", asegúrese de que el campo URI de redireccionamiento autorizado esté configurado en localhost:8080/login /oauth2/code/google.

La redirección predeterminada La plantilla de URI es {baseUrl}/login/oauth2/code/{registrationId}. RegistrationId es un identificador único para ClientRegistration.
Si El cliente OAuth se ejecuta detrás de un servidor proxy; se recomienda verificar la configuración del servidor proxy para asegurarse de que la aplicación se haya configurado correctamente. Consulte también las variables de plantilla URI admitidas para redirect-uri.

Configure el archivo application.yml

Ahora que Si tiene uno nuevo cliente OAuth a través de Google, debe configurar su aplicación para utilizar un cliente OAuth para el flujo de autenticación. Para hacer esto:

  1. Vaya a application.yml y establezca la siguiente configuración:

    
    spring:
      security:
        oauth2:
          client:
            registration: 
              google: 
                client-id: google-client-id
                client-secret: google-client-secret
    Propiedades del cliente OAuth
    1. spring.security.oauth2.client.registration es el prefijo de propiedad base para las propiedades del cliente OAuth.
    2. El prefijo de propiedad base es seguido del identificador de ClientRegistration, por ejemplo google.
  2. Reemplace los valores en client-id y client-secret a las credenciales de OAuth 2.0 que se crearon anteriormente.

Descargando la aplicación

Ejecute el ejemplo Spring Boot 2.x y vaya a localhost:8080. Luego será redirigido a una página de inicio de sesión estándar generada automáticamente que muestra un enlace para Google.

Haga clic en el enlace de Google y será redirigido a Google para autenticarse.

Después de la autenticación Con las credenciales de su cuenta de Google, aparece la pantalla de Consentimiento en la página siguiente. La pantalla de Consentimiento le pedirá que permita o deniegue el acceso al cliente OAuth que se creó anteriormente. Haga clic en Permitir para permitir que el cliente de OAuth acceda a su dirección de correo electrónico y a la información básica de su perfil.

En este punto, el cliente de OAuth recibe su dirección de correo electrónico y su información básica de perfil. punto final UserInfo y establece una sesión autenticada.

Asignaciones de propiedades en Spring Boot 2.x

La siguiente tabla describe la asignación de las propiedades del cliente OAuth de Spring Boot 2.x a las propiedades ClientRegistration.

Spring Boot 2.x ClientRegistration

spring.security.oauth2.client.registration.[registrationId]

ID de registro

spring.security.oauth2.client.registration.[registrationId].client-id

clientId

spring.security.oauth2.client.registration.[registrationId].client-secret

clientSecret

primavera. seguridad.oauth2.client.registration.[registrationId].client-authentication-method

clientAuthenticationMethod

spring.security.oauth2.client.registration.[registrationId].autorización-grant-type

autorizaciónGrantType

spring.security.oauth2.client.registration.[registrationId].redirect-uri

redirectUri

spring.security.oauth2.client.registration.[registrationId].scope

ámbitos

spring.security. oauth2.client.registration.[registrationId].client-name

clientName

spring.security.oauth2.client.provider.[providerId].authorization-uri

providerDetails.authorizationUri

spring.security. oauth2.client.provider.[providerId].token-uri

providerDetails.tokenUri

spring.security.oauth2.client.provider.[providerId].jwk-set-uri

providerDetails.jwkSetUri

spring.security.oauth2.client.provider.[providerId].issuer-uri

providerDetails.issuerUri

spring.security.oauth2.client.provider.[providerId].user-info -uri

providerDetails.userInfoEndpoint.uri

spring.security.oauth2.client.provider.[providerId].método-de-autenticación-info-usuario

providerDetails.userInfoEndpoint.authenticationMethod

spring.security.oauth2.client.provider.[providerId].user-name-attribute

providerDetails.userInfoEndpoint.userNameAttributeName

ClientRegistration se puede configurar inicialmente usando punto final de configuración del proveedor de OpenID Connect o Punto final de metadatos del servidor de autorización estableciendo la propiedad spring.security.oauth2.client.provider.[providerId].issuer- uri.

CommonOAuth2Provider

CommonOAuth2Provider predefine un conjunto de propiedades de cliente estándar para varios proveedores conocidos: Google, GitHub, Facebook y Okta.

Por ejemplo, authorization-uri, token-uri y user-info-uri no cambian frecuentemente para cualquier proveedor determinado. Por lo tanto, tiene sentido proporcionar valores predeterminados para reducir la configuración requerida.

Como mostramos anteriormente cuando configuramos el cliente de Google, solo el client-id y el las propiedades del cliente son obligatorias client-secret.

El siguiente listado es un ejemplo:

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: google-client-id
            client-secret: google-client-secrett
La detección automática de propiedades estándar del cliente funciona sin problemas aquí, ya que registrationId (google) coincide con enum GOOGLE (no distingue entre mayúsculas y minúsculas) en CommonOAuth2Provider.

En los casos en los que necesite establecer un registrationId diferente, por ejemplo google-login, aún puede utilizar la detección automática del valor predeterminado. propiedades del cliente configurando la propiedad provider.

El siguiente listado es un ejemplo:

spring:
  security:
    oauth2:
      client:
        registration:
          google-login: 
            provider: google	
            client-id: google-client-id
            client-secret: google-client-secre
  1. El registrationId está configurado en google-login.
  2. La propiedad provider está configurada en google, lo que permitirá la detección de propiedades de cliente predeterminadas establecidas en CommonOAuth2Provider.GOOGLE.getBuilder().

Configuración de propiedades de proveedor personalizadas

Algunos proveedores de OAuth 2.0 admiten archivos compartidos arrendamiento, lo que da como resultado la creación de diferentes protocolos de puntos finales para cada inquilino (o subdominio).

Por ejemplo, un cliente OAuth registrado con Okta se asigna a un subdominio específico y tiene sus propios puntos finales de protocolo.

Para tales casos, Spring Boot 2 .x proporciona la siguiente propiedad básica para configurar propiedades de proveedor personalizadas: spring.security.oauth2.client.provider.[providerId].

El siguiente listado es un ejemplo:


spring:
  security:
    oauth2:
      client:
        registration:
          okta:
            client-id: okta-client-id
            client-secret: okta-client-secret
        provider:
          okta:	
            authorization-uri: https://your-subdomain.oktapreview.com/oauth2/v1/authorize
            token-uri: https://your-subdomain.oktapreview.com/oauth2/v1/token
            user-info-uri: https://your-subdomain.oktapreview.com/oauth2/v1/userinfo
            user-name-attribute: sub
            jwk-set-uri: https://your-subdomain.oktapreview.com/oauth2/v1/keys
  1. Propiedad base (spring.security.oauth2.client.provider.okta) le permite configurar de forma personalizada la ubicación de los puntos finales del protocolo.

Anulación de la configuración automática de Spring Boot 2.x

Clase de configuración automática Spring Boot 2.x para soporte de cliente OAuth – OAuth2ClientAutoConfiguration.

Realiza las siguientes tareas:

  • Registra @Bean para ClientRegistrationRepository que consta de instancias ClientRegistration de propiedades de cliente OAuth configuradas.

  • Registra un @Bean para SecurityFilterChain y activa la autorización en OAuth 2.0 a través de httpSecurity.oauth2Login().

Si necesita anular la configuración automática para necesidades específicas, puede hacerlo de las siguientes maneras:

  • Registrar @Bean para ClientRegistrationRepository

  • Registrar @Bean para SecurityFilterChain

  • Anulación completa de la configuración automática

Registro de @Bean para ClientRegistrationRepository

El siguiente ejemplo muestra cómo registrar @Bean para ClientRegistrationRepository:

Java

@Configuration
public class OAuth2LoginConfig {
	@Bean
	public ClientRegistrationRepository clientRegistrationRepository() {
		return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
	}
	private ClientRegistration googleClientRegistration() {
		return ClientRegistration.withRegistrationId("google")
			.clientId("google-client-id")
			.clientSecret("google-client-secret")
			.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
			.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
			.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
			.scope("openid", "profile", "email", "address", "phone")
			.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
			.tokenUri("https://www.googleapis.com/oauth2/v4/token")
			.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
			.userNameAttributeName(IdTokenClaimNames.SUB)
			.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
			.clientName("Google")
			.build();
	}
}
Kotlin

@Configuration
class OAuth2LoginConfig {
    @Bean
    fun clientRegistrationRepository(): ClientRegistrationRepository {
        return InMemoryClientRegistrationRepository(googleClientRegistration())
    }
    private fun googleClientRegistration(): ClientRegistration {
        return ClientRegistration.withRegistrationId("google")
                .clientId("google-client-id")
                .clientSecret("google-client-secret")
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
                .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
                .redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
                .scope("openid", "profile", "email", "address", "phone")
                .authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
                .tokenUri("https://www.googleapis.com/oauth2/v4/token")
                .userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
                .userNameAttributeName(IdTokenClaimNames.SUB)
                .jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
                .clientName("Google")
                .build()
    }
}

Registro de @Bean para SecurityFilterChain

El siguiente ejemplo muestra cómo registrar @Bean para SecurityFilterChain usando la anotación @EnableWebSecurity y habilite la autorización en OAuth 2.0 a través de httpSecurity.oauth2Login():

Configuración de inicio de sesión de OAuth2
Java

@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http
			.authorizeHttpRequests(authorize -> authorize
				.anyRequest().authenticated()
			)
			.oauth2Login(withDefaults());
		return http.build();
	}
}
Kotlin

@EnableWebSecurity
class OAuth2LoginSecurityConfig {
    open fun filterChain(http: HttpSecurity): SecurityFilterChain {
        http {
            authorizeRequests {
                authorize(anyRequest, authenticated)
            }
            oauth2Login { }
        }
        return http.build()
    }
}

Anulación completa de la configuración automática

El siguiente ejemplo muestra cómo anular completamente la configuración automática registrando @Bean para ClientRegistrationRepository y @Bean para SecurityFilterChain.

Anulación de configuración automática
Java

@Configuration
public class OAuth2LoginConfig {
	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http
			.authorizeHttpRequests(authorize -> authorize
				.anyRequest().authenticated()
			)
			.oauth2Login(withDefaults());
		return http.build();
	}
	@Bean
	public ClientRegistrationRepository clientRegistrationRepository() {
		return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
	}
	private ClientRegistration googleClientRegistration() {
		return ClientRegistration.withRegistrationId("google")
			.clientId("google-client-id")
			.clientSecret("google-client-secret")
			.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
			.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
			.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
			.scope("openid", "profile", "email", "address", "phone")
			.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
			.tokenUri("https://www.googleapis.com/oauth2/v4/token")
			.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
			.userNameAttributeName(IdTokenClaimNames.SUB)
			.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
			.clientName("Google")
			.build();
	}
}
Kotlin

@Configuration
class OAuth2LoginConfig {
    @Bean
    open fun filterChain(http: HttpSecurity): SecurityFilterChain {
        http {
            authorizeRequests {
                authorize(anyRequest, authenticated)
            }
            oauth2Login { }
        }
        return http.build()
    }
    @Bean
    fun clientRegistrationRepository(): ClientRegistrationRepository {
        return InMemoryClientRegistrationRepository(googleClientRegistration())
    }
    private fun googleClientRegistration(): ClientRegistration {
        return ClientRegistration.withRegistrationId("google")
                .clientId("google-client-id")
                .clientSecret("google-client-secret")
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
                .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
                .redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
                .scope("openid", "profile", "email", "address", "phone")
                .authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
                .tokenUri("https://www.googleapis.com/oauth2/v4/token")
                .userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
                .userNameAttributeName(IdTokenClaimNames.SUB)
                .jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
                .clientName("Google")
                .build()
    }
}

Configuración basada en Java sin Spring Boot 2.x

Si no es posible usar Spring Boot 2.x, pero necesita configurar uno de los proveedores predefinidos en CommonOAuth2Provider (por ejemplo, Google), aplique la siguiente configuración:

Configuración de inicio de sesión de OAuth2
Java

@EnableWebSecurity
public class OAuth2LoginConfig {
	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http
			.authorizeHttpRequests(authorize -> authorize
				.anyRequest().authenticated()
			)
			.oauth2Login(withDefaults());
		return http.build();
	}
	@Bean
	public ClientRegistrationRepository clientRegistrationRepository() {
		return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
	}
	@Bean
	public OAuth2AuthorizedClientService authorizedClientService(
			ClientRegistrationRepository clientRegistrationRepository) {
		return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
	}
	@Bean
	public OAuth2AuthorizedClientRepository authorizedClientRepository(
			OAuth2AuthorizedClientService authorizedClientService) {
		return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService);
	}
	private ClientRegistration googleClientRegistration() {
		return CommonOAuth2Provider.GOOGLE.getBuilder("google")
			.clientId("google-client-id")
			.clientSecret("google-client-secret")
			.build();
	}
}
Kotlin

@EnableWebSecurity
open class OAuth2LoginConfig {
    @Bean
    open fun filterChain(http: HttpSecurity): SecurityFilterChain {
        http {
            authorizeRequests {
                authorize(anyRequest, authenticated)
            }
            oauth2Login { }
        }
        return http.build()
    }
    @Bean
    open fun clientRegistrationRepository(): ClientRegistrationRepository {
        return InMemoryClientRegistrationRepository(googleClientRegistration())
    }
    @Bean
    open fun authorizedClientService(
        clientRegistrationRepository: ClientRegistrationRepository?
    ): OAuth2AuthorizedClientService {
        return InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository)
    }
    @Bean
    open fun authorizedClientRepository(
        authorizedClientService: OAuth2AuthorizedClientService?
    ): OAuth2AuthorizedClientRepository {
        return AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService)
    }
    private fun googleClientRegistration(): ClientRegistration {
        return CommonOAuth2Provider.GOOGLE.getBuilder("google")
            .clientId("google-client-id")
            .clientSecret("google-client-secret")
            .build()
    }
}
Xml

<http auto-config="true">
	<intercept-url pattern="/**" access="authenticated"/>
	<oauth2-login authorized-client-repository-ref="authorizedClientRepository"/>
</http>
<client-registrations>
	<client-registration registration-id="google"
                         client-id="google-client-id"
                         client-secret="google-client-secret"
                         provider-id="google"/>
</client-registrations>
<b:bean id="authorizedClientService"
        class="org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService"
        autowire="constructor"/>
<b:bean id="authorizedClientRepository"
        class="org.springframework.security.oauth2.client.web.AuthenticatedPrincipalOAuth2AuthorizedClientRepository">
	<b:constructor-arg ref="authorizedClientService"/>
</b:bean>