...
En la clase con la configuración de seguridad (ver pasos 1 y 2 de la configuración común), añadir el siguiente Bean para configurar el filtro para LoA, estableciendo el nivel mínimo que se desea establecer en toda nuestra API:
Bloque de código @Bean public UmuJwtLoaAuthenticationFilter loaFilterBean() { return new UmuJwtLoaAuthenticationFilter( UmuJwtLoaLevelEnum.SUBSTANTIAL); }En la misma clase, en el método configure, añadir el filtro configurado en el paso anterior de la siguiente forma:
Bloque de código language java .addFilterAfter( loaFilterBean(), BearerTokenAuthenticationFilter.class )
Hay que añadirlo justo antes de .oauth2ResourceServer().jwt().
Por ejemplo:Bloque de código language java @Override public SecurityFilterChain filterChain( HttpSecurity http ) throws Exception { http.authorizeRequests() .mvcMatchers("/actuator/**").permitAll() .mvcMatchers("/api-docs").permitAll() .mvcMatchers(apiPath+"/public/**").permitAll() .mvcMatchers(apiPath+"/private/**").hasAnyAuthority(serverScopes) .anyRequest().authenticated().and() .addFilterAfter( loggingFilterBean(), BearerTokenAuthenticationFilter.class ) .addFilterAfter( loaFilterBean(), BearerTokenAuthenticationFilter.class ) .oauth2ResourceServer().jwt(); return http.build(); }Advertencia Repetimos: ESTA CONFIGURACIÓN GLOBAL VALIDARÁ EL NIVEL DEL CLAIM LOA EN TODOS LOS ENDPOINTS DEL API.
...
En la clase con la configuración de seguridad (ver pasos 1 y 2 de la configuración común), añadir la siguiente anotación en la declaración de la clase:
Bloque de código language java @EnableGlobalMethodSecurity( prePostEnabled = true )
Añadir el siguiente Bean:
Bloque de código language java @Bean UmuJwtLoaAccessDeniedHandler accessDeniedHandler() { return new UmuJwtLoaAccessDeniedHandler(); }En la misma clase, en el método configure, añadir el accessDeniedHandler configurado en el paso anterior de la siguiente forma:
Bloque de código language java .and().exceptionHandling().accessDeniedHandler( accessDeniedHandler() )
Ejemplo de configuración completa:
Bloque de código language java public SecurityFilterChain filterChain( HttpSecurity http ) throws Exception { http .authorizeRequests() .mvcMatchers("/actuator/**").permitAll() .mvcMatchers("/api-docs").permitAll() .mvcMatchers(apiPath+"/public/**").permitAll() .mvcMatchers(apiPath+"/private/**").hasAnyAuthority(serverScopes) .anyRequest().authenticated() .and().exceptionHandling().accessDeniedHandler( accessDeniedHandler() ) .and().addFilterAfter( loggingFilterBean(), BearerTokenAuthenticationFilter.class ) .oauth2ResourceServer().jwt(); return http.build(); }
RestController
Ahora, en nuestro RestController, anotar el método con nuestro endpoint a securizar con la siguiente anotación:Bloque de código language java @PreAuthorize( "@umuJwtLoaAuthenticator.isSubstantialLoA(authentication)" )
Advertencia El método isSubstantialLoA del componente umuJwtLoaAuthenticator establece el nivel mínimo de LoA para acceder al endpoint a medio (Substantial del eIDAS).
Para establecer el nivel alto (High), es necesario utilizar el método isHighLoA(authentication).
Por ejemplo:Bloque de código language java @GetMapping( "/private/afiliacion" ) @Operation( summary = "Endpoint test /afiliacion", description = "Obtiene el dto de afiliación del token llamando a serviciosgente internamente", tags = {"Serviciosgente"}, security = {@SecurityRequirement( name = "OIDC", scopes = "openid" )}, responses = { @ApiResponse( responseCode = "401", description = "Token inválido o LoA mínimo no alcanzado", content = @Content ), @ApiResponse( responseCode = "500", description = "Error de comunicación con serviciosgente", content = @Content ), @ApiResponse( responseCode = "200", description = "Datos de Afiliación del propietario del token obtenidos correctamente", content = @Content( schema = @Schema( implementation = AfiliacionDTO.class ) ) ) } ) @PreAuthorize( "@umuJwtLoaAuthenticator.isSubstantialLoA(authentication)" ) public ResponseEntity<AfiliacionDTO> getAfiliacionGente( @AuthenticationPrincipal Jwt jwt ) {Advertencia Repetimos: ESTA CONFIGURACIÓN POR MÉTODO VALIDARÁ EL NIVEL DEL CLAIM LOA EN EL ENDPOINT CON LA ANOTACIÓN PREAUTHORIZE.
...
RESPUESTA DE ERROR
Cuando se intenta acceder a un endpoint securizado con un token sin el claim LoA mínimo (independientemente de la configuración elegida), se devolverá la siguiente información:
- Código HTTP: 401
- Cabecera en la respuesta: umu-authenticat: invalid_loa_claim
- Cabecera en la respuesta: www-authenticate: Bearer error="invalid_loa_claim",error_description="Invalid LoA Claim. Excepted level 'SUBSTANTIAL' : Found level: 'LOW' ",error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"
...