Repository: gravitee-io/graviteeio-access-management
Pull request #477 (2018-12-15 14:24:32)

fix(oauth2): use client_id as jwt client claim value
Fixing issue #476 


Patch:
diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/src/main/java/io/gravitee/am/gateway/handler/oauth2/token/impl/TokenServiceImpl.java b/gravitee-am-gateway/gravitee-am-gateway-handler/src/main/java/io/gravitee/am/gateway/handler/oauth2/token/impl/TokenServiceImpl.java
index 61db8d1c51..8157cd30d6 100644
--- a/gravitee-am-gateway/gravitee-am-gateway-handler/src/main/java/io/gravitee/am/gateway/handler/oauth2/token/impl/TokenServiceImpl.java
+++ b/gravitee-am-gateway/gravitee-am-gateway-handler/src/main/java/io/gravitee/am/gateway/handler/oauth2/token/impl/TokenServiceImpl.java
@@ -168,7 +168,7 @@ public class TokenServiceImpl implements TokenService {
         accessToken.setId(UUID.random().toString());
         accessToken.setToken(UUID.random().toString());
         accessToken.setDomain(client.getDomain());
-        accessToken.setClient(client.getId());
+        accessToken.setClient(client.getClientId());
         accessToken.setSubject(endUser != null ? endUser.getId() : null);
         accessToken.setCreatedAt(new Date());
         accessToken.setExpireAt(new Date(System.currentTimeMillis() + (getAccessTokenValiditySeconds(client) * 1000L)));
@@ -198,7 +198,7 @@ public class TokenServiceImpl implements TokenService {
         refreshToken.setId(UUID.random().toString());
         refreshToken.setToken(UUID.random().toString());
         refreshToken.setDomain(client.getDomain());
-        refreshToken.setClient(client.getId());
+        refreshToken.setClient(client.getClientId());
         refreshToken.setSubject(endUser != null ? endUser.getId() : null);
         refreshToken.setCreatedAt(new Date());
         refreshToken.setExpireAt(new Date(System.currentTimeMillis() + (getRefreshTokenValiditySeconds(client) * 1000L)));
diff --git a/postman/graviteeam-collection b/postman/graviteeam-collection
index d4c7ea7b23..35adc2325e 100644
--- a/postman/graviteeam-collection
+++ b/postman/graviteeam-collection
@@ -1,6 +1,6 @@
 {
 	"info": {
-		"_postman_id": "7020629d-e044-4769-b2ae-7648a5d35520",
+		"_postman_id": "34dfd549-9129-42ee-ba6f-505e06b6458c",
 		"name": "Gravitee.io AM",
 		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
 	},
@@ -1357,11 +1357,16 @@
 									"script": {
 										"id": "462b93ec-a015-41b8-a1bf-8d5446fc31aa",
 										"exec": [
+											"function parseJwt (token) {",
+											"            var base64Url = token.split('.')[1];",
+											"            var base64 = base64Url.replace('-', '+').replace('_', '/');",
+											"            return JSON.parse(atob(base64));",
+											"        }",
+											"",
 											"pm.test(\"Status code is 200\", function () {",
 											"    pm.response.to.have.status(200);",
 											"});",
 											"",
-											"",
 											"pm.test(\"Has an access_token without refresh token\", function () {",
 											"    var body = pm.response.json();",
 											"    pm.expect(body).to.have.property('access_token');",
@@ -1371,6 +1376,10 @@
 											"    pm.expect(body).to.not.have.property('refresh_token');",
 											"    pm.expect(body).to.have.property('scope');",
 											"    pm.expect(body.scope).to.eql('scope1');",
+											"    ",
+											"    let jwt = parseJwt(body.access_token);",
+											"    ",
+											"    tests['Contains a sub claim'] = jwt.sub === 'my-client';",
 											"});"
 										],
 										"type": "text/javascript"
@@ -2690,7 +2699,10 @@
 												"value": "Basic bXktY2xpZW50Om15LWNsaWVudC1zZWNyZXQ="
 											}
 										],
-										"body": {},
+										"body": {
+											"mode": "raw",
+											"raw": ""
+										},
 										"url": {
 											"raw": "{{gateway_url}}/test/oauth/token?grant_type=authorization_code&code={{authorization_code}}&redirect_uri=http://localhost:4000/",
 											"host": [
@@ -3131,7 +3143,10 @@
 												"value": "Basic bXktY2xpZW50MjpteS1jbGllbnQtc2VjcmV0Mg=="
 											}
 										],
-										"body": {},
+										"body": {
+											"mode": "raw",
+											"raw": ""
+										},
 										"url": {
 											"raw": "{{gateway_url}}/test/oauth/token?grant_type=authorization_code&code={{authorization_code}}&redirect_uri=http://localhost:5000/",
 											"host": [
@@ -3580,7 +3595,10 @@
 												"value": "Basic bXktY2xpZW50MjpteS1jbGllbnQtc2VjcmV0Mg=="
 											}
 										],
-										"body": {},
+										"body": {
+											"mode": "raw",
+											"raw": ""
+										},
 										"url": {
 											"raw": "{{gateway_url}}/test/oauth/token?grant_type=authorization_code&code={{authorization_code}}&redirect_uri=http://localhost:4000/",
 											"host": [
@@ -4674,7 +4692,10 @@
 												"value": "Basic bXktY2xpZW50MjpteS1jbGllbnQtc2VjcmV0Mg=="
 											}
 										],
-										"body": {},
+										"body": {
+											"mode": "raw",
+											"raw": ""
+										},
 										"url": {
 											"raw": "{{gateway_url}}/test/oauth/token?grant_type=authorization_code&code={{authorization_code}}&redirect_uri=http://localhost:4000/",
 											"host": [
@@ -5128,7 +5149,10 @@
 												"value": "Basic bXktY2xpZW50MjpteS1jbGllbnQtc2VjcmV0Mg=="
 											}
 										],
-										"body": {},
+										"body": {
+											"mode": "raw",
+											"raw": ""
+										},
 										"url": {
 											"raw": "{{gateway_url}}/test/oauth/token?grant_type=authorization_code&code={{authorization_code}}&redirect_uri=http://localhost:4000/",
 											"host": [
@@ -5582,7 +5606,10 @@
 												"value": "Basic bXktY2xpZW50MjpteS1jbGllbnQtc2VjcmV0Mg=="
 											}
 										],
-										"body": {},
+										"body": {
+											"mode": "raw",
+											"raw": ""
+										},
 										"url": {
 											"raw": "{{gateway_url}}/test/oauth/token?grant_type=authorization_code&code={{authorization_code}}&redirect_uri=http://localhost:4000/&code_verifier=qsdqsdqsdqsqsd",
 											"host": [
@@ -6040,7 +6067,10 @@
 												"value": "Basic bXktY2xpZW50MjpteS1jbGllbnQtc2VjcmV0Mg=="
 											}
 										],
-										"body": {},
+										"body": {
+											"mode": "raw",
+											"raw": ""
+										},
 										"url": {
 											"raw": "{{gateway_url}}/test/oauth/token?grant_type=authorization_code&code={{authorization_code}}&redirect_uri=http://localhost:4000/&code_verifier=qsdqsdqsdqsqsd",
 											"host": [
@@ -6501,7 +6531,10 @@
 												"value": "Basic bXktY2xpZW50MjpteS1jbGllbnQtc2VjcmV0Mg=="
 											}
 										],
-										"body": {},
+										"body": {
+											"mode": "raw",
+											"raw": ""
+										},
 										"url": {
 											"raw": "{{gateway_url}}/test/oauth/token?grant_type=authorization_code&code={{authorization_code}}&redirect_uri=http://localhost:4000/&code_verifier=M25iVXpKU3puUjFaYWg3T1NDTDQtcW1ROUY5YXlwalNoc0hhakxifmZHag",
 											"host": [
@@ -6962,7 +6995,10 @@
 												"value": "Basic bXktY2xpZW50MjpteS1jbGllbnQtc2VjcmV0Mg=="
 											}
 										],
-										"body": {},
+										"body": {
+											"mode": "raw",
+											"raw": ""
+										},
 										"url": {
 											"raw": "{{gateway_url}}/test/oauth/token?grant_type=authorization_code&code={{authorization_code}}&redirect_uri=http://localhost:4000/&code_verifier=qjrzSW9gMiUgpUvqgEPE4_-8swvyCtfOVvg55o5S_es",
 											"host": [
@@ -7756,7 +7792,10 @@
 												"value": "Basic bXktY2xpZW50MjpteS1jbGllbnQtc2VjcmV0Mg=="
 											}
 										],
-										"body": {},
+										"body": {
+											"mode": "raw",
+											"raw": ""
+										},
 										"url": {
 											"raw": "{{gateway_url}}/test/oauth/token?grant_type=authorization_code&redirect_uri=http://localhost:5000/",
 											"host": [
@@ -7817,7 +7856,10 @@
 									"request": {
 										"method": "POST",
 										"header": [],
-										"body": {},
+										"body": {
+											"mode": "raw",
+											"raw": ""
+										},
 										"url": {
 											"raw": "{{gateway_url}}/test/oauth/token?grant_type=authorization_code&redirect_uri=http://localhost:5000/",
 											"host": [


Test patch:
diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/src/test/java/io/gravitee/am/gateway/handler/oauth2/token/TokenServiceTest.java b/gravitee-am-gateway/gravitee-am-gateway-handler/src/test/java/io/gravitee/am/gateway/handler/oauth2/token/TokenServiceTest.java
index 22adf46fa7..14c531fc8c 100644
--- a/gravitee-am-gateway/gravitee-am-gateway-handler/src/test/java/io/gravitee/am/gateway/handler/oauth2/token/TokenServiceTest.java
+++ b/gravitee-am-gateway/gravitee-am-gateway-handler/src/test/java/io/gravitee/am/gateway/handler/oauth2/token/TokenServiceTest.java
@@ -30,8 +30,10 @@ import io.reactivex.Completable;
 import io.reactivex.Maybe;
 import io.reactivex.Single;
 import io.reactivex.observers.TestObserver;
+import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.runners.MockitoJUnitRunner;
@@ -70,8 +72,10 @@ public class TokenServiceTest {
         Client client = new Client();
         client.setClientId("my-client-id");
 
+        ArgumentCaptor<io.gravitee.am.repository.oauth2.model.AccessToken> accessTokenCaptor = ArgumentCaptor.forClass(io.gravitee.am.repository.oauth2.model.AccessToken.class);
+
         when(jwtService.encode(any(), any(Client.class))).thenReturn(Single.just(""));
-        when(accessTokenRepository.create(any())).thenReturn(Single.just(new io.gravitee.am.repository.oauth2.model.AccessToken()));
+        when(accessTokenRepository.create(accessTokenCaptor.capture())).thenReturn(Single.just(new io.gravitee.am.repository.oauth2.model.AccessToken()));
         when(tokenEnhancer.enhance(any(), any(), any(), any())).thenReturn(Single.just(new AccessToken("token-id")));
 
         TestObserver<Token> testObserver = tokenService.create(oAuth2Request, client, null).test();
@@ -81,6 +85,8 @@ public class TokenServiceTest {
         verify(accessTokenRepository, times(1)).create(any());
         verify(accessTokenRepository, never()).delete(anyString());
         verify(refreshTokenRepository, never()).delete(anyString());
+
+        Assert.assertTrue("client should be client_id", client.getClientId().equals(accessTokenCaptor.getValue().getClient()));
     }
 
     @Test