1414use Exception ;
1515use Illuminate \Support \Collection ;
1616use Lcobucci \JWT \Builder ;
17- use Lcobucci \JWT \Parser ;
17+ use Lcobucci \JWT \Configuration ;
1818use Lcobucci \JWT \Signer \Ecdsa ;
1919use Lcobucci \JWT \Signer \Ecdsa \Sha256 as ES256 ;
2020use Lcobucci \JWT \Signer \Ecdsa \Sha384 as ES384 ;
2121use Lcobucci \JWT \Signer \Ecdsa \Sha512 as ES512 ;
2222use Lcobucci \JWT \Signer \Hmac \Sha256 as HS256 ;
2323use Lcobucci \JWT \Signer \Hmac \Sha384 as HS384 ;
2424use Lcobucci \JWT \Signer \Hmac \Sha512 as HS512 ;
25- use Lcobucci \JWT \Signer \Keychain ;
25+ use Lcobucci \JWT \Signer \Key \InMemory ;
26+ use Lcobucci \JWT \Signer ;
27+ use Lcobucci \JWT \Signer \Key ;
2628use Lcobucci \JWT \Signer \Rsa ;
2729use Lcobucci \JWT \Signer \Rsa \Sha256 as RS256 ;
2830use Lcobucci \JWT \Signer \Rsa \Sha384 as RS384 ;
2931use Lcobucci \JWT \Signer \Rsa \Sha512 as RS512 ;
32+ use Lcobucci \JWT \Token \RegisteredClaims ;
33+ use Lcobucci \JWT \Validation \Constraint \SignedWith ;
3034use ReflectionClass ;
3135use PHPOpenSourceSaver \JWTAuth \Contracts \Providers \JWT ;
3236use PHPOpenSourceSaver \JWTAuth \Exceptions \JWTException ;
3539class Lcobucci extends Provider implements JWT
3640{
3741 /**
38- * The Builder instance.
42+ * The builder instance.
3943 *
40- * @var \Lcobucci\JWT\ Builder
44+ * @var Builder
4145 */
4246 protected $ builder ;
4347
4448 /**
45- * The Parser instance.
49+ * The configuration instance.
4650 *
47- * @var \Lcobucci\JWT\Parser
51+ * @var Configuration
4852 */
49- protected $ parser ;
53+ protected $ config ;
54+
55+ /**
56+ * The Signer instance.
57+ *
58+ * @var Signer
59+ */
60+ protected $ signer ;
5061
5162 /**
5263 * Create the Lcobucci provider.
5364 *
54- * @param \Lcobucci\JWT\Builder $builder
55- * @param \Lcobucci\JWT\Parser $parser
5665 * @param string $secret
5766 * @param string $algo
5867 * @param array $keys
68+ * @param Configuration $config Optional, to pass an existing configuration to be used.
5969 *
6070 * @return void
6171 */
6272 public function __construct (
63- Builder $ builder ,
64- Parser $ parser ,
6573 $ secret ,
6674 $ algo ,
67- array $ keys
75+ array $ keys ,
76+ $ config = null
6877 ) {
6978 parent ::__construct ($ secret , $ algo , $ keys );
7079
71- $ this ->builder = $ builder ;
72- $ this ->parser = $ parser ;
7380 $ this ->signer = $ this ->getSigner ();
81+
82+ if (!is_null ($ config )) {
83+ $ this ->config = $ config ;
84+ } elseif ($ this ->isAsymmetric ()) {
85+ $ this ->config = Configuration::forAsymmetricSigner ($ this ->signer , $ this ->getSigningKey (), $ this ->getVerificationKey ());
86+ } else {
87+ $ this ->config = Configuration::forSymmetricSigner ($ this ->signer , InMemory::plainText ($ this ->getSecret ()));
88+ }
89+ if (!count ($ this ->config ->validationConstraints ())) {
90+ $ this ->config ->setValidationConstraints (
91+ new SignedWith ($ this ->signer , $ this ->getVerificationKey ()),
92+ );
93+ }
94+ }
95+
96+ /**
97+ * Gets the {@see $config} attribute.
98+ *
99+ * @return Configuration
100+ */
101+ public function getConfig ()
102+ {
103+ return $ this ->config ;
74104 }
75105
76106 /**
@@ -101,19 +131,18 @@ public function __construct(
101131 */
102132 public function encode (array $ payload )
103133 {
104- // Remove the signature on the builder instance first.
105- $ this ->builder -> unsign ();
134+ $ this -> builder = null ;
135+ $ this ->builder = $ this -> config -> builder ();
106136
107137 try {
108138 foreach ($ payload as $ key => $ value ) {
109- $ this ->builder -> set ($ key , $ value );
139+ $ this ->addClaim ($ key , $ value );
110140 }
111- $ this ->builder ->sign ($ this ->signer , $ this ->getSigningKey ());
141+
142+ return $ this ->builder ->getToken ($ this ->config ->signer (), $ this ->config ->signingKey ())->toString ();
112143 } catch (Exception $ e ) {
113- throw new JWTException ('Could not create token: ' . $ e ->getMessage (), $ e ->getCode (), $ e );
144+ throw new JWTException ('Could not create token: ' . $ e ->getMessage (), $ e ->getCode (), $ e );
114145 }
115-
116- return (string ) $ this ->builder ->getToken ();
117146 }
118147
119148 /**
@@ -128,20 +157,66 @@ public function encode(array $payload)
128157 public function decode ($ token )
129158 {
130159 try {
131- $ jwt = $ this ->parser ->parse ($ token );
160+ $ jwt = $ this ->config -> parser () ->parse ($ token );
132161 } catch (Exception $ e ) {
133- throw new TokenInvalidException ('Could not decode token: ' . $ e ->getMessage (), $ e ->getCode (), $ e );
162+ throw new TokenInvalidException ('Could not decode token: ' . $ e ->getMessage (), $ e ->getCode (), $ e );
134163 }
135164
136- if (! $ jwt -> verify ( $ this -> signer , $ this ->getVerificationKey ())) {
165+ if (!$ this -> config -> validator ()-> validate ( $ jwt , ... $ this ->config -> validationConstraints ())) {
137166 throw new TokenInvalidException ('Token Signature could not be verified. ' );
138167 }
139168
140- return (new Collection ($ jwt ->getClaims ()))->map (function ($ claim ) {
141- return is_object ($ claim ) ? $ claim ->getValue () : $ claim ;
169+ return (new Collection ($ jwt ->claims ()->all ()))->map (function ($ claim ) {
170+ if (is_a ($ claim , \DateTimeImmutable::class)) {
171+ return $ claim ->getTimestamp ();
172+ }
173+ if (is_object ($ claim ) && method_exists ($ claim , 'getValue ' )) {
174+ return $ claim ->getValue ();
175+ }
176+
177+ return $ claim ;
142178 })->toArray ();
143179 }
144180
181+ /**
182+ * Adds a claim to the {@see $config}.
183+ *
184+ * @param string $key
185+ * @param mixed $value
186+ */
187+ protected function addClaim ($ key , $ value )
188+ {
189+ if (!isset ($ this ->builder )) {
190+ $ this ->builder = $ this ->config ->builder ();
191+ }
192+
193+ switch ($ key ) {
194+ case RegisteredClaims::ID :
195+ $ this ->builder ->identifiedBy ($ value );
196+ break ;
197+ case RegisteredClaims::EXPIRATION_TIME :
198+ $ this ->builder ->expiresAt (\DateTimeImmutable::createFromFormat ('U ' , $ value ));
199+ break ;
200+ case RegisteredClaims::NOT_BEFORE :
201+ $ this ->builder ->canOnlyBeUsedAfter (\DateTimeImmutable::createFromFormat ('U ' , $ value ));
202+ break ;
203+ case RegisteredClaims::ISSUED_AT :
204+ $ this ->builder ->issuedAt (\DateTimeImmutable::createFromFormat ('U ' , $ value ));
205+ break ;
206+ case RegisteredClaims::ISSUER :
207+ $ this ->builder ->issuedBy ($ value );
208+ break ;
209+ case RegisteredClaims::AUDIENCE :
210+ $ this ->builder ->permittedFor ($ value );
211+ break ;
212+ case RegisteredClaims::SUBJECT :
213+ $ this ->builder ->relatedTo ($ value );
214+ break ;
215+ default :
216+ $ this ->builder ->withClaim ($ key , $ value );
217+ }
218+ }
219+
145220 /**
146221 * Get the signer instance.
147222 *
@@ -151,7 +226,7 @@ public function decode($token)
151226 */
152227 protected function getSigner ()
153228 {
154- if (! array_key_exists ($ this ->algo , $ this ->signers )) {
229+ if (!array_key_exists ($ this ->algo , $ this ->signers )) {
155230 throw new JWTException ('The given algorithm could not be found ' );
156231 }
157232
@@ -169,22 +244,26 @@ protected function isAsymmetric()
169244 }
170245
171246 /**
172- * {@inheritdoc}
247+ * Get the key used to sign the tokens.
248+ *
249+ * @return Key|string
173250 */
174251 protected function getSigningKey ()
175252 {
176253 return $ this ->isAsymmetric () ?
177- ( new Keychain ())-> getPrivateKey ( $ this ->getPrivateKey (), $ this ->getPassphrase ()) :
178- $ this ->getSecret ();
254+ InMemory:: plainText ( $ this ->getPrivateKey (), $ this ->getPassphrase () ?? '' ) :
255+ InMemory:: plainText ( $ this ->getSecret () );
179256 }
180257
181258 /**
182- * {@inheritdoc}
259+ * Get the key used to verify the tokens.
260+ *
261+ * @return Key|string
183262 */
184263 protected function getVerificationKey ()
185264 {
186265 return $ this ->isAsymmetric () ?
187- ( new Keychain ())-> getPublicKey ($ this ->getPublicKey ()) :
188- $ this ->getSecret ();
266+ InMemory:: plainText ($ this ->getPublicKey ()) :
267+ InMemory:: plainText ( $ this ->getSecret () );
189268 }
190269}
0 commit comments