2727
2828#include "zend_smart_str.h"
2929#include "zend_exceptions.h"
30+ #include "ext/spl/spl_exceptions.h"
3031#include "ext/json/php_json.h"
3132#include "ext/standard/base64.h"
3233#include "ext/standard/info.h"
3738
3839#include "php_jwt.h"
3940
41+ /* Exceptions */
42+ PHP_JWT_API zend_class_entry * jwt_signature_invalid_cex ;
43+ PHP_JWT_API zend_class_entry * jwt_before_valid_cex ;
44+ PHP_JWT_API zend_class_entry * jwt_expired_signature_cex ;
45+ PHP_JWT_API zend_class_entry * jwt_invalid_issuer_cex ;
46+ PHP_JWT_API zend_class_entry * jwt_invalid_aud_cex ;
47+ PHP_JWT_API zend_class_entry * jwt_invalid_jti_cex ;
48+ PHP_JWT_API zend_class_entry * jwt_invalid_iat_cex ;
49+ PHP_JWT_API zend_class_entry * jwt_invalid_sub_cex ;
50+
4051ZEND_DECLARE_MODULE_GLOBALS (jwt )
4152
4253/* string to algorithm */
@@ -300,14 +311,15 @@ int jwt_array_equals(zend_array *arr1, zend_array *arr2) {
300311 php_error_docref (NULL , E_WARNING , "Aud each item type must be string" );
301312 }
302313 }
303- }ZEND_HASH_FOREACH_END ();
314+ } ZEND_HASH_FOREACH_END ();
304315 }
305316
306317 return 0 ;
307318}
308319
309320int jwt_verify_body (char * body , zval * return_value )
310321{
322+ zend_class_entry * ce ;
311323 char * err_msg = NULL ;
312324 time_t curr_time = time ((time_t * )NULL );
313325 zend_string * vs = jwt_b64_url_decode (body );
@@ -317,8 +329,10 @@ int jwt_verify_body(char *body, zval *return_value)
317329 zend_string_free (vs );
318330
319331 /* Expiration */
320- if (JWT_G (expiration ) && (curr_time - JWT_G (leeway )) >= JWT_G (expiration ))
332+ if (JWT_G (expiration ) && (curr_time - JWT_G (leeway )) >= JWT_G (expiration )) {
333+ ce = jwt_expired_signature_cex ;
321334 err_msg = "Expired token" ;
335+ }
322336
323337 /* not before */
324338 if (JWT_G (not_before ) && JWT_G (not_before ) > (curr_time + JWT_G (leeway ))) {
@@ -327,12 +341,15 @@ int jwt_verify_body(char *body, zval *return_value)
327341
328342 timeinfo = localtime (& JWT_G (not_before ));
329343 strftime (buf , sizeof (buf ), "Cannot handle token prior to %Y-%m-%d %H:%M:%S" , timeinfo );
344+ ce = jwt_before_valid_cex ;
330345 err_msg = buf ;
331346 }
332347
333348 /* iss */
334- if (jwt_verify_claims (return_value , "iss" , JWT_G (iss )))
335- err_msg = "Iss verify fail" ;
349+ if (jwt_verify_claims (return_value , "iss" , JWT_G (iss ))) {
350+ ce = jwt_invalid_issuer_cex ;
351+ err_msg = "Invalid Issuer" ;
352+ }
336353
337354 /* iat */
338355 if (JWT_G (iat ) && JWT_G (iat ) > (curr_time + JWT_G (leeway ))) {
@@ -341,23 +358,30 @@ int jwt_verify_body(char *body, zval *return_value)
341358
342359 timeinfo = localtime (& JWT_G (iat ));
343360 strftime (buf , sizeof (buf ), "Cannot handle token prior to %Y-%m-%d %H:%M:%S" , timeinfo );
361+ ce = jwt_invalid_iat_cex ;
344362 err_msg = buf ;
345363 }
346364
347365 /* jti */
348- if (jwt_verify_claims (return_value , "jti" , JWT_G (jti )))
349- err_msg = "Tti verify fail" ;
366+ if (jwt_verify_claims (return_value , "jti" , JWT_G (jti ))) {
367+ ce = jwt_invalid_jti_cex ;
368+ err_msg = "Invalid Jti" ;
369+ }
350370
351371 /* aud */
352- if (jwt_array_equals (JWT_G (aud ), jwt_hash_str_find_ht (return_value , "aud" )))
353- err_msg = "Aud verify fail" ;
372+ if (jwt_array_equals (JWT_G (aud ), jwt_hash_str_find_ht (return_value , "aud" ))) {
373+ ce = jwt_invalid_aud_cex ;
374+ err_msg = "Invalid Aud" ;
375+ }
354376
355377 /* sub */
356- if (jwt_verify_claims (return_value , "sub" , JWT_G (sub )))
357- err_msg = "Sub verify fail" ;
378+ if (jwt_verify_claims (return_value , "sub" , JWT_G (sub ))) {
379+ ce = jwt_invalid_sub_cex ;
380+ err_msg = "Invalid Sub" ;
381+ }
358382
359383 if (err_msg ) {
360- zend_throw_exception (zend_ce_exception , err_msg , 0 );
384+ zend_throw_exception (ce , err_msg , 0 );
361385 return FAILURE ;
362386 }
363387
@@ -419,7 +443,7 @@ PHP_FUNCTION(jwt_encode)
419443 jwt -> alg = jwt_str_alg (alg );
420444
421445 if (jwt -> alg == JWT_ALG_INVAL ) {
422- zend_throw_exception (zend_ce_exception , "Algorithm not supported" , 0 );
446+ zend_throw_exception (spl_ce_UnexpectedValueException , "Algorithm not supported" , 0 );
423447 goto encode_done ;
424448 }
425449
@@ -451,16 +475,16 @@ PHP_FUNCTION(jwt_encode)
451475
452476 /* sign */
453477 if (jwt -> alg == JWT_ALG_NONE ) {
454- // alg none.
455- smart_str_appendl (& segments , "." , 1 );
478+ /* alg none */
479+ smart_str_appendl (& segments , "." , 1 );
456480 } else {
457481 /* set jwt struct */
458482 jwt -> key = key ;
459483 jwt -> str = segments .s ;
460484
461485 /* sign */
462486 if (jwt_sign (jwt , & sig , & sig_len )) {
463- zend_throw_exception (zend_ce_exception , "Signature error " , 0 );
487+ zend_throw_exception (spl_ce_DomainException , "OpenSSL unable to sign data " , 0 );
464488 goto encode_done ;
465489 }
466490
@@ -506,15 +530,15 @@ PHP_FUNCTION(jwt_decode)
506530
507531 /* Parse options */
508532 if (jwt_parse_options (options ) == FAILURE ) {
509- zend_throw_exception (zend_ce_exception , "Options parse error" , 0 );
533+ zend_throw_exception (spl_ce_UnexpectedValueException , "Options parse error" , 0 );
510534 goto decode_done ;
511535 }
512536
513537 /* Algorithm */
514538 jwt -> alg = jwt_str_alg (JWT_G (algorithm ));
515539
516540 if (jwt -> alg == JWT_ALG_INVAL ) {
517- zend_throw_exception (zend_ce_exception , "Algorithm not supported" , 0 );
541+ zend_throw_exception (spl_ce_UnexpectedValueException , "Algorithm not supported" , 0 );
518542 goto decode_done ;
519543 }
520544
@@ -542,7 +566,7 @@ PHP_FUNCTION(jwt_decode)
542566 zend_string * json_h = jwt_b64_url_decode (head );
543567
544568 if (!json_h ) {
545- zend_throw_exception (zend_ce_exception , "Base64 decode error" , 0 );
569+ zend_throw_exception (spl_ce_UnexpectedValueException , "Base64 decode error" , 0 );
546570 goto decode_done ;
547571 }
548572
@@ -555,11 +579,11 @@ PHP_FUNCTION(jwt_decode)
555579 zval_ptr_dtor (& zv );
556580
557581 if (strcmp (Z_STRVAL_P (zalg ), JWT_G (algorithm ))) {
558- zend_throw_exception (zend_ce_exception , "Algorithm not allowed" , 0 );
582+ zend_throw_exception (spl_ce_UnexpectedValueException , "Algorithm not allowed" , 0 );
559583 goto decode_done ;
560584 }
561585 } else {
562- zend_throw_exception (zend_ce_exception , "Json decode error" , 0 );
586+ zend_throw_exception (spl_ce_UnexpectedValueException , "Json decode error" , 0 );
563587 goto decode_done ;
564588 }
565589
@@ -582,7 +606,7 @@ PHP_FUNCTION(jwt_decode)
582606 jwt -> str = segments .s ;
583607
584608 if (jwt_verify (jwt , sig )) {
585- zend_throw_exception (zend_ce_exception , "Signature verification failed" , 0 );
609+ zend_throw_exception (jwt_signature_invalid_cex , "Signature verification failed" , 0 );
586610 }
587611 }
588612
@@ -614,6 +638,40 @@ PHP_GINIT_FUNCTION(jwt) {
614638
615639PHP_MINIT_FUNCTION (jwt )
616640{
641+ zend_class_entry ce ;
642+
643+ /* SignatureInvalidException */
644+ INIT_CLASS_ENTRY (ce , "SignatureInvalidException" , NULL );
645+ jwt_signature_invalid_cex = zend_register_internal_class_ex (& ce , zend_ce_exception );
646+
647+ /* BeforeValidException */
648+ INIT_CLASS_ENTRY (ce , "BeforeValidException" , NULL );
649+ jwt_before_valid_cex = zend_register_internal_class_ex (& ce , zend_ce_exception );
650+
651+ /* ExpiredSignatureException */
652+ INIT_CLASS_ENTRY (ce , "ExpiredSignatureException" , NULL );
653+ jwt_expired_signature_cex = zend_register_internal_class_ex (& ce , zend_ce_exception );
654+
655+ /* InvalidIssuerException */
656+ INIT_CLASS_ENTRY (ce , "InvalidIssuerException" , NULL );
657+ jwt_invalid_issuer_cex = zend_register_internal_class_ex (& ce , zend_ce_exception );
658+
659+ /* InvalidAudException */
660+ INIT_CLASS_ENTRY (ce , "InvalidAudException" , NULL );
661+ jwt_invalid_aud_cex = zend_register_internal_class_ex (& ce , zend_ce_exception );
662+
663+ /* InvalidJtiException */
664+ INIT_CLASS_ENTRY (ce , "InvalidJtiException" , NULL );
665+ jwt_invalid_jti_cex = zend_register_internal_class_ex (& ce , zend_ce_exception );
666+
667+ /* InvalidIatException */
668+ INIT_CLASS_ENTRY (ce , "InvalidIatException" , NULL );
669+ jwt_invalid_iat_cex = zend_register_internal_class_ex (& ce , zend_ce_exception );
670+
671+ /* InvalidSubException */
672+ INIT_CLASS_ENTRY (ce , "InvalidSubException" , NULL );
673+ jwt_invalid_sub_cex = zend_register_internal_class_ex (& ce , zend_ce_exception );
674+
617675 return SUCCESS ;
618676}
619677
0 commit comments