22
33namespace Stackkit \LaravelGoogleCloudScheduler ;
44
5+ use Carbon \Carbon ;
56use Firebase \JWT \JWT ;
7+ use Firebase \JWT \SignatureInvalidException ;
68use GuzzleHttp \Client ;
79use Illuminate \Support \Arr ;
810use Illuminate \Support \Facades \Cache ;
@@ -19,6 +21,7 @@ class OpenIdVerificator
1921 private $ guzzle ;
2022 private $ rsa ;
2123 private $ jwt ;
24+ private $ maxAge = [];
2225
2326 public function __construct (Client $ guzzle , RSA $ rsa , JWT $ jwt )
2427 {
@@ -32,7 +35,6 @@ public function guardAgainstInvalidOpenIdToken($decodedToken)
3235 /**
3336 * https://developers.google.com/identity/protocols/oauth2/openid-connect#validatinganidtoken
3437 */
35-
3638 if (!in_array ($ decodedToken ->iss , ['https://accounts.google.com ' , 'accounts.google.com ' ])) {
3739 throw new CloudSchedulerException ('The given OpenID token is not valid ' );
3840 }
@@ -46,30 +48,40 @@ public function guardAgainstInvalidOpenIdToken($decodedToken)
4648 }
4749 }
4850
49- public function decodeToken ( $ token )
51+ public function decodeOpenIdToken ( $ openIdToken , $ kid , $ cache = true )
5052 {
53+ if (!$ cache ) {
54+ $ this ->forgetFromCache ();
55+ }
56+
57+ $ publicKey = $ this ->getPublicKey ($ kid );
58+
5159 try {
52- $ kid = $ this ->getKidFromOpenIdToken ($ token );
53- $ publicKey = $ this ->getPublicKey ($ kid );
60+ return $ this ->jwt ->decode ($ openIdToken , $ publicKey , ['RS256 ' ]);
61+ } catch (SignatureInvalidException $ e ) {
62+ if (!$ cache ) {
63+ throw $ e ;
64+ }
5465
55- return $ this ->jwt ->decode ($ token , $ publicKey , ['RS256 ' ]);
56- } catch (Throwable $ e ) {
57- throw new CloudSchedulerException ('Could not decode token ' );
66+ return $ this ->decodeOpenIdToken ($ openIdToken , $ kid , false );
5867 }
5968 }
6069
6170 public function getPublicKey ($ kid = null )
6271 {
63- $ v3Certs = Cache::rememberForever (self ::V3_CERTS , function () {
64- return $ this ->getv3Certs ();
65- });
72+ if (Cache::has (self ::V3_CERTS )) {
73+ $ v3Certs = Cache::get (self ::V3_CERTS );
74+ } else {
75+ $ v3Certs = $ this ->getFreshCertificates ();
76+ Cache::put (self ::V3_CERTS , $ v3Certs , Carbon::now ()->addSeconds ($ this ->maxAge [self ::URL_OPENID_CONFIG ]));
77+ }
6678
6779 $ cert = $ kid ? collect ($ v3Certs )->firstWhere ('kid ' , '= ' , $ kid ) : $ v3Certs [0 ];
6880
6981 return $ this ->extractPublicKeyFromCertificate ($ cert );
7082 }
7183
72- private function getv3Certs ()
84+ private function getFreshCertificates ()
7385 {
7486 $ jwksUri = $ this ->callApiAndReturnValue (self ::URL_OPENID_CONFIG , 'jwks_uri ' );
7587
@@ -97,11 +109,24 @@ private function callApiAndReturnValue($url, $value)
97109
98110 $ data = json_decode ($ response ->getBody (), true );
99111
112+ $ maxAge = 0 ;
113+ foreach ($ response ->getHeader ('Cache-Control ' ) as $ line ) {
114+ preg_match ('/max-age=(\d+)/ ' , $ line , $ matches );
115+ $ maxAge = isset ($ matches [1 ]) ? (int ) $ matches [1 ] : 0 ;
116+ }
117+
118+ $ this ->maxAge [$ url ] = $ maxAge ;
119+
100120 return Arr::get ($ data , $ value );
101121 }
102122
103123 public function isCached ()
104124 {
105125 return Cache::has (self ::V3_CERTS );
106126 }
127+
128+ public function forgetFromCache ()
129+ {
130+ Cache::forget (self ::V3_CERTS );
131+ }
107132}
0 commit comments