I am trying to validate an access token on a resource server.
jwt.io validates the access token with the signature, so I guess the problem is spring configuration
This is my pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>uy.edu.anep</groupId>
<artifactId>aplicacion-funcionarios-service</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>aplicacion-funcionarios-service</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.11.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<start-class>edu.anep.familia.aplicacionfuncionarios.Application</start-class>
<org.mapstruct.version>1.2.0.Final</org.mapstruct.version>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<oauth-autoconfig.version>2.1.11.RELEASE</oauth-autoconfig.version>
<spring-cloud.version>Greenwich.SR4</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- oauth -->
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-envers</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<!-- https://stackoverflow.com/a/43574427/1989579 -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.11</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.2.11</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.11</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>edu.anep.microservicios</groupId>
<artifactId>spring-DMZ-Utils</artifactId>
<version>0.0.8-spring_2.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.12.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>recreate-docker</id>
<configuration>
<environmentVariables>
<COMPOSE_PATH>./</COMPOSE_PATH>
<COMPOSE_SERVICE_NAME>aplicacion-funcionarios-service</COMPOSE_SERVICE_NAME>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</environmentVariables>
<executable>rebuild.sh</executable>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</project>
this my application.yml
server:
port: 8080
endpoints:
shutdown:
enabled: true
restart:
enabled: true
server.servlet.context-path: /aplicacion-funcionarios-service
security:
basic:
enabled: false
oauth2:
resource:
jwt:
key-value: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvVSBre7DgM7FS1d9gzwBMaOY6j40AjcFHq3s9zx/0QMGAmRrVD2Eiuc7YdIZu9gRpCAohKDz1v0wmeE9Nafqw9XjcxJX2Te4+TTF8/Pia8adSyKVjpFMvlvCu83fdT+vgM3P08QLHtm19ToImTsI5oNZhH/iZNm8bjMJL4D4DXv3rOKwhKp5Sb2Hn8Qwes8MJSFO2YtVtqLCc60L2ERxPd5vZ/7s4mEIhI1bw/U/n5n5yPVHpXsZoP3Eru2LksDsWoWK/jKjJIhRtEZxbDuycMYEYiCaVaxLJ2Bwu41bob+FrS3YOlSqzQDpyTcpuACOdUmRFmtnRtORF1wnlDiyYQIDAQAB
-----END PUBLIC KEY-----
spring:
cloud.circuit.breaker.enabled: false
application:
name: aplicacion-funcionarios-service
#el formato en que van las fechas por defecto, sin zona horaria
jackson:
date-format: yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
time-zone: America/Montevideo
# Spring JDBC configuration
datasource:
url: ...
username: ...
password: ..
# Spring Data JPA configuration
jpa:
properties:
org.hibernate.envers.audit_table_suffix: _aud
org.hibernate.envers.default_schema: audit
hibernate:
#format_sql: true
#do_not_audit_optimistic_locking_field: false
dialect: org.hibernate.dialect.PostgreSQLDialect
#https://github.com/spring-projects/spring-boot/issues/12007#issuecomment-369388646
jdbc.lob.non_contextual_creation: true
hibernate:
# To be updated in real production usage! update create-drop none
#ddl-auto: update
show-sql: false
sleuth:
baggage-keys:
- x-request-id
- x-b3-traceid
- x-b3-spanid
- x-b3-parentspanid
- x-b3-sampled
- x-b3-flags
- x-ot-span-context
#configuracion del cache de redis
cache:
type: none
#Disable Ribbon
ribbon.eureka.enabled: false
#se habilita liquidbase
spring.liquibase.change-log: classpath:db/changelog/db.changelog-master.xml
logging.level.root: INFO
logging.level.org.springframework.web: DEBUG
logging.level.org.springframework.security: DEBUG
logging.level.org.springframework.security.oauth2: DEBUG
#logging.level.org.apache: trace
this is my config class
@Configuration
@EnableResourceServer
public class OAuth2SecurityConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests()
//.antMatchers("/**").authenticated()
.antMatchers(
"/*/v2/api-docs",
"/v2/api-docs",
"/swagger-ui.html",
"/swagger-ui.html/**",
"/webjars/springfox-swagger-ui/**",
"/swagger-resources/**",
"/actuator/*"
).permitAll()
.anyRequest().authenticated();
//http.cors(
// @formatter:on
}
}
but I receive the following error in response
401
{
"error": "invalid_token",
"error_description": "Cannot convert access token to JSON"
}
the log shows little information
aplicacion-funcionarios-service_1 | 2019-12-14 22:31:57.545 DEBUG [aplicacion-funcionarios-service,2e8a7fbc810ad58c,2e8a7fbc810ad58c,false] 1 --- [nio-8080-exec-1] p.a.OAuth2AuthenticationProcessingFilter : Authentication request failed: error="invalid_token", error_description="Cannot convert access token to JSON"
aplicacion-funcionarios-service_1 | 2019-12-14 22:31:57.594 DEBUG [aplicacion-funcionarios-service,2e8a7fbc810ad58c,2e8a7fbc810ad58c,false] 1 --- [nio-8080-exec-1] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@64c00153
aplicacion-funcionarios-service_1 | 2019-12-14 22:31:57.598 DEBUG [aplicacion-funcionarios-service,2e8a7fbc810ad58c,2e8a7fbc810ad58c,false] 1 --- [nio-8080-exec-1] s.s.o.p.e.DefaultOAuth2ExceptionRenderer : Written [error="invalid_token", error_description="Cannot convert access token to JSON"] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@5739b1cb]
aplicacion-funcionarios-service_1 | 2019-12-14 22:31:57.599 DEBUG [aplicacion-funcionarios-service,2e8a7fbc810ad58c,2e8a7fbc810ad58c,false] 1 --- [nio-8080-exec-1] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
this is the header sent
Authorization: Bearer eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCIsIm9yZy5hcGVyZW8uY2FzLnNlcnZpY2VzLlJlZ2lzdGVyZWRTZXJ2aWNlIjoiMSJ9.eyJzdWIiOiJkZW1vZG9jZW50ZSIsInJvbGVzIjpbXSwiaXNzIjoiaHR0cHM6XC9cL3ByZXByb2QuYW5lcC5lZHUudXlcL2NhcyIsIm5vbmNlIjpbIiJdLCJjbGllbnRfaWQiOlsiQVBQRnVuY2lvbmFyaW9zIl0sImF1ZCI6Imh0dHA6XC9cL2xvY2FsaG9zdDo4MDgxXC9cL2xvZ2luIiwiZ3JhbnRfdHlwZSI6WyJBVVRIT1JJWkFUSU9OX0NPREUiXSwicGVybWlzc2lvbnMiOltdLCJzY29wZSI6WyJlbWFpbCIsIm9wZW5pZCIsInByb2ZpbGUiXSwiY2xhaW1zIjpbXSwic2NvcGVzIjpbIm9wZW5pZCBwcm9maWxlIGVtYWlsIl0sInN0YXRlIjpbIiJdLCJleHAiOjE1NzYzOTE0MTgsImlhdCI6MTU3NjM2MjYxOCwianRpIjoiQVQtNS05a3ZvNGhsUFY0TUkzcjdReEticGRaSDYtMnRlNTQtdiJ9.NvFRFpa8XqYwGCYNHV6brBoi2wMsHH9YthbUK4wjifg7Kfeu__R9wialAyCUJViifi1cTCkTNfysbo-tH5WaJN3vrENDVSpSPlBbWJS5fVmNR45-HCDtLJkNsoexeTwNin1R5tz-GHNTnh4rNFjGJwj_gI5_MCFRYODBiuU_19HsVX_eEYJn7mPchk_Q8wujk9e_akPRLHzruCa3yilR6LGOzWWecQwVt3q0ZMgaOt-aG42OVuGySD-vgzpfJfPc4SFzYXyQYtvnuOyb3q1pxECzBVbW296uzzWaEOfV5OlGcMk_i4vN61HBQDMYbYcheehO3T7jZgCulYlGzit6Mw
2
Answers
I couldn't solve this using the spring-oauth dependencies.
I used
I created my custom filter that validate the token
and then configure the filter like this
By default, Oauth2 Spring integration uses its own "type of tokens", if you want to work with JWT ones you have to specify how to deal with them developing the suitable behaviour of
JwtAccessTokenConverter
.I hope the following links help you to solve the problem:
Option1
Option2
In the following link you will be able to see a tutorial with a complete integration with: JWT + Oauth2
On the other hand, in the next one you will find a fully functional microservice used as Oauth 2.0 security server integrated with Spring, that includes several other customizations:
Oauth 2 security server