1515use Jose \Component \Core \Util \ECKey ;
1616use Jose \Component \Core \Util \RSAKey ;
1717
18+ /**
19+ * This class contains code to fetch the WebId from a request
20+ * It also verifies that the request has a valid DPoP token
21+ * that matches the access token
22+ */
1823class DPop {
24+
25+ /**
26+ * This method fetches the WebId from a request and verifies
27+ * that the request has a valid DPoP token that matches
28+ * the access token.
29+ * @param Psr\Http\Message\ServerRequestInterface $request Server Request
30+ * @return string the WebId, or "public" if no WebId is found
31+ * @throws \Exception "Invalid token" when the DPoP token is invalid
32+ * @throws \Exception "Missng DPoP token" when the DPoP token is missing, but the Authorisation header in the request specifies it
33+ */
1934 public function getWebId ($ request ) {
2035 $ auth = explode (" " , $ request ->getServerParams ()['HTTP_AUTHORIZATION ' ]);
2136 $ jwt = $ auth [1 ] ?? false ;
2237
2338 if (strtolower ($ auth [0 ]) == "dpop " ) {
2439 $ dpop = $ request ->getServerParams ()['HTTP_DPOP ' ];
40+ //@FIXME: check that there is just one DPoP token in the request
2541 if ($ dpop ) {
2642 $ dpopKey = $ this ->getDpopKey ($ dpop , $ request );
27- if (!$ this ->validateJwtDpop ($ jwt , $ dpopKey )) {
28- throw new \Exception ("Invalid token " );
43+ try {
44+ $ this ->validateJwtDpop ($ jwt , $ dpopKey );
45+ } catch (Lcobucci \JWT \Validation \RequiredConstraintsViolated $ e ) {
46+ throw new \Exception ("Invalid token " , $ e );
2947 }
48+ } else {
49+ throw new \Exception ("Missing DPoP token " );
3050 }
3151 }
3252
@@ -39,16 +59,21 @@ public function getWebId($request) {
3959 return $ webId ;
4060 }
4161
62+ /**
63+ * Returns the "kid" from the "jwk" header in the DPoP token.
64+ * The DPoP token must be valid.
65+ * @param string $dpop The DPoP token
66+ * @param Psr\Http\Message\ServerRequestInterface $request Server Request
67+ * @return string the "kid" from the "jwk" header in the DPoP token.
68+ * @throws Lcobucci\JWT\Validation\RequiredConstraintsViolated
69+ */
4270 public function getDpopKey ($ dpop , $ request ) {
43- //error_log("11");
4471 $ this ->validateDpop ($ dpop , $ request );
45- //error_log("22");
4672
4773 // 1. the string value is a well-formed JWT,
4874 $ jwtConfig = $ configuration = Configuration::forUnsecuredSigner ();
4975 $ dpop = $ jwtConfig ->parser ()->parse ($ dpop );
50- $ jwk = $ dpop ->headers ()->get ("jwk " );
51- //error_log(print_r($jwk, true));
76+ $ jwk = $ dpop ->headers ()->get ("jwk " );
5277
5378 return $ jwk ['kid ' ];
5479 }
@@ -59,13 +84,10 @@ private function validateJwtDpop($jwt, $dpopKey) {
5984 $ cnf = $ jwt ->claims ()->get ("cnf " );
6085
6186 if ($ cnf ['jkt ' ] == $ dpopKey ) {
62- //error_log("dpopKey matches");
6387 return true ;
6488 }
65- //error_log("dpopKey mismatch");
66- //error_log(print_r($cnf, true));
67- //error_log($dpopKey);
6889
90+ //@FIXME: add check for "ath" claim in DPoP token, per https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop#section-7
6991 return false ;
7092 }
7193
0 commit comments