diff --git a/classes/IdTokenBuilder.php b/classes/IdTokenBuilder.php
index 1ea499de588ce879559ed0653029fbc4d0702f88..a198208ae65a44d5abd44645b20340b909f91ee0 100644
--- a/classes/IdTokenBuilder.php
+++ b/classes/IdTokenBuilder.php
@@ -12,16 +12,16 @@ class IdTokenBuilder {
         $this->locator = $locator;
     }
 
-    public function getIdToken(AccessToken $accessToken): string {
+    public function getIdToken(AccessToken $accessToken, $nonce = null): string {
 
         $keyPair = $this->locator->getJWKSDAO()->getNewestKeyPair();
 
-        $payload = $this->createPayloadArray($accessToken);
+        $payload = $this->createPayloadArray($accessToken, $nonce);
 
         return JWT::encode($payload, $keyPair->privateKey, $keyPair->alg, $keyPair->keyId);
     }
 
-    private function createPayloadArray(AccessToken $accessToken) {
+    private function createPayloadArray(AccessToken $accessToken, $nonce = null) {
 
         $user = $this->locator->getUserDAO()->findUserById($accessToken->userId);
 
@@ -30,9 +30,14 @@ class IdTokenBuilder {
             'sub' => $user->id,
             'iat' => time(),
             'exp' => time() + 3600,
-            'name' => $user->getCompleteName()
+            'name' => $user->getCompleteName(),
+            'aud' => $accessToken->clientId
         );
 
+        if ($nonce !== null) {
+            $payloadArr['nonce'] = $nonce;
+        }
+
         if (in_array("email", $accessToken->scope)) {
             $payloadArr['email'] = $user->getPrimaryEmail();
         }
diff --git a/classes/JWKSHandler.php b/classes/JWKSHandler.php
index 48b58226fb14af6d4575dd1008245e279fa51f6d..4c2ca9b645ba17b53bc51f32c717a060adda1af0 100644
--- a/classes/JWKSHandler.php
+++ b/classes/JWKSHandler.php
@@ -21,7 +21,8 @@ class JWKSHandler {
 
         $rsa->setPrivateKeyFormat(RSA::PRIVATE_FORMAT_PKCS1);
         $rsa->setPublicKeyFormat(RSA::PUBLIC_FORMAT_PKCS8);
-        $result = $rsa->createKey();
+        // Guacamole needs a key of at least 2048
+        $result = $rsa->createKey(2048);
 
         $keyPair = new RSAKeyPair();
         $keyPair->alg = 'RS256';
diff --git a/classes/OAuth2RequestHandler.php b/classes/OAuth2RequestHandler.php
index 08c996768bbc436996a5b47dedcb0ff9c4bfb158..44175c438bf76b0347beb58d1773b1817348541f 100644
--- a/classes/OAuth2RequestHandler.php
+++ b/classes/OAuth2RequestHandler.php
@@ -36,8 +36,10 @@ class OAuth2RequestHandler {
         }
 
         $state = $params['state'];
-        if ($state === null) {
-            throw new BadRequestException("State is required");
+        $nonce = $params['nonce'];
+
+        if ($state === null && $nonce === null) {
+            throw new BadRequestException("State or nonce is required");
         }
 
         // Storing OAuth2 data in session
@@ -45,6 +47,7 @@ class OAuth2RequestHandler {
         $oauth2Data->clientId = $client->client;
         $oauth2Data->redirectUrl = $client->redirectUrl;
         $oauth2Data->state = $state;
+        $oauth2Data->nonce = $nonce;
 
         $scope = $params['scope'];
         if ($scope !== null) {
@@ -55,7 +58,7 @@ class OAuth2RequestHandler {
         $session->setOAuth2Data($oauth2Data);
     }
 
-    public function getCodeResponseUrl(): string {
+    public function getRedirectResponseUrl(): string {
 
         $session = $this->locator->getSession();
 
@@ -70,9 +73,17 @@ class OAuth2RequestHandler {
         $this->locator->getAccessTokenDAO()->createAccessToken($accessToken);
 
         $state = $session->getOAuth2Data()->state;
+        $nonce = $session->getOAuth2Data()->nonce;
 
-        $redirectUrl = $session->getOAuth2Data()->redirectUrl
-                . '?code=' . $accessToken->code . '&scope=profile&state=' . $state;
+        if ($state !== null) {
+            // Authorization code grant flow
+            $redirectUrl = $session->getOAuth2Data()->redirectUrl
+                    . '?code=' . $accessToken->code . '&scope=profile&state=' . $state;
+        } else {
+            // Implicit grant flow
+            $idToken = $this->locator->getIdTokenBuilder()->getIdToken($accessToken, $nonce);
+            $redirectUrl = $session->getOAuth2Data()->redirectUrl . "#id_token=" . $idToken;
+        }
 
         return $redirectUrl;
     }
diff --git a/classes/login/LoginHandler.php b/classes/login/LoginHandler.php
index 0bb85fd34be1f08db06f95c6c5bc0cef243089a3..198e140aa78b1cc55f8155097416ec6dd856a9a5 100644
--- a/classes/login/LoginHandler.php
+++ b/classes/login/LoginHandler.php
@@ -75,7 +75,7 @@ class LoginHandler {
 
         if ($session->getOAuth2Data() !== null) {
             $session->setUser($user);
-            $redirectUrl = $this->locator->getOAuth2RequestHandler()->getCodeResponseUrl();
+            $redirectUrl = $this->locator->getOAuth2RequestHandler()->getRedirectResponseUrl();
             session_destroy();
             return $redirectUrl;
         }
diff --git a/classes/model/OAuth2Data.php b/classes/model/OAuth2Data.php
index f4ae310449345126fe8b1d98974cdbba75855e92..9716301cddf32d11ca4664d931e88056df1ce1d4 100644
--- a/classes/model/OAuth2Data.php
+++ b/classes/model/OAuth2Data.php
@@ -8,5 +8,6 @@ class OAuth2Data {
     public $redirectUrl;
     public $state;
     public $scope;
+    public $nonce;
 
 }
diff --git a/include/front-controller.php b/include/front-controller.php
index d47c05b809afe1192edc9368477559cce6c6e3b6..90a9da3af63c52dd2c07dae286e0b3a39bd8b779 100644
--- a/include/front-controller.php
+++ b/include/front-controller.php
@@ -79,7 +79,8 @@ Flight::route('GET /auth/oauth2/authorize', function() {
         "redirect_uri" => filter_input(INPUT_GET, 'redirect_uri', FILTER_SANITIZE_STRING),
         "alg" => filter_input(INPUT_GET, 'alg', FILTER_SANITIZE_STRING),
         "state" => filter_input(INPUT_GET, 'state', FILTER_SANITIZE_STRING),
-        "scope" => filter_input(INPUT_GET, 'scope', FILTER_SANITIZE_STRING)
+        "scope" => filter_input(INPUT_GET, 'scope', FILTER_SANITIZE_STRING),
+        "nonce" => filter_input(INPUT_GET, 'nonce', FILTER_SANITIZE_STRING)
     ];
 
     $requestHandler = new \RAP\OAuth2RequestHandler($locator);