From d643fb285fa7173357627f2756ec42fd56cb7145 Mon Sep 17 00:00:00 2001 From: Ryan Liang <109499885+RyanL1997@users.noreply.github.com> Date: Fri, 4 Aug 2023 22:57:18 -0700 Subject: [PATCH] [Feature/Extension] Restrict OBO token's usage for certain endpoints (#3008) Signed-off-by: Ryan Liang --- .../http/OnBehalfOfJwtAuthenticationTest.java | 84 +++++++++++-------- .../framework/cluster/TestRestClient.java | 20 +++++ .../onbehalf/CreateOnBehalfOfTokenAction.java | 2 +- .../security/authtoken/jwt/JwtVendor.java | 3 + .../security/filter/SecurityRestFilter.java | 1 - .../http/OnBehalfOfAuthenticator.java | 29 ++++++- .../security/ssl/util/ExceptionUtils.java | 4 + .../security/authtoken/jwt/JwtVendorTest.java | 1 + .../http/OnBehalfOfAuthenticatorTest.java | 44 ++++++---- 9 files changed, 134 insertions(+), 54 deletions(-) diff --git a/src/integrationTest/java/org/opensearch/security/http/OnBehalfOfJwtAuthenticationTest.java b/src/integrationTest/java/org/opensearch/security/http/OnBehalfOfJwtAuthenticationTest.java index 9afebe457b..4e90044ec4 100644 --- a/src/integrationTest/java/org/opensearch/security/http/OnBehalfOfJwtAuthenticationTest.java +++ b/src/integrationTest/java/org/opensearch/security/http/OnBehalfOfJwtAuthenticationTest.java @@ -19,6 +19,7 @@ import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.message.BasicHeader; +import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; @@ -55,8 +56,15 @@ public class OnBehalfOfJwtAuthenticationTest { private static final String encryptionKey = Base64.getEncoder().encodeToString("encryptionKey".getBytes(StandardCharsets.UTF_8)); public static final String ADMIN_USER_NAME = "admin"; public static final String DEFAULT_PASSWORD = "secret"; + public static final String NEW_PASSWORD = "testPassword123!!"; public static final String OBO_TOKEN_REASON = "{\"reason\":\"Test generation\"}"; public static final String OBO_ENDPOINT_PREFIX = "_plugins/_security/api/user/onbehalfof"; + public static final String OBO_REASON = "{\"reason\":\"Testing\", \"service\":\"self-issued\"}"; + public static final String CURRENT_AND_NEW_PASSWORDS = "{ \"current_password\": \"" + + DEFAULT_PASSWORD + + "\", \"password\": \"" + + NEW_PASSWORD + + "\" }"; @ClassRule public static final LocalCluster cluster = new LocalCluster.Builder().clusterManager(ClusterManager.SINGLENODE) @@ -76,60 +84,62 @@ public class OnBehalfOfJwtAuthenticationTest { @Test public void shouldAuthenticateWithOBOTokenEndPoint() { - Header adminOboAuthHeader; - - try (TestRestClient client = cluster.getRestClient(ADMIN_USER_NAME, DEFAULT_PASSWORD)) { - - client.assertCorrectCredentials(ADMIN_USER_NAME); - - TestRestClient.HttpResponse response = client.postJson(OBO_ENDPOINT_PREFIX, OBO_TOKEN_REASON); - response.assertStatusCode(200); - - Map oboEndPointResponse = response.getBodyAs(Map.class); - assertThat(oboEndPointResponse, allOf(aMapWithSize(3), hasKey("user"), hasKey("onBehalfOfToken"), hasKey("duration"))); + String oboToken = generateOboToken(ADMIN_USER_NAME, DEFAULT_PASSWORD); + Header adminOboAuthHeader = new BasicHeader("Authorization", "Bearer " + oboToken); + authenticateWithOboToken(adminOboAuthHeader, ADMIN_USER_NAME, 200); + } - String encodedOboTokenStr = oboEndPointResponse.get("onBehalfOfToken").toString(); + @Test + public void shouldNotAuthenticateWithATemperedOBOToken() { + String oboToken = generateOboToken(ADMIN_USER_NAME, DEFAULT_PASSWORD); + oboToken = oboToken.substring(0, oboToken.length() - 1); // tampering the token + Header adminOboAuthHeader = new BasicHeader("Authorization", "Bearer " + oboToken); + authenticateWithOboToken(adminOboAuthHeader, ADMIN_USER_NAME, 401); + } - adminOboAuthHeader = new BasicHeader("Authorization", "Bearer " + encodedOboTokenStr); - } + @Test + public void shouldNotAuthenticateForUsingOBOTokenToAccessOBOEndpoint() { + String oboToken = generateOboToken(ADMIN_USER_NAME, DEFAULT_PASSWORD); + Header adminOboAuthHeader = new BasicHeader("Authorization", "Bearer " + oboToken); try (TestRestClient client = cluster.getRestClient(adminOboAuthHeader)) { - - TestRestClient.HttpResponse response = client.getAuthInfo(); - response.assertStatusCode(200); - - String username = response.getTextFromJsonBody(POINTER_USERNAME); - assertThat(username, equalTo(ADMIN_USER_NAME)); + TestRestClient.HttpResponse response = client.getOBOTokenFromOboEndpoint(OBO_REASON, adminOboAuthHeader); + response.assertStatusCode(401); } } @Test - public void shouldNotAuthenticateWithATemperedOBOToken() { - Header adminOboAuthHeader; + public void shouldNotAuthenticateForUsingOBOTokenToAccessAccountEndpoint() { + String oboToken = generateOboToken(ADMIN_USER_NAME, DEFAULT_PASSWORD); + Header adminOboAuthHeader = new BasicHeader("Authorization", "Bearer " + oboToken); - try (TestRestClient client = cluster.getRestClient(ADMIN_USER_NAME, DEFAULT_PASSWORD)) { - - client.assertCorrectCredentials(ADMIN_USER_NAME); + try (TestRestClient client = cluster.getRestClient(adminOboAuthHeader)) { + TestRestClient.HttpResponse response = client.changeInternalUserPassword(CURRENT_AND_NEW_PASSWORDS, adminOboAuthHeader); + response.assertStatusCode(401); + } + } + private String generateOboToken(String username, String password) { + try (TestRestClient client = cluster.getRestClient(username, password)) { + client.assertCorrectCredentials(username); TestRestClient.HttpResponse response = client.postJson(OBO_ENDPOINT_PREFIX, OBO_TOKEN_REASON); response.assertStatusCode(200); - Map oboEndPointResponse = response.getBodyAs(Map.class); assertThat(oboEndPointResponse, allOf(aMapWithSize(3), hasKey("user"), hasKey("onBehalfOfToken"), hasKey("duration"))); - - String encodedOboTokenStr = oboEndPointResponse.get("onBehalfOfToken").toString(); - StringBuilder stringBuilder = new StringBuilder(encodedOboTokenStr); - stringBuilder.deleteCharAt(encodedOboTokenStr.length() - 1); - String temperedOboTokenStr = stringBuilder.toString(); - - adminOboAuthHeader = new BasicHeader("Authorization", "Bearer " + temperedOboTokenStr); + return oboEndPointResponse.get("onBehalfOfToken").toString(); } + } - try (TestRestClient client = cluster.getRestClient(adminOboAuthHeader)) { - + private void authenticateWithOboToken(Header authHeader, String expectedUsername, int expectedStatusCode) { + try (TestRestClient client = cluster.getRestClient(authHeader)) { TestRestClient.HttpResponse response = client.getAuthInfo(); - response.assertStatusCode(401); - response.getBody().contains("Unauthorized"); + response.assertStatusCode(expectedStatusCode); + if (expectedStatusCode == 200) { + String username = response.getTextFromJsonBody(POINTER_USERNAME); + assertThat(username, equalTo(expectedUsername)); + } else { + Assert.assertTrue(response.getBody().contains("Unauthorized")); + } } } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClient.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClient.java index f446cac933..e48acafd2f 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClient.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClient.java @@ -135,6 +135,26 @@ public HttpResponse getAuthInfo(Header... headers) { return executeRequest(new HttpGet(getHttpServerUri() + "/_opendistro/_security/authinfo?pretty"), headers); } + public HttpResponse getOBOTokenFromOboEndpoint(String jsonData, Header... headers) { + try { + HttpPost httpPost = new HttpPost(new URIBuilder(getHttpServerUri() + "/_plugins/_security/api/user/onbehalfof?pretty").build()); + httpPost.setEntity(toStringEntity(jsonData)); + return executeRequest(httpPost, mergeHeaders(CONTENT_TYPE_JSON, headers)); + } catch (URISyntaxException ex) { + throw new RuntimeException("Incorrect URI syntax", ex); + } + } + + public HttpResponse changeInternalUserPassword(String jsonData, Header... headers) { + try { + HttpPut httpPut = new HttpPut(new URIBuilder(getHttpServerUri() + "/_plugins/_security/api/account?pretty").build()); + httpPut.setEntity(toStringEntity(jsonData)); + return executeRequest(httpPut, mergeHeaders(CONTENT_TYPE_JSON, headers)); + } catch (URISyntaxException ex) { + throw new RuntimeException("Incorrect URI syntax", ex); + } + } + public void assertCorrectCredentials(String expectedUserName) { HttpResponse response = getAuthInfo(); assertThat(response, notNullValue()); diff --git a/src/main/java/org/opensearch/security/action/onbehalf/CreateOnBehalfOfTokenAction.java b/src/main/java/org/opensearch/security/action/onbehalf/CreateOnBehalfOfTokenAction.java index be12de5bae..69c51482b2 100644 --- a/src/main/java/org/opensearch/security/action/onbehalf/CreateOnBehalfOfTokenAction.java +++ b/src/main/java/org/opensearch/security/action/onbehalf/CreateOnBehalfOfTokenAction.java @@ -24,7 +24,7 @@ import org.opensearch.client.node.NodeClient; import org.opensearch.cluster.service.ClusterService; import org.opensearch.common.settings.Settings; -import org.opensearch.common.transport.TransportAddress; +import org.opensearch.core.common.transport.TransportAddress; import org.opensearch.core.xcontent.XContentBuilder; import org.opensearch.rest.BaseRestHandler; import org.opensearch.rest.BytesRestResponse; diff --git a/src/main/java/org/opensearch/security/authtoken/jwt/JwtVendor.java b/src/main/java/org/opensearch/security/authtoken/jwt/JwtVendor.java index 3cec339647..21d7caad57 100644 --- a/src/main/java/org/opensearch/security/authtoken/jwt/JwtVendor.java +++ b/src/main/java/org/opensearch/security/authtoken/jwt/JwtVendor.java @@ -105,6 +105,7 @@ public String createJwt( List roles, List backendRoles ) throws Exception { + String tokenIdentifier = "obo"; long timeMillis = timeProvider.getAsLong(); Instant now = Instant.ofEpochMilli(timeProvider.getAsLong()); @@ -112,6 +113,8 @@ public String createJwt( JwtClaims jwtClaims = new JwtClaims(); JwtToken jwt = new JwtToken(jwtClaims); + jwtClaims.setProperty("typ", tokenIdentifier); + jwtClaims.setIssuer(issuer); jwtClaims.setIssuedAt(timeMillis); diff --git a/src/main/java/org/opensearch/security/filter/SecurityRestFilter.java b/src/main/java/org/opensearch/security/filter/SecurityRestFilter.java index 54d98ffe13..9b06e15c5d 100644 --- a/src/main/java/org/opensearch/security/filter/SecurityRestFilter.java +++ b/src/main/java/org/opensearch/security/filter/SecurityRestFilter.java @@ -258,7 +258,6 @@ private boolean checkAndAuthenticateRequest(RestRequest request, RestChannel cha ); } } - return false; } diff --git a/src/main/java/org/opensearch/security/http/OnBehalfOfAuthenticator.java b/src/main/java/org/opensearch/security/http/OnBehalfOfAuthenticator.java index 00f69c55dc..f812cc97ee 100644 --- a/src/main/java/org/opensearch/security/http/OnBehalfOfAuthenticator.java +++ b/src/main/java/org/opensearch/security/http/OnBehalfOfAuthenticator.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Map.Entry; import java.util.Objects; +import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -28,6 +29,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.opensearch.OpenSearchException; import org.opensearch.OpenSearchSecurityException; import org.opensearch.SpecialPermission; import org.opensearch.common.settings.Settings; @@ -36,16 +38,26 @@ import org.opensearch.rest.RestRequest; import org.opensearch.security.auth.HTTPAuthenticator; import org.opensearch.security.authtoken.jwt.EncryptionDecryptionUtil; +import org.opensearch.security.ssl.util.ExceptionUtils; import org.opensearch.security.user.AuthCredentials; import org.opensearch.security.util.keyUtil; +import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; +import static org.opensearch.security.OpenSearchSecurityPlugin.PLUGINS_PREFIX; + public class OnBehalfOfAuthenticator implements HTTPAuthenticator { + private static final String REGEX_PATH_PREFIX = "/(" + LEGACY_OPENDISTRO_PREFIX + "|" + PLUGINS_PREFIX + ")/" + "(.*)"; + private static final Pattern PATTERN_PATH_PREFIX = Pattern.compile(REGEX_PATH_PREFIX); + private static final String ON_BEHALF_OF_SUFFIX = "api/user/onbehalfof"; + private static final String ACCOUNT_SUFFIX = "api/account"; + protected final Logger log = LogManager.getLogger(this.getClass()); private static final Pattern BEARER = Pattern.compile("^\\s*Bearer\\s.*", Pattern.CASE_INSENSITIVE); private static final String BEARER_PREFIX = "bearer "; - private static final String SUBJECT_CLAIM = "sub"; + private static final String TOKEN_TYPE_CLAIM = "typ"; + private static final String TOKEN_TYPE = "obo"; private final JwtParser jwtParser; private final String encryptionKey; @@ -168,6 +180,15 @@ private AuthCredentials extractCredentials0(final RestRequest request) { } try { + Matcher matcher = PATTERN_PATH_PREFIX.matcher(request.path()); + final String suffix = matcher.matches() ? matcher.group(2) : null; + if (request.method() == RestRequest.Method.POST && ON_BEHALF_OF_SUFFIX.equals(suffix) + || request.method() == RestRequest.Method.PUT && ACCOUNT_SUFFIX.equals(suffix)) { + final OpenSearchException exception = ExceptionUtils.invalidUsageOfOBOTokenException(); + log.error(exception.toString()); + return null; + } + final Claims claims = jwtParser.parseClaimsJws(jwtToken).getBody(); final String subject = claims.getSubject(); @@ -182,6 +203,12 @@ private AuthCredentials extractCredentials0(final RestRequest request) { return null; } + final String tokenType = claims.get(TOKEN_TYPE_CLAIM).toString(); + if (!tokenType.equals(TOKEN_TYPE)) { + log.error("This toke is not verifying as an on-behalf-of token"); + return null; + } + List roles = extractSecurityRolesFromClaims(claims); String[] backendRoles = extractBackendRolesFromClaims(claims); diff --git a/src/main/java/org/opensearch/security/ssl/util/ExceptionUtils.java b/src/main/java/org/opensearch/security/ssl/util/ExceptionUtils.java index 9d6d3dade8..972f7ea035 100644 --- a/src/main/java/org/opensearch/security/ssl/util/ExceptionUtils.java +++ b/src/main/java/org/opensearch/security/ssl/util/ExceptionUtils.java @@ -64,6 +64,10 @@ public static OpenSearchException createBadHeaderException() { ); } + public static OpenSearchException invalidUsageOfOBOTokenException() { + return new OpenSearchException("On-Behalf-Of Token is not allowed to be used for accessing this endopoint."); + } + public static OpenSearchException createTransportClientNoLongerSupportedException() { return new OpenSearchException("Transport client authentication no longer supported."); } diff --git a/src/test/java/org/opensearch/security/authtoken/jwt/JwtVendorTest.java b/src/test/java/org/opensearch/security/authtoken/jwt/JwtVendorTest.java index a278a526b3..60ed365285 100644 --- a/src/test/java/org/opensearch/security/authtoken/jwt/JwtVendorTest.java +++ b/src/test/java/org/opensearch/security/authtoken/jwt/JwtVendorTest.java @@ -62,6 +62,7 @@ public void testCreateJwtWithRoles() throws Exception { JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(encodedJwt); JwtToken jwt = jwtConsumer.getJwtToken(); + Assert.assertEquals("obo", jwt.getClaim("typ")); Assert.assertEquals("cluster_0", jwt.getClaim("iss")); Assert.assertEquals("admin", jwt.getClaim("sub")); Assert.assertEquals("audience_0", jwt.getClaim("aud")); diff --git a/src/test/java/org/opensearch/security/http/OnBehalfOfAuthenticatorTest.java b/src/test/java/org/opensearch/security/http/OnBehalfOfAuthenticatorTest.java index d71fe54951..e9208ccac8 100644 --- a/src/test/java/org/opensearch/security/http/OnBehalfOfAuthenticatorTest.java +++ b/src/test/java/org/opensearch/security/http/OnBehalfOfAuthenticatorTest.java @@ -16,7 +16,6 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; -import java.util.List; import java.util.Map; import javax.crypto.SecretKey; @@ -52,7 +51,7 @@ public void testNoKey() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( null, claimsEncryptionKey, - Jwts.builder().setSubject("Leonard McCoy"), + Jwts.builder().claim("typ", "obo").setSubject("Leonard McCoy"), false ); Assert.fail("Expected a RuntimeException"); @@ -68,7 +67,7 @@ public void testEmptyKey() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( null, claimsEncryptionKey, - Jwts.builder().setSubject("Leonard McCoy"), + Jwts.builder().claim("typ", "obo").setSubject("Leonard McCoy"), false ); Assert.fail("Expected a RuntimeException"); @@ -84,7 +83,7 @@ public void testBadKey() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( BaseEncoding.base64().encode(new byte[] { 1, 3, 3, 4, 3, 6, 7, 8, 3, 10 }), claimsEncryptionKey, - Jwts.builder().setSubject("Leonard McCoy"), + Jwts.builder().claim("typ", "obo").setSubject("Leonard McCoy"), false ); Assert.fail("Expected a WeakKeyException"); @@ -120,6 +119,7 @@ public void testInvalid() throws Exception { @Test public void testDisabled() throws Exception { String jwsToken = Jwts.builder() + .claim("typ", "obo") .setSubject("Leonard McCoy") .setAudience("ext_0") .signWith(Keys.hmacShaKeyFor(Base64.getDecoder().decode(signingKeyB64Encoded)), SignatureAlgorithm.HS512) @@ -136,6 +136,7 @@ public void testDisabled() throws Exception { @Test public void testNonSpecifyOBOSetting() throws Exception { String jwsToken = Jwts.builder() + .claim("typ", "obo") .setSubject("Leonard McCoy") .setAudience("ext_0") .signWith(Keys.hmacShaKeyFor(Base64.getDecoder().decode(signingKeyB64Encoded)), SignatureAlgorithm.HS512) @@ -153,6 +154,7 @@ public void testNonSpecifyOBOSetting() throws Exception { public void testBearer() throws Exception { String jwsToken = Jwts.builder() + .claim("typ", "obo") .setSubject("Leonard McCoy") .setAudience("ext_0") .signWith(Keys.hmacShaKeyFor(Base64.getDecoder().decode(signingKeyB64Encoded)), SignatureAlgorithm.HS512) @@ -168,13 +170,14 @@ public void testBearer() throws Exception { Assert.assertEquals("Leonard McCoy", credentials.getUsername()); Assert.assertEquals(0, credentials.getSecurityRoles().size()); Assert.assertEquals(0, credentials.getBackendRoles().size()); - Assert.assertEquals(2, credentials.getAttributes().size()); + Assert.assertEquals(3, credentials.getAttributes().size()); } @Test public void testBearerWrongPosition() throws Exception { String jwsToken = Jwts.builder() + .claim("typ", "obo") .setSubject("Leonard McCoy") .setAudience("ext_0") .signWith(secretKey, SignatureAlgorithm.HS512) @@ -192,6 +195,7 @@ public void testBearerWrongPosition() throws Exception { @Test public void testBasicAuthHeader() throws Exception { String jwsToken = Jwts.builder() + .claim("typ", "obo") .setSubject("Leonard McCoy") .setAudience("ext_0") .signWith(secretKey, SignatureAlgorithm.HS512) @@ -207,11 +211,10 @@ public void testBasicAuthHeader() throws Exception { @Test public void testRoles() throws Exception { - List roles = List.of("IT", "HR"); final AuthCredentials credentials = extractCredentialsFromJwtHeader( signingKeyB64Encoded, claimsEncryptionKey, - Jwts.builder().setSubject("Leonard McCoy").claim("dr", "role1,role2").setAudience("svc1"), + Jwts.builder().claim("typ", "obo").setSubject("Leonard McCoy").claim("dr", "role1,role2").setAudience("svc1"), true ); @@ -221,13 +224,26 @@ public void testRoles() throws Exception { Assert.assertEquals(0, credentials.getBackendRoles().size()); } + @Test + public void testNoTokenType() throws Exception { + + final AuthCredentials credentials = extractCredentialsFromJwtHeader( + signingKeyB64Encoded, + claimsEncryptionKey, + Jwts.builder().setSubject("Leonard McCoy").claim("dr", "role1,role2").setAudience("svc1"), + true + ); + + Assert.assertNull(credentials); + } + @Test public void testNullClaim() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( signingKeyB64Encoded, claimsEncryptionKey, - Jwts.builder().setSubject("Leonard McCoy").claim("dr", null).setAudience("svc1"), + Jwts.builder().claim("typ", "obo").setSubject("Leonard McCoy").claim("dr", null).setAudience("svc1"), false ); @@ -242,7 +258,7 @@ public void testNonStringClaim() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( signingKeyB64Encoded, claimsEncryptionKey, - Jwts.builder().setSubject("Leonard McCoy").claim("dr", 123L).setAudience("svc1"), + Jwts.builder().claim("typ", "obo").setSubject("Leonard McCoy").claim("dr", 123L).setAudience("svc1"), true ); @@ -258,7 +274,7 @@ public void testRolesMissing() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( signingKeyB64Encoded, claimsEncryptionKey, - Jwts.builder().setSubject("Leonard McCoy").setAudience("svc1"), + Jwts.builder().claim("typ", "obo").setSubject("Leonard McCoy").setAudience("svc1"), false ); @@ -274,7 +290,7 @@ public void testWrongSubjectKey() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( signingKeyB64Encoded, claimsEncryptionKey, - Jwts.builder().claim("roles", "role1,role2").claim("asub", "Dr. Who").setAudience("svc1"), + Jwts.builder().claim("typ", "obo").claim("roles", "role1,role2").claim("asub", "Dr. Who").setAudience("svc1"), false ); @@ -287,7 +303,7 @@ public void testExp() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( signingKeyB64Encoded, claimsEncryptionKey, - Jwts.builder().setSubject("Expired").setExpiration(new Date(100)), + Jwts.builder().claim("typ", "obo").setSubject("Expired").setExpiration(new Date(100)), false ); @@ -300,7 +316,7 @@ public void testNbf() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( signingKeyB64Encoded, claimsEncryptionKey, - Jwts.builder().setSubject("Expired").setNotBefore(new Date(System.currentTimeMillis() + (1000 * 36000))), + Jwts.builder().claim("typ", "obo").setSubject("Expired").setNotBefore(new Date(System.currentTimeMillis() + (1000 * 36000))), false ); @@ -311,7 +327,7 @@ public void testNbf() throws Exception { public void testRolesArray() throws Exception { JwtBuilder builder = Jwts.builder() - .setPayload("{" + "\"sub\": \"Cluster_0\"," + "\"aud\": \"ext_0\"," + "\"dr\": \"a,b,3rd\"" + "}"); + .setPayload("{" + "\"typ\": \"obo\"," + "\"sub\": \"Cluster_0\"," + "\"aud\": \"ext_0\"," + "\"dr\": \"a,b,3rd\"" + "}"); final AuthCredentials credentials = extractCredentialsFromJwtHeader(signingKeyB64Encoded, claimsEncryptionKey, builder, true);