@@ -116,8 +116,65 @@ private function validateJwtDpop($jwt, $dpopKey) {
116116 throw new InvalidTokenException ('JWT Confirmation claim (cnf) is missing Thumbprint (jkt) ' );
117117 }
118118
119- if ($ cnf ['jkt ' ] !== $ dpopKey ) {
120- throw new InvalidTokenException ('JWT Confirmation claim (cnf) provided Thumbprint (jkt) does not match Key ID from JWK header ' );
119+ // !!! HIER GEBLEVEN !!!
120+
121+ // @CHECKME: If we are checking against the JKT this "if" can be removed
122+ if ($ dpopKey !== '' ) {
123+ $ keyTypes = [
124+ /*ES256*/ 'EC ' => ['crv ' , 'kty ' , 'x ' , 'y ' ],
125+ /*RS256*/ 'RSA ' => ['e ' , 'kty ' , 'n ' ],
126+ ];
127+
128+ $ jwk = $ jwt ->headers ()->get ('jwk ' );
129+
130+ $ keyType = $ jwk ['kty ' ];
131+
132+ if (array_key_exists ($ keyType , $ keyTypes ) === false ) {
133+ $ message = vsprintf ('Unsupported key type "%s". Must be one of: %s ' , [
134+ $ keyType ,
135+ implode (', ' , array_keys ($ keyTypes )),
136+ ]);
137+ throw new InvalidTokenException ($ message );
138+ }
139+
140+ $ required = $ keyTypes [$ keyType ];
141+ $ missing = array_diff ($ required , array_keys ($ jwk ));
142+
143+ if ($ missing !== []) {
144+ throw new InvalidTokenException ('Required JWK values have not been set: ' . implode (', ' , $ missing ));
145+ }
146+
147+ /**
148+ * RFC7638 defines a method for computing the hash value (or "digest") of a JSON Web Key (JWK).
149+ *
150+ * The resulting hash value can be used for identifying the key represented by the JWK
151+ * that is the subject of the thumbprint.
152+ *
153+ * For instance by using the base64url-encoded JWK Thumbprint value as a key ID (or "kid") value.
154+ *
155+ * @see https://www.rfc-editor.org/rfc/rfc7638
156+ *
157+ * The thumbprint of a JWK is created by:
158+ *
159+ * 1. Constructing a JSON string (without whitespaces) with the required keys in alphabetical order.
160+ * 2. Hashing the JSON string using SHA-256 (or another hash function)
161+ *
162+ */
163+ // @FIXME: Add logic to build correct JSON string
164+ $ json = vsprintf ('{"e":"%s","kty":"%s","n":"%s"} ' , [
165+ $ jwk ['e ' ],
166+ $ jwk ['kty ' ],
167+ $ jwk ['n ' ],
168+ ]);
169+
170+ $ hash = hash ('sha256 ' , $ json );
171+ $ encoded = Base64Url::encode ($ hash );
172+
173+ // @FIXME: What are we comparing against? JKT? KID / $dpopKey?
174+ if ($ encoded !== $ dpopKey /* or $cnf['jkt'] ?*/ ) {
175+ // @CHECKME: What error message belongs here?
176+ throw new InvalidTokenException ('JWT Confirmation claim (cnf) provided Thumbprint (jkt) does not match Key ID from JWK header ' );
177+ }
121178 }
122179
123180 //@FIXME: add check for "ath" claim in DPoP token, per https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop#section-7
0 commit comments