2121 * that matches the access token
2222 */
2323class DPop {
24-
24+
2525 /**
2626 * This method fetches the WebId from a request and verifies
2727 * that the request has a valid DPoP token that matches
2828 * the access token.
29+ *
2930 * @param Psr\Http\Message\ServerRequestInterface $request Server Request
31+ *
3032 * @return string the WebId, or "public" if no WebId is found
33+ *
3134 * @throws \Exception "Invalid token" when the DPoP token is invalid
3235 * @throws \Exception "Missng DPoP token" when the DPoP token is missing, but the Authorisation header in the request specifies it
3336 */
@@ -62,9 +65,12 @@ public function getWebId($request) {
6265 /**
6366 * Returns the "kid" from the "jwk" header in the DPoP token.
6467 * The DPoP token must be valid.
68+ *
6569 * @param string $dpop The DPoP token
6670 * @param Psr\Http\Message\ServerRequestInterface $request Server Request
71+ *
6772 * @return string the "kid" from the "jwk" header in the DPoP token.
73+ *
6874 * @throws Lcobucci\JWT\Validation\RequiredConstraintsViolated
6975 */
7076 public function getDpopKey ($ dpop , $ request ) {
@@ -74,29 +80,32 @@ public function getDpopKey($dpop, $request) {
7480 $ jwtConfig = $ configuration = Configuration::forUnsecuredSigner ();
7581 $ dpop = $ jwtConfig ->parser ()->parse ($ dpop );
7682 $ jwk = $ dpop ->headers ()->get ("jwk " );
77-
83+
7884 return $ jwk ['kid ' ];
7985 }
8086
8187 private function validateJwtDpop ($ jwt , $ dpopKey ) {
8288 $ jwtConfig = $ configuration = Configuration::forUnsecuredSigner ();
8389 $ jwt = $ jwtConfig ->parser ()->parse ($ jwt );
8490 $ cnf = $ jwt ->claims ()->get ("cnf " );
85-
91+
8692 if ($ cnf ['jkt ' ] == $ dpopKey ) {
8793 return true ;
8894 }
89-
95+
9096 //@FIXME: add check for "ath" claim in DPoP token, per https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop#section-7
9197 return false ;
9298 }
9399
94100 /**
95101 * Validates that the DPOP token matches all requirements from
96102 * https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop#section-4.2
103+ *
97104 * @param string $dpop The DPOP token
98105 * @param Psr\Http\Message\ServerRequestInterface $request Server Request
106+ *
99107 * @return bool True if the DPOP token is valid, false otherwise
108+ *
100109 * @throws Lcobucci\JWT\Validation\RequiredConstraintsViolated
101110 */
102111 public function validateDpop ($ dpop , $ request ) {
@@ -128,7 +137,7 @@ public function validateDpop($dpop, $request) {
128137 // 1. the string value is a well-formed JWT,
129138 $ jwtConfig = $ configuration = Configuration::forUnsecuredSigner ();
130139 $ dpop = $ jwtConfig ->parser ()->parse ($ dpop );
131-
140+
132141 // 2. all required claims are contained in the JWT,
133142 $ htm = $ dpop ->claims ()->get ("htm " ); // http method
134143 if (!$ htm ) {
@@ -158,7 +167,7 @@ public function validateDpop($dpop, $request) {
158167 if ($ alg == "none " ) {
159168 throw new \Exception ("alg is none " );
160169 }
161-
170+
162171 // 5. that the JWT is signed using the public key contained in the
163172 // "jwk" header of the JWT,
164173 $ jwk = $ dpop ->headers ()->get ("jwk " );
@@ -179,7 +188,7 @@ public function validateDpop($dpop, $request) {
179188 $ key = InMemory::plainText ($ pem );
180189 $ validationConstraints = [];
181190 $ validationConstraints [] = new SignedWith ($ signer , $ key );
182-
191+
183192 // 6. the "htm" claim matches the HTTP method value of the HTTP request
184193 // in which the JWT was received (case-insensitive),
185194 if (strtolower ($ htm ) != strtolower ($ request ->getMethod ())) {
@@ -215,7 +224,7 @@ public function validateDpop($dpop, $request) {
215224
216225 return true ;
217226 }
218-
227+
219228 private function getSubjectFromJwt ($ jwt ) {
220229 $ jwtConfig = $ configuration = Configuration::forUnsecuredSigner ();
221230 try {
0 commit comments