1515use Lcobucci \JWT \Validation \Constraint \LooseValidAt ;
1616use Lcobucci \JWT \Validation \Constraint \SignedWith ;
1717use Lcobucci \JWT \Validation \RequiredConstraintsViolated ;
18+ use Pdsinterop \Solid \Auth \Exception \AuthorizationHeaderException ;
19+ use Pdsinterop \Solid \Auth \Exception \InvalidTokenException ;
1820use Psr \Http \Message \ServerRequestInterface ;
1921
2022/**
@@ -47,22 +49,22 @@ public function getWebId($request) {
4749 $ serverParams = $ request ->getServerParams ();
4850
4951 if (isset ($ serverParams ['HTTP_AUTHORIZATION ' ]) === false ) {
50- throw new Exception ("Authorization Header missing " );
52+ throw new AuthorizationHeaderException ("Authorization Header missing " );
5153 }
5254
5355 if (str_contains ($ serverParams ['HTTP_AUTHORIZATION ' ], ' ' ) === false ) {
54- throw new Exception ("Authorization Header does not contain parameters " );
56+ throw new AuthorizationHeaderException ("Authorization Header does not contain parameters " );
5557 }
5658
5759 [$ authScheme , $ jwt ] = explode (" " , $ serverParams ['HTTP_AUTHORIZATION ' ], 2 );
5860 $ authScheme = strtolower ($ authScheme );
5961
6062 if ($ authScheme !== "dpop " ) {
61- throw new Exception ('Only "dpop" authorization scheme is supported ' );
63+ throw new AuthorizationHeaderException ('Only "dpop" authorization scheme is supported ' );
6264 }
6365
6466 if (isset ($ serverParams ['HTTP_DPOP ' ]) === false ) {
65- throw new Exception ("Missing DPoP token " );
67+ throw new AuthorizationHeaderException ("Missing DPoP token " );
6668 }
6769
6870 $ dpop = $ serverParams ['HTTP_DPOP ' ];
@@ -71,13 +73,13 @@ public function getWebId($request) {
7173 try {
7274 $ dpopKey = $ this ->getDpopKey ($ dpop , $ request );
7375 } catch (InvalidTokenStructure $ e ) {
74- throw new Exception ("Invalid JWT token: {$ e ->getMessage ()}" , 0 , $ e );
76+ throw new InvalidTokenException ("Invalid JWT token: {$ e ->getMessage ()}" , 0 , $ e );
7577 }
7678
7779 try {
7880 $ this ->validateJwtDpop ($ jwt , $ dpopKey );
7981 } catch (RequiredConstraintsViolated $ e ) {
80- throw new Exception ( " Invalid token: { $ e ->getMessage ()}" , 0 , $ e );
82+ throw new InvalidTokenException ( $ e ->getMessage (), 0 , $ e );
8183 }
8284
8385 if ($ jwt ) {
@@ -109,7 +111,7 @@ public function getDpopKey($dpop, $request) {
109111 $ jwk = $ dpop ->headers ()->get ("jwk " );
110112
111113 if (isset ($ jwk ['kid ' ]) === false ) {
112- throw new Exception ('Key ID is missing from JWK header ' );
114+ throw new InvalidTokenException ('Key ID is missing from JWK header ' );
113115 }
114116
115117 return $ jwk ['kid ' ];
@@ -121,15 +123,15 @@ private function validateJwtDpop($jwt, $dpopKey) {
121123 $ cnf = $ jwt ->claims ()->get ("cnf " );
122124
123125 if ($ cnf === null ) {
124- throw new Exception ('JWT Confirmation claim (cnf) is missing ' );
126+ throw new InvalidTokenException ('JWT Confirmation claim (cnf) is missing ' );
125127 }
126128
127129 if (isset ($ cnf ['jkt ' ]) === false ) {
128- throw new Exception ('JWT Confirmation claim (cnf) is missing Thumbprint (jkt) ' );
130+ throw new InvalidTokenException ('JWT Confirmation claim (cnf) is missing Thumbprint (jkt) ' );
129131 }
130132
131133 if ($ cnf ['jkt ' ] !== $ dpopKey ) {
132- throw new Exception ('JWT Confirmation claim (cnf) provided Thumbprint (jkt) does not match Key ID from JWK header ' );
134+ throw new InvalidTokenException ('JWT Confirmation claim (cnf) provided Thumbprint (jkt) does not match Key ID from JWK header ' );
133135 }
134136
135137 //@FIXME: add check for "ath" claim in DPoP token, per https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop#section-7
@@ -180,31 +182,31 @@ public function validateDpop($dpop, $request) {
180182 // 2. all required claims are contained in the JWT,
181183 $ htm = $ dpop ->claims ()->get ("htm " ); // http method
182184 if (!$ htm ) {
183- throw new Exception ("missing htm " );
185+ throw new InvalidTokenException ("missing htm " );
184186 }
185187 $ htu = $ dpop ->claims ()->get ("htu " ); // http uri
186188 if (!$ htu ) {
187- throw new Exception ("missing htu " );
189+ throw new InvalidTokenException ("missing htu " );
188190 }
189191 $ typ = $ dpop ->headers ()->get ("typ " );
190192 if (!$ typ ) {
191- throw new Exception ("missing typ " );
193+ throw new InvalidTokenException ("missing typ " );
192194 }
193195 $ alg = $ dpop ->headers ()->get ("alg " );
194196 if (!$ alg ) {
195- throw new Exception ("missing alg " );
197+ throw new InvalidTokenException ("missing alg " );
196198 }
197199
198200 // 3. the "typ" field in the header has the value "dpop+jwt",
199201 if ($ typ != "dpop+jwt " ) {
200- throw new Exception ("typ is not dpop+jwt " );
202+ throw new InvalidTokenException ("typ is not dpop+jwt " );
201203 }
202204
203205 // 4. the algorithm in the header of the JWT indicates an asymmetric
204206 // digital signature algorithm, is not "none", is supported by the
205207 // application, and is deemed secure,
206208 if ($ alg == "none " ) {
207- throw new Exception ("alg is none " );
209+ throw new InvalidTokenException ("alg is none " );
208210 }
209211
210212 // 5. that the JWT is signed using the public key contained in the
@@ -221,7 +223,7 @@ public function validateDpop($dpop, $request) {
221223 $ signer = Sha256::create ();
222224 break ;
223225 default :
224- throw new Exception ("unsupported algorithm " );
226+ throw new InvalidTokenException ("unsupported algorithm " );
225227 break ;
226228 }
227229 $ key = InMemory::plainText ($ pem );
@@ -231,7 +233,7 @@ public function validateDpop($dpop, $request) {
231233 // 6. the "htm" claim matches the HTTP method value of the HTTP request
232234 // in which the JWT was received (case-insensitive),
233235 if (strtolower ($ htm ) != strtolower ($ request ->getMethod ())) {
234- throw new Exception ("htm http method is invalid " );
236+ throw new InvalidTokenException ("htm http method is invalid " );
235237 }
236238
237239 // 7. the "htu" claims matches the HTTP URI value for the HTTP request
@@ -243,7 +245,7 @@ public function validateDpop($dpop, $request) {
243245 //error_log("REQUESTED HTU $htu");
244246 //error_log("REQUESTED PATH $requestedPath");
245247 if ($ htu != $ requestedPath ) {
246- throw new Exception ("htu does not match requested path " );
248+ throw new InvalidTokenException ("htu does not match requested path " );
247249 }
248250
249251 // 8. the token was issued within an acceptable timeframe (see Section 9.1), and
@@ -258,11 +260,11 @@ public function validateDpop($dpop, $request) {
258260 // 9. that, within a reasonable consideration of accuracy and resource utilization, a JWT with the same "jti" value has not been received previously (see Section 9.1).
259261 $ jti = $ dpop ->claims ()->get ("jti " );
260262 if ($ jti === null ) {
261- throw new Exception ("jti is missing " );
263+ throw new InvalidTokenException ("jti is missing " );
262264 }
263265 $ isJtiValid = $ this ->jtiValidator ->validate ($ jti , (string ) $ request ->getUri ());
264266 if (! $ isJtiValid ) {
265- throw new Exception ("jti is invalid " );
267+ throw new InvalidTokenException ("jti is invalid " );
266268 }
267269
268270 // 10. that, if used with an access token, it also contains the 'ath' claim, with a hash of the access token
@@ -276,12 +278,12 @@ private function getSubjectFromJwt($jwt) {
276278 try {
277279 $ jwt = $ jwtConfig ->parser ()->parse ($ jwt );
278280 } catch (Exception $ e ) {
279- throw new Exception ("Invalid JWT token " , 409 , $ e );
281+ throw new InvalidTokenException ("Invalid JWT token " , 409 , $ e );
280282 }
281283
282284 $ sub = $ jwt ->claims ()->get ("sub " );
283285 if ($ sub === null ) {
284- throw new Exception ('Missing "SUB" ' );
286+ throw new InvalidTokenException ('Missing "SUB" ' );
285287 }
286288 return $ sub ;
287289 }
0 commit comments