]> BookStack Code Mirror - bookstack/blobdiff - app/Access/Oidc/OidcUserinfoResponse.php
ZIP Imports: Added API examples, finished testing
[bookstack] / app / Access / Oidc / OidcUserinfoResponse.php
index 7c7760434b0f6865b3e36e110548a318fca0178c..33b8ec80665523a88a63ef9f3438e04546ad6d64 100644 (file)
@@ -7,25 +7,32 @@ use Psr\Http\Message\ResponseInterface;
 class OidcUserinfoResponse implements ProvidesClaims
 {
     protected array $claims = [];
+    protected ?OidcJwtWithClaims $jwt = null;
 
-    public function __construct(ResponseInterface $response)
+    public function __construct(ResponseInterface $response, string $issuer, array $keys)
     {
-        if ($response->getHeader('Content-Type')[0] === 'application/json') {
+        $contentTypeHeaderValue = $response->getHeader('Content-Type')[0] ?? '';
+        $contentType = strtolower(trim(explode(';', $contentTypeHeaderValue, 2)[0]));
+
+        if ($contentType === 'application/json') {
             $this->claims = json_decode($response->getBody()->getContents(), true);
         }
 
-        // TODO - Support JWTs
-        // TODO - Response validation (5.3.4):
-            // TODO - Verify that the OP that responded was the intended OP through a TLS server certificate check, per RFC 6125 [RFC6125].
-            // TODO - If the Client has provided a userinfo_encrypted_response_alg parameter during Registration, decrypt the UserInfo Response using the keys specified during Registration.
-            // TODO - If the response was signed, the Client SHOULD validate the signature according to JWS [JWS].
+        if ($contentType === 'application/jwt') {
+            $this->jwt = new OidcJwtWithClaims($response->getBody()->getContents(), $issuer, $keys);
+            $this->claims = $this->jwt->getAllClaims();
+        }
     }
 
     /**
      * @throws OidcInvalidTokenException
      */
-    public function validate(string $idTokenSub): bool
+    public function validate(string $idTokenSub, string $clientId): bool
     {
+        if (!is_null($this->jwt)) {
+            $this->jwt->validateCommonTokenDetails($clientId);
+        }
+
         $sub = $this->getClaim('sub');
 
         // Spec: v1.0 5.3.2: The sub (subject) Claim MUST always be returned in the UserInfo Response.
@@ -39,6 +46,14 @@ class OidcUserinfoResponse implements ProvidesClaims
             throw new OidcInvalidTokenException("Subject value provided in the userinfo endpoint does not match the provided ID token value");
         }
 
+        // Spec v1.0 5.3.4 Defines the following:
+        // Verify that the OP that responded was the intended OP through a TLS server certificate check, per RFC 6125 [RFC6125].
+          // This is effectively done as part of the HTTP request we're making through CURLOPT_SSL_VERIFYHOST on the request.
+        // If the Client has provided a userinfo_encrypted_response_alg parameter during Registration, decrypt the UserInfo Response using the keys specified during Registration.
+          // We don't currently support JWT encryption for OIDC
+        // If the response was signed, the Client SHOULD validate the signature according to JWS [JWS].
+          // This is done as part of the validateCommonClaims above.
+
         return true;
     }