diff --git a/pom.xml b/pom.xml index 3d539d82cad5cf803f7e6760f2a35eabb654f712..be1fa817a1c93caeab45a756db330f07447dbbd6 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> - <version>2.7.3</version> + <version>2.7.4</version> </parent> <groupId>fr.gouv.stopc</groupId> @@ -20,12 +20,12 @@ <properties> <flyway.version>7.15.0</flyway.version> <java.version>11</java.version> - <kotlin.version>1.7.10</kotlin.version> + <kotlin.version>1.7.20</kotlin.version> <commons-compress.version>1.21</commons-compress.version> - <commons-text.version>1.9</commons-text.version> + <commons-text.version>1.10.0</commons-text.version> <hamcrest-date.version>2.0.8</hamcrest-date.version> - <spring-cloud.version>2021.0.3</spring-cloud.version> - <testcontainers.version>1.17.3</testcontainers.version> + <spring-cloud.version>2021.0.4</spring-cloud.version> + <testcontainers.version>1.17.5</testcontainers.version> </properties> <dependencyManagement> @@ -91,10 +91,9 @@ <dependency> <groupId>com.nimbusds</groupId> <artifactId>nimbus-jose-jwt</artifactId> - <version>9.24.3</version> + <version>9.25.5</version> </dependency> - <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> @@ -158,7 +157,7 @@ <plugin> <groupId>com.diffplug.spotless</groupId> <artifactId>spotless-maven-plugin</artifactId> - <version>2.22.5</version> + <version>2.27.2</version> <configuration> <java> <importOrder> @@ -199,7 +198,7 @@ <plugin> <groupId>org.openapitools</groupId> <artifactId>openapi-generator-maven-plugin</artifactId> - <version>6.0.0</version> + <version>6.2.0</version> <executions> <execution> <goals> @@ -218,7 +217,9 @@ </modelPackage> <configOptions> <sourceFolder>src/main/kotlin</sourceFolder> - <documentationProvider>none</documentationProvider> + <documentationProvider> + none + </documentationProvider> <dateLibrary>java8</dateLibrary> <interfaceOnly>true</interfaceOnly> <useTags>true</useTags> diff --git a/src/main/kotlin/fr/gouv/stopc/submissioncode/service/SubmissionCodeService.kt b/src/main/kotlin/fr/gouv/stopc/submissioncode/service/SubmissionCodeService.kt index 8232893b828d7beeeae468cc62b9edf7cb8458a3..ef5bc6fe6bc666dc2fe130a7d3f6d619d4e4a9d1 100644 --- a/src/main/kotlin/fr/gouv/stopc/submissioncode/service/SubmissionCodeService.kt +++ b/src/main/kotlin/fr/gouv/stopc/submissioncode/service/SubmissionCodeService.kt @@ -143,9 +143,9 @@ class SubmissionCodeService( val signedJwt = try { SignedJWT.parse(jwt) - } catch (e: ParseException) { + } catch (e: Exception) { metricsService.countCodeUsed(JWT, false) - log.info("JWT could not be parsed: ${e.message}, $jwt") + log.info("JWT could not be parsed: ${e.message ?: e::class.simpleName}, $jwt") return false } diff --git a/src/test/kotlin/fr/gouv/stopc/submissioncode/controller/VerifyControllerTest.kt b/src/test/kotlin/fr/gouv/stopc/submissioncode/controller/VerifyControllerTest.kt index 757088dbdf94b7d8b7b776b7d96908d9914990d1..ea09eba07bb425fccba8ec117b3e3b59c6082f94 100644 --- a/src/test/kotlin/fr/gouv/stopc/submissioncode/controller/VerifyControllerTest.kt +++ b/src/test/kotlin/fr/gouv/stopc/submissioncode/controller/VerifyControllerTest.kt @@ -25,9 +25,11 @@ import org.junit.jupiter.params.provider.ValueSource import org.springframework.boot.test.system.CapturedOutput import org.springframework.boot.test.system.OutputCaptureExtension import org.springframework.http.HttpStatus.OK +import java.time.Duration import java.time.Instant import java.time.temporal.ChronoUnit.DAYS import java.time.temporal.ChronoUnit.MINUTES +import java.time.temporal.ChronoUnit.SECONDS import java.util.Base64 import java.util.UUID import java.util.stream.Stream @@ -230,16 +232,19 @@ class VerifyControllerTest { inner class JwtTest { private fun generateInvalidJwt(): Stream<Arguments> { + val tenDaysAgo = Instant.now().minus(10, DAYS).truncatedTo(SECONDS) + val oneMinuteAgo = Instant.now().minus(1, MINUTES).truncatedTo(SECONDS) + val oneMinuteLater = Instant.now().plus(1, MINUTES).truncatedTo(SECONDS) return Stream.of( Arguments.of( "the JWT is issued more than 10 days in the past", - givenJwt(iat = Instant.now().minus(10, DAYS).epochSecond), - "JWT has expired, it was issued at [^ ]+, so it expired on [^ ]+:" + givenJwt(iat = tenDaysAgo.epochSecond), + "JWT has expired, it was issued at $tenDaysAgo, so it expired on ${tenDaysAgo.plus(Duration.ofDays(10))}:" ), Arguments.of( "the JWT is issued in the future", - givenJwt(iat = Instant.now().plus(1, MINUTES).epochSecond), - "JWT is issued at a future time \\([^)]+\\):" + givenJwt(iat = oneMinuteLater.epochSecond), + "JWT is issued at a future time ($oneMinuteLater):" ), Arguments.of( "the iat field is an empty string instead of a numeric Date", @@ -258,23 +263,23 @@ class VerifyControllerTest { ), Arguments.of( "the iat field is missing", - givenJwt(iat = null), - "JWT is missing claim jti \\([^)]+\\) or iat \\(null\\):" + givenJwt(jti = "some-jwt-identifier", iat = null), + "JWT is missing claim jti (some-jwt-identifier) or iat (null):" ), Arguments.of( "the jti field is empty", - givenJwt(jti = ""), - "JWT is missing claim jti \\(\\) or iat \\([^)]+\\):" + givenJwt(jti = "", iat = oneMinuteAgo.epochSecond), + "JWT is missing claim jti () or iat ($oneMinuteAgo):" ), Arguments.of( "the jti field is blank", - givenJwt(jti = " "), - "JWT is missing claim jti \\( \\) or iat \\([^)]+\\):" + givenJwt(jti = " ", iat = oneMinuteAgo.epochSecond), + "JWT is missing claim jti ( ) or iat ($oneMinuteAgo):" ), Arguments.of( "the jti field is missing", - givenJwt(jti = null), - "JWT is missing claim jti \\(null\\) or iat \\([^)]+\\):" + givenJwt(jti = null, iat = oneMinuteAgo.epochSecond), + "JWT is missing claim jti (null) or iat ($oneMinuteAgo):" ), Arguments.of( "the jti field is a number instead of a string", @@ -306,6 +311,16 @@ class VerifyControllerTest { givenJwt(kid = "AnotherKID"), "JWT signature is invalid:" ), + Arguments.of( + "the alg field is missing", + givenJwt().replaceBefore(".", Base64.getEncoder().encodeToString("""{"kid": "TousAntiCovidKID","typ":"JWT"}""".toByteArray())), + "JWT could not be parsed: Invalid JWS header: Missing \"alg\" in header JSON object," + ), + Arguments.of( + "the JWT header is corrupt", + givenJwt().replaceBefore(".", "Z"), + "JWT could not be parsed: Invalid JWS header: Invalid JSON object," + ), ) } @@ -355,7 +370,7 @@ class VerifyControllerTest { .body("valid", equalTo(false)) assertThat(output.all) - .containsPattern("$logMessage $serializedJwt") + .contains("$logMessage $serializedJwt") } @Test