diff --git a/classes/ClientAuthChecker.php b/classes/ClientAuthChecker.php
index 497f9bbc385eb2e8b3845cb6c8532b3474904f4b..89598f8acc49bbea450eb498e73fd93ff2f4458d 100644
--- a/classes/ClientAuthChecker.php
+++ b/classes/ClientAuthChecker.php
@@ -15,19 +15,19 @@ class ClientAuthChecker {
         $this->locator = $locator;
     }
 
-    public function validateClientAuth(): void {
+    public function validateClientAuth(array $headers): BrowserBasedOAuth2Client {
 
-        $basic = $this->getBasicAuthArray();
+        $basic = $this->getBasicAuthArray($headers);
 
         $clientId = $basic[0];
         $clientSecret = $basic[1];
 
-        $this->locator->getBrowserBasedOAuth2ClientByIdAndSecret($clientId, $clientSecret);
+        return $this->locator->getBrowserBasedOAuth2ClientByIdAndSecret($clientId, $clientSecret);
     }
 
-    public function validateCliClientAuth(): CliOAuth2Client {
+    public function validateCliClientAuth(array $headers): CliOAuth2Client {
 
-        $basic = $this->getBasicAuthArray();
+        $basic = $this->getBasicAuthArray($headers);
 
         $clientId = $basic[0];
         $clientSecret = $basic[1];
@@ -35,8 +35,7 @@ class ClientAuthChecker {
         return $this->locator->getCliClientByIdAndSecret($clientId, $clientSecret);
     }
 
-    private function getBasicAuthArray(): array {
-        $headers = apache_request_headers();
+    private function getBasicAuthArray($headers): array {
 
         if (!isset($headers['Authorization'])) {
             throw new UnauthorizedException("Missing Authorization header");
diff --git a/classes/ClientsLocator.php b/classes/ClientsLocator.php
index 5ebe6230fff1552dd4193caba0c408fd84412b73..184f39cf6e21fee6f547883fe5efc5974844f01e 100644
--- a/classes/ClientsLocator.php
+++ b/classes/ClientsLocator.php
@@ -31,7 +31,7 @@ trait ClientsLocator {
     private function getClientConfigFromListByIdAndSecret(array $clients, string $clientId, string $secret): object {
         $client = $this->getClientConfigFromListById($clients, $clientId);
         $secretHash = hash('sha256', $secret);
-        if ($client->secretHash !== $secretHash) {
+        if ($client->secret !== $secretHash) {
             throw new UnauthorizedException("Wrong secret provided for client '$clientId'");
         }
         return $client;
diff --git a/classes/JWKSHandler.php b/classes/JWKSHandler.php
index d7598164ce1be87705f729caff54f3969bc53675..2f2d5bc96748730a8a1e592114c5827e1810992b 100644
--- a/classes/JWKSHandler.php
+++ b/classes/JWKSHandler.php
@@ -79,8 +79,10 @@ class JWKSHandler {
 
     public function loadAllJWKS(): array {
 
-        foreach ($this->locator->config->jwksUrls as $url) {
-            $this->loadJWKS($url);
+        foreach ($this->locator->getBrowserBasedOAuth2Clients() as $client) {
+            if ($client->jwks !== null) {
+                $this->loadJWKS($client->jwks);
+            }
         }
 
         $dao = $this->locator->getJWKSDAO();
diff --git a/classes/Locator.php b/classes/Locator.php
index 956b273cc485b26d45af2e6da0d54c6ea75cd4cf..4b34c0c888642f12204180881d88799b3da10fac 100644
--- a/classes/Locator.php
+++ b/classes/Locator.php
@@ -74,18 +74,10 @@ class Locator {
         }
     }
 
-    public function getCallbackHandler(): CallbackHandler {
-        return new CallbackHandler($this);
-    }
-
     public function getUserHandler(): UserHandler {
         return new UserHandler($this);
     }
 
-    public function getMailSender(): MailSender {
-        return new MailSender($_SERVER['HTTP_HOST'], $this->getBasePath());
-    }
-
     public function getOAuth2RequestHandler(): OAuth2RequestHandler {
         return new OAuth2RequestHandler($this);
     }
diff --git a/classes/OAuth2RequestHandler.php b/classes/OAuth2RequestHandler.php
index 084d43c2c7f8cb7ef8353cfb73ab14ebc78c240a..2b45d367145fccd8a32d64a99aa4f495748738a4 100644
--- a/classes/OAuth2RequestHandler.php
+++ b/classes/OAuth2RequestHandler.php
@@ -76,7 +76,12 @@ class OAuth2RequestHandler {
         if ($state !== null) {
             // Authorization code grant flow
             $redirectUrl = $session->getOAuth2RequestData()->redirectUrl
-                    . '?code=' . $code . '&scope=profile&state=' . $state;
+                    . '?code=' . $code;
+            $scope = $tokenData->scope;
+            if ($scope !== null && count($scope) > 0) {
+                $redirectUrl .= '&scope=' . implode("%20", $scope);
+            }
+            $redirectUrl .= '&state=' . $state;
         } else {
             // Implicit grant flow
             $idToken = $this->locator->getTokenBuilder()->getIdToken($tokenData, function(& $jwt) use($nonce) {
@@ -88,9 +93,27 @@ class OAuth2RequestHandler {
         return $redirectUrl;
     }
 
-    public function handleGetTokenFromCodeRequest($params): array {
+    public function handleAccessTokenRequest(array $params, array $headers): array {
+
+        if ($params['grant_type'] === null) {
+            throw new \RAP\BadRequestException("grant_type is required");
+        }
+
+        switch ($params['grant_type']) {
+            case "authorization_code":
+                return $this->handleGetTokenFromCodeRequest($params, $headers);
+            case "client_credentials":
+                return $this->handleClientCredentialsRequest($headers);
+            case "refresh_token":
+                return $this->handleRefreshTokenRequest($params, $headers);
+            default:
+                throw new \RAP\BadRequestException("Unsupported grant type " . $params['grant_type']);
+        }
+    }
+
+    private function handleGetTokenFromCodeRequest(array $params, array $headers): array {
 
-        $this->locator->getClientAuthChecker()->validateClientAuth();
+        $this->locator->getClientAuthChecker()->validateClientAuth($headers);
 
         if ($params['code'] === null) {
             throw new BadRequestException("code id is required");
@@ -120,9 +143,9 @@ class OAuth2RequestHandler {
         return $response;
     }
 
-    public function handleClientCredentialsRequest($params): array {
+    private function handleClientCredentialsRequest(array $headers): array {
 
-        $client = $this->locator->getClientAuthChecker()->validateCliClientAuth();
+        $client = $this->locator->getClientAuthChecker()->validateCliClientAuth($headers);
 
         $accessTokenData = new AccessTokenData();
         $accessTokenData->clientId = $client->id;
@@ -133,9 +156,9 @@ class OAuth2RequestHandler {
         return $this->getAccessTokenResponse($accessTokenData, false);
     }
 
-    public function handleRefreshTokenRequest($params): array {
+    private function handleRefreshTokenRequest(array $params, array $headers): array {
 
-        $this->locator->getClientAuthChecker()->validateClientAuth();
+        $this->locator->getClientAuthChecker()->validateClientAuth($headers);
 
         if ($params['refresh_token'] === null) {
             throw new BadRequestException("refresh_token is required");
diff --git a/classes/TokenBuilder.php b/classes/TokenBuilder.php
index e64162d936305e9d695c2094a7c5f2d1ad469795..912c13dea92f5e622d6276fcb45138e2d502ae40 100644
--- a/classes/TokenBuilder.php
+++ b/classes/TokenBuilder.php
@@ -53,7 +53,7 @@ class TokenBuilder {
         return $payloadArr;
     }
 
-    public function getAccessToken(AccessTokenData $tokenData, \Closure $jwtCustomizer = null) {
+    public function getAccessToken(AccessTokenData $tokenData, \Closure $jwtCustomizer = null): string {
 
         $keyPair = $this->locator->getJWKSDAO()->getNewestKeyPair();
 
@@ -95,11 +95,13 @@ class TokenBuilder {
 
         $audiences = [$tokenData->clientId];
 
-        foreach ($tokenData->scope as $scope) {
-            if (array_key_exists($scope, $client->scopeAudienceMap)) {
-                $audience = $client->scopeAudienceMap[$scope];
-                if (!in_array($audience, $audiences)) {
-                    array_push($audiences, $audience);
+        if ($client->scopeAudienceMap !== null) {
+            foreach ($tokenData->scope as $scope) {
+                if (array_key_exists($scope, $client->scopeAudienceMap)) {
+                    $audience = $client->scopeAudienceMap[$scope];
+                    if (!in_array($audience, $audiences)) {
+                        array_push($audiences, $audience);
+                    }
                 }
             }
         }
diff --git a/config-example.yaml b/config-example.yaml
index fcd8cdb97e965b761012abff8f2c7ed7d8b2904b..a850423765872916b1e03d384932a5bb7ed80626 100644
--- a/config-example.yaml
+++ b/config-example.yaml
@@ -52,7 +52,7 @@ tokenIssuer:
 clients:
   - label: "GMS Test (localhost)"
     id: gms
-    secret: "XXXXXX"
+    secret: 2a97516c354b68848cdbd8f54a226a0a55b21ed138e207ad6c5cbb9c00aa5aea
     redirect: http://localhost:8082/gms/login
     scope: "openid email"
     home: http://localhost:8082/gms
@@ -62,7 +62,7 @@ clients:
     jwks:
   - label: "Asiago Astrophysical Observatory (localhost)"
     id: aao-dev
-    secret: "XXXXXX"
+    secret: 2a97516c354b68848cdbd8f54a226a0a55b21ed138e207ad6c5cbb9c00aa5aea
     redirect: http://localhost:8081/aao/login
     scope: "openid read:userspace write:userspace read:fileserver write:fileserver read:gms"
     home: http://localhost:8081/aao
@@ -72,6 +72,6 @@ clients:
     jwks: http://localhost:8081/aao/jwks
 cliClients:
   - id: gms_cli
-    secret: "XXXXXX"
+    secret: 2a97516c354b68848cdbd8f54a226a0a55b21ed138e207ad6c5cbb9c00aa5aea
     scope: "read:gms write:gms read:rap"
     audience: gms
\ No newline at end of file
diff --git a/include/front-controller.php b/include/front-controller.php
index b7f9b2cd17b324f0fd73ce0a21c356472e82a250..56b2021328db081c0060904d57a757fa96852529 100644
--- a/include/front-controller.php
+++ b/include/front-controller.php
@@ -102,25 +102,10 @@ Flight::route('POST /auth/oauth2/token', function() {
         "scope" => filter_input(INPUT_POST, "scope", FILTER_SANITIZE_STRING)
     ];
 
-    if ($params['grant_type'] === null) {
-        throw new \RAP\BadRequestException("grant_type is required");
-    }
+    $headers = apache_request_headers();
 
     $requestHandler = new \RAP\OAuth2RequestHandler($locator);
-
-    switch ($params['grant_type']) {
-        case "authorization_code":
-            $token = $requestHandler->handleGetTokenFromCodeRequest($params);
-            break;
-        case "client_credentials":
-            $token = $requestHandler->handleClientCredentialsRequest($params);
-            break;
-        case "refresh_token":
-            $token = $requestHandler->handleRefreshTokenRequest($params);
-            break;
-        default:
-            throw new \RAP\BadRequestException("Unsupported grant type " . $params['grant_type']);
-    }
+    $token = $requestHandler->handleAccessTokenRequest($params, $headers);
 
     Flight::json($token);
 });
diff --git a/tests/ClientAuthCheckerTest.php b/tests/ClientAuthCheckerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f98919a951e1d25e2c3f9eb0c46fc59ec0f06385
--- /dev/null
+++ b/tests/ClientAuthCheckerTest.php
@@ -0,0 +1,33 @@
+<?php
+
+use PHPUnit\Framework\TestCase;
+
+class ClientAuthCheckerTest extends TestCase {
+
+    public function testValidateClientAuth() {
+
+        $locatorStub = $this->createMock(\RAP\Locator::class);
+
+        $locatorStub->expects($this->once())
+                ->method('getBrowserBasedOAuth2ClientByIdAndSecret')->with('client', 'secret');
+
+        $authChecker = new \RAP\ClientAuthChecker($locatorStub);
+        $authChecker->validateClientAuth([
+            "Authorization" => "Basic " . base64_encode("client:secret")
+        ]);
+    }
+
+    public function testValidateCliClientAuth() {
+
+        $locatorStub = $this->createMock(\RAP\Locator::class);
+
+        $locatorStub->expects($this->once())
+                ->method('getCliClientByIdAndSecret')->with('client', 'secret');
+
+        $authChecker = new \RAP\ClientAuthChecker($locatorStub);
+        $authChecker->validateCliClientAuth([
+            "Authorization" => "Basic " . base64_encode("client:secret")
+        ]);
+    }
+
+}
diff --git a/tests/LocatorTest.php b/tests/LocatorTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d33b8c7329fd3bc6d0c492b0352bce26016c78cd
--- /dev/null
+++ b/tests/LocatorTest.php
@@ -0,0 +1,36 @@
+<?php
+
+use PHPUnit\Framework\TestCase;
+
+class LocatorTest extends TestCase {
+
+    public function testLocator() {
+
+        define('ROOT', dirname(dirname(__FILE__)));
+
+        $config = yaml_parse_file(ROOT . '/config-example.yaml');
+        $config = json_decode(json_encode($config), FALSE);
+
+        $locator = new \RAP\Locator($config);
+
+        $this->assertNotNull($locator->getUserDAO());
+        $this->assertNotNull($locator->getJWKSDAO());
+        $this->assertNotNull($locator->getAccessTokenDAO());
+        $this->assertNotNull($locator->getRefreshTokenDAO());
+        $this->assertNotNull($locator->getUserHandler());
+        $this->assertNotNull($locator->getOAuth2RequestHandler());
+        $this->assertNotNull($locator->getTokenBuilder());
+        $this->assertNotNull($locator->getTokenChecker());
+        $this->assertNotNull($locator->getClientAuthChecker());
+        $this->assertNotNull($locator->getSession());
+        $this->assertNotNull($locator->getServiceLogger());
+        $this->assertNotNull($locator->getAuditLogger());
+        $this->assertNotNull($locator->getJWKSHandler());
+
+        $this->assertNotNull($locator->getBrowserBasedOAuth2Clients());
+        $this->assertNotNull($locator->getBrowserBasedOAuth2ClientById("gms", false));
+        $this->assertNotNull($locator->getBrowserBasedOAuth2ClientByIdAndSecret("gms", "demo"));
+        $this->assertNotNull($locator->getCliClientByIdAndSecret("gms_cli", "demo"));
+    }
+
+}
diff --git a/tests/OAuth2RequestHandlerTest.php b/tests/OAuth2RequestHandlerTest.php
index f970eede895acc7deb2992b96d721b3b8f45b9e8..16cd7235f3489f522d67a2b78a1f41982c52b067 100644
--- a/tests/OAuth2RequestHandlerTest.php
+++ b/tests/OAuth2RequestHandlerTest.php
@@ -105,4 +105,151 @@ final class OAuth2RequestHandlerTest extends TestCase {
         $this->assertEquals('id-token', $result['id_token']);
     }
 
+    public function testHandleGetTokenFromCodeRequest(): void {
+
+        $authCheckerStub = $this->createMock(\RAP\ClientAuthChecker::class);
+
+        $tokenData = new \RAP\AccessTokenData();
+        $tokenData->redirectUri = "redirect";
+        $tokenData->scope = ['openid'];
+
+        $tokenDaoStub = $this->createMock(\RAP\AccessTokenDAO::class);
+        $tokenDaoStub->method('retrieveTokenDataFromCode')->willReturn($tokenData);
+
+        $tokenBuilderStub = $this->createMock(\RAP\TokenBuilder::class);
+        $tokenBuilderStub->method('getAccessToken')->willReturn('<access_token>');
+
+        $refreshTokenDaoStub = $this->createMock(\RAP\RefreshTokenDAO::class);
+
+        $locatorStub = $this->createMock(\RAP\Locator::class);
+        $locatorStub->method('getClientAuthChecker')->willReturn($authCheckerStub);
+        $locatorStub->method('getAccessTokenDAO')->willReturn($tokenDaoStub);
+        $locatorStub->method('getTokenBuilder')->willReturn($tokenBuilderStub);
+        $locatorStub->method('getRefreshTokenDAO')->willReturn($refreshTokenDaoStub);
+
+        $authCheckerStub->expects($this->once())
+                ->method('validateClientAuth')->with($this->anything());
+
+        $tokenDaoStub->expects($this->once())
+                ->method('retrieveTokenDataFromCode')->with($this->anything());
+
+        $tokenDaoStub->expects($this->once())
+                ->method('deleteTokenData')->with($this->anything());
+
+        $requestHandler = new \RAP\OAuth2RequestHandler($locatorStub);
+
+        $params = [
+            "grant_type" => "authorization_code",
+            "redirect_uri" => "redirect",
+            "code" => "123"
+        ];
+        $result = $requestHandler->handleAccessTokenRequest($params, []);
+
+        $this->assertEquals(3600, $result['expires_in']);
+        $this->assertEquals("Bearer", $result['token_type']);
+        $this->assertEquals("<access_token>", $result['access_token']);
+        $this->assertNotNull($result['refresh_token']);
+    }
+
+    public function testHandleClientCredentialsRequest(): void {
+
+        $authCheckerStub = $this->createMock(\RAP\ClientAuthChecker::class);
+
+        $tokenBuilderStub = $this->createMock(\RAP\TokenBuilder::class);
+        $tokenBuilderStub->method('getAccessToken')->willReturn('<access_token>');
+
+        $locatorStub = $this->createMock(\RAP\Locator::class);
+        $locatorStub->method('getClientAuthChecker')->willReturn($authCheckerStub);
+        $locatorStub->method('getTokenBuilder')->willReturn($tokenBuilderStub);
+
+        $authCheckerStub->expects($this->once())
+                ->method('validateCliClientAuth')->with($this->anything());
+
+        $requestHandler = new \RAP\OAuth2RequestHandler($locatorStub);
+
+        $params = [
+            "grant_type" => "client_credentials"
+        ];
+        $result = $requestHandler->handleAccessTokenRequest($params, []);
+
+        $this->assertEquals(3600, $result['expires_in']);
+        $this->assertEquals("Bearer", $result['token_type']);
+        $this->assertEquals("<access_token>", $result['access_token']);
+        $this->assertFalse(isset($result['refresh_token']));
+    }
+
+    public function testHandleRefreshTokenRequest(): void {
+
+        $refreshTokenData = new \RAP\RefreshTokenData();
+        $refreshTokenData->scope = ['openid', 'email'];
+
+        $authCheckerStub = $this->createMock(\RAP\ClientAuthChecker::class);
+
+        $tokenBuilderStub = $this->createMock(\RAP\TokenBuilder::class);
+        $tokenBuilderStub->method('getAccessToken')->willReturn('<access_token>');
+
+        $refreshTokenDaoStub = $this->createMock(\RAP\RefreshTokenDAO::class);
+        $refreshTokenDaoStub->method('getRefreshTokenData')->willReturn($refreshTokenData);
+
+        $tokenDaoStub = $this->createMock(\RAP\AccessTokenDAO::class);
+        $tokenDaoStub->method('createTokenData')->will($this->returnArgument(0));
+
+        $locatorStub = $this->createMock(\RAP\Locator::class);
+        $locatorStub->method('getClientAuthChecker')->willReturn($authCheckerStub);
+        $locatorStub->method('getTokenBuilder')->willReturn($tokenBuilderStub);
+        $locatorStub->method('getRefreshTokenDAO')->willReturn($refreshTokenDaoStub);
+        $locatorStub->method('getAccessTokenDAO')->willReturn($tokenDaoStub);
+
+        $authCheckerStub->expects($this->once())
+                ->method('validateClientAuth')->with($this->anything());
+
+        $requestHandler = new \RAP\OAuth2RequestHandler($locatorStub);
+
+        $params = [
+            "grant_type" => "refresh_token",
+            "refresh_token" => "<refresh_token>",
+            "scope" => "openid email"
+        ];
+        $result = $requestHandler->handleAccessTokenRequest($params, []);
+
+        $this->assertEquals(3600, $result['expires_in']);
+        $this->assertEquals("Bearer", $result['token_type']);
+        $this->assertEquals("<access_token>", $result['access_token']);
+        $this->assertNotNull($result['refresh_token']);
+    }
+
+    public function testGetRedirectResponseUrlForAuthorizationCodeFlow(): void {
+
+        $user = new \RAP\User();
+        $user->id = "123";
+
+        $requestData = new \RAP\OAuth2RequestData();
+        $requestData->clientId = "<client-id>";
+        $requestData->redirectUrl = "<base-path>";
+        $requestData->scope = ["openid", "profile"];
+        $requestData->state = "<state>";
+
+        $sessionStub = $this->createMock(\RAP\SessionData::class);
+        $sessionStub->method('getUser')->willReturn($user);
+        $sessionStub->method('getOAuth2RequestData')->willReturn($requestData);
+
+        $locatorStub = $this->createMock(\RAP\Locator::class);
+        $locatorStub->method('getSession')->willReturn($sessionStub);
+
+        $requestHandler = new \RAP\OAuth2RequestHandler($locatorStub);
+
+        $result = $requestHandler->getRedirectResponseUrl();
+
+        $url_components = parse_url($result);
+        $this->assertEquals('<base-path>', $url_components['path']);
+
+        $params = [];
+        parse_str($url_components['query'], $params);
+
+        $this->assertEquals("<state>", $params['state']);
+        $this->assertEquals("openid profile", $params['scope']);
+
+        $this->assertNotNull($params['code']);
+    }
+
 }
diff --git a/tests/TokenBuilderTest.php b/tests/TokenBuilderTest.php
index 61618878dd51cebe6623b302bf67e93ab09c6bfc..8e1636da844edf847325e48de627c2bc17e7b1b1 100644
--- a/tests/TokenBuilderTest.php
+++ b/tests/TokenBuilderTest.php
@@ -17,15 +17,7 @@ final class TokenBuilderTest extends TestCase {
 
         $jwksDAOStub->method('getNewestKeyPair')->willReturn($keyPair);
 
-        $user = new \RAP\User();
-        $user->id = "user_id";
-        $identity = new \RAP\Identity(\RAP\Identity::EDU_GAIN);
-        $identity->email = "name@inaf.it";
-        $identity->name = "Name";
-        $identity->surname = "Surname";
-        $identity->primary = true;
-        $identity->institution = "INAF";
-        $user->addIdentity($identity);
+        $user = $this->getUser();
 
         $daoStub = $this->createMock(\RAP\UserDAO::class);
         $locatorStub->method('getUserDAO')->willReturn($daoStub);
@@ -48,9 +40,67 @@ final class TokenBuilderTest extends TestCase {
         $this->assertEquals("issuer", $payload->iss);
         $this->assertEquals($user->id, $payload->sub);
         $this->assertEquals($user->getCompleteName(), $payload->name);
+        $identity = $user->identities[0];
         $this->assertEquals($identity->name, $payload->given_name);
         $this->assertEquals($identity->surname, $payload->family_name);
         $this->assertEquals($identity->institution, $payload->org);
     }
 
+    public function testGetAccessToken(): void {
+
+        $jwksDAOStub = $this->createMock(\RAP\JWKSDAO::class);
+
+        $locatorStub = $this->createMock(\RAP\Locator::class);
+        $locatorStub->method('getJWKSDAO')->willReturn($jwksDAOStub);
+
+        $jwksHandler = new \RAP\JWKSHandler($locatorStub);
+        $keyPair = $jwksHandler->generateKeyPair();
+
+        $jwksDAOStub->method('getNewestKeyPair')->willReturn($keyPair);
+
+        $userDaoStub = $this->createMock(\RAP\UserDAO::class);
+        $locatorStub->method('getUserDAO')->willReturn($userDaoStub);
+
+        $user = $this->getUser();
+        $userDaoStub->method('findUserById')->willReturn($user);
+
+        $client = new \RAP\BrowserBasedOAuth2Client((object) [
+                    "id" => "aao",
+                    "secret" => "2a97516c354b68848cdbd8f54a226a0a55b21ed138e207ad6c5cbb9c00aa5aea",
+                    "redirect" => "redirect",
+                    "scope" => "openid email",
+                    "methods" => [],
+                    "scopeAudienceMap" => ["read:gms" => "gms"]
+        ]);
+
+        $locatorStub->method('getBrowserBasedOAuth2ClientById')->willReturn($client);
+
+        $locatorStub->config = json_decode('{"jwtIssuer": "issuer"}');
+
+        $tokenBuilder = new \RAP\TokenBuilder($locatorStub);
+
+        $tokenData = new \RAP\AccessTokenData();
+        $tokenData->token = "ttt";
+        $tokenData->scope = ["openid", "read:gms"];
+        $tokenData->userId = "user_id";
+        $tokenData->clientId = "aao";
+
+        $jwt = $tokenBuilder->getAccessToken($tokenData);
+
+        $this->assertNotNull($jwt);
+    }
+
+    private function getUser(): \RAP\User {
+        $user = new \RAP\User();
+        $user->id = "user_id";
+        $identity = new \RAP\Identity(\RAP\Identity::EDU_GAIN);
+        $identity->email = "name@inaf.it";
+        $identity->name = "Name";
+        $identity->surname = "Surname";
+        $identity->primary = true;
+        $identity->institution = "INAF";
+        $user->addIdentity($identity);
+        return $user;
+    }
+
 }