Skip to content

Commit

Permalink
Create mp.jwt.verify.token.age config property for issue #195
Browse files Browse the repository at this point in the history
Signed-off-by: Teddy J. Torres <teddyjtorres@hotmail.com>
  • Loading branch information
teddyjtorres committed Mar 31, 2022
1 parent fe63825 commit ed58fb0
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 36 deletions.
13 changes: 11 additions & 2 deletions spec/src/main/asciidoc/configuration.asciidoc
@@ -1,4 +1,4 @@
// Copyright (c) 2016-2020 Eclipse Microprofile Contributors:
// Copyright (c) 2016-2022 Eclipse Microprofile Contributors:
// Red Hat, IBM, Tomitribe
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -412,7 +412,7 @@ Please see <<verification-publickey-location, mp.jwt.publickey.location>> for al
[[claims-verification]]
## Verification of JWT token claims

MP JWT specification currently supports the verification of the token `iss` issuer and `aud` audience claims which is done after the token signature has been verified or the token has been decrypted.
MP JWT specification currently supports the verification of the token `iss` issuer, `aud` audience, and `iat` issued at claims which is done after the token signature has been verified or the token has been decrypted.

[[verify-issuer]]
### `mp.jwt.verify.issuer`
Expand All @@ -426,6 +426,15 @@ Note that since this property verifies the `iss` claim value, it will be effecti

The `mp.jwt.verify.audiences` config property is a comma delimited list of allowable values for the `aud` claim. If specified, a MicroProfile JWT implementation must verify the `aud` claim of incoming JWTs is present and at least one value in the claim matches one of the configured values of `mp.jwt.verify.audiences`.

[[verify-token-age]]
### `mp.jwt.verify.token.age`

The `mp.jwt.verify.token.age` config property allows for the number of seconds since `iat` to be specified. A MicroProfile JWT implementation must verify the `iat` claim of incoming JWTs is present and the configured value of `mp.jwt.verify.token.age` since `iat` has not elapsed. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.

[[verify-clock-skew]]
### `mp.jwt.verify.clock.skew`
The `mp.jwt.verify.clock.skew` config property allows for the clock skew in seconds used during the token expiry and age verification to be specified. Default value is 60 seconds.

## Requirements for accepting signed and encrypted tokens

MP JWT specification currently requires that an MP JWT application accepts only signed or only encrypted or only signed and encrypted tokens as it expected that many endpoints will have the requirements to accept a single token type only.
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Contributors to the Eclipse Foundation
* Copyright (c) 2016-2022 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand Down Expand Up @@ -84,17 +84,17 @@ public void callEchoExpiredToken() throws Exception {
HashSet<TokenUtils.InvalidClaims> invalidFields = new HashSet<>();
invalidFields.add(TokenUtils.InvalidClaims.EXP);
String token = TokenUtils.generateTokenString("/Token1.json", invalidFields);
System.out.printf("jwt: %s\n", token);

String uri = baseURL.toExternalForm() + "endp/echo";
WebTarget echoEndpointTarget = ClientBuilder.newClient()
.target(uri)
.queryParam("input", "hello");
Response response =
echoEndpointTarget.request(TEXT_PLAIN).header(HttpHeaders.AUTHORIZATION, "Bearer " + token).get();
Assert.assertEquals(response.getStatus(), HttpURLConnection.HTTP_UNAUTHORIZED);
String reply = response.readEntity(String.class);
System.out.printf("Reply: %s\n", reply);
callEchoAndExpectUnauthorized(token);
}

@RunAsClient
@Test(groups = TEST_GROUP_JAXRS, description = "Validate a request with aged token fails with HTTP_UNAUTHORIZED")
public void callEchoAgedToken() throws Exception {
String token = TokenUtils.generateTokenString("/Token1.json");
Thread.sleep(5000);

callEchoAndExpectUnauthorized(token);
}

@RunAsClient
Expand All @@ -103,17 +103,8 @@ public void callEchoBadIssuer() throws Exception {
HashSet<TokenUtils.InvalidClaims> invalidFields = new HashSet<>();
invalidFields.add(TokenUtils.InvalidClaims.ISSUER);
String token = TokenUtils.generateTokenString("/Token1.json", invalidFields);
System.out.printf("jwt: %s\n", token);

String uri = baseURL.toExternalForm() + "endp/echo";
WebTarget echoEndpointTarget = ClientBuilder.newClient()
.target(uri)
.queryParam("input", "hello");
Response response =
echoEndpointTarget.request(TEXT_PLAIN).header(HttpHeaders.AUTHORIZATION, "Bearer " + token).get();
Assert.assertEquals(response.getStatus(), HttpURLConnection.HTTP_UNAUTHORIZED);
String reply = response.readEntity(String.class);
System.out.printf("Reply: %s\n", reply);
callEchoAndExpectUnauthorized(token);
}

@RunAsClient
Expand All @@ -122,17 +113,8 @@ public void callEchoBadSigner() throws Exception {
HashSet<TokenUtils.InvalidClaims> invalidFields = new HashSet<>();
invalidFields.add(TokenUtils.InvalidClaims.SIGNER);
String token = TokenUtils.generateTokenString("/Token1.json", invalidFields);
System.out.printf("jwt: %s\n", token);

String uri = baseURL.toExternalForm() + "endp/echo";
WebTarget echoEndpointTarget = ClientBuilder.newClient()
.target(uri)
.queryParam("input", "hello");
Response response =
echoEndpointTarget.request(TEXT_PLAIN).header(HttpHeaders.AUTHORIZATION, "Bearer " + token).get();
Assert.assertEquals(response.getStatus(), HttpURLConnection.HTTP_UNAUTHORIZED);
String reply = response.readEntity(String.class);
System.out.printf("Reply: %s\n", reply);
callEchoAndExpectUnauthorized(token);
}

@RunAsClient
Expand All @@ -141,14 +123,19 @@ public void callEchoBadSignerAlg() throws Exception {
HashSet<TokenUtils.InvalidClaims> invalidFields = new HashSet<>();
invalidFields.add(TokenUtils.InvalidClaims.ALG);
String token = TokenUtils.generateTokenString("/Token1.json", invalidFields);

callEchoAndExpectUnauthorized(token);
}

private void callEchoAndExpectUnauthorized(String token) throws Exception {
System.out.printf("jwt: %s\n", token);

String uri = baseURL.toExternalForm() + "endp/echo";
WebTarget echoEndpointTarget = ClientBuilder.newClient()
.target(uri)
.queryParam("input", "hello");
Response response =
echoEndpointTarget.request(TEXT_PLAIN).header(HttpHeaders.AUTHORIZATION, "Bearer " + token).get();
Response response = echoEndpointTarget.request(TEXT_PLAIN)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + token).get();
Assert.assertEquals(response.getStatus(), HttpURLConnection.HTTP_UNAUTHORIZED);
String reply = response.readEntity(String.class);
System.out.printf("Reply: %s\n", reply);
Expand Down
@@ -1,5 +1,5 @@
#
# Copyright (c) 2011-2017 Contributors to the Eclipse Foundation
# Copyright (c) 2011-2022 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
Expand All @@ -20,3 +20,4 @@
# A reference to the publicKey4k.pem contents embedded location
mp.jwt.verify.publickey.location=/publicKey.pem
mp.jwt.verify.issuer=https://server.example.com
mp.jwt.verify.token.age=4

0 comments on commit ed58fb0

Please sign in to comment.