Skip to content

Commit 563f7dc

Browse files
authored
Merge pull request #269 from robinnydahl/main
Implement config variable to allow iat to remain unchanged claim when refreshing a token
2 parents 9af3bd9 + 0a1c221 commit 563f7dc

File tree

7 files changed

+80
-5
lines changed

7 files changed

+80
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ You can find and compare releases at the [GitHub release page](https://github.co
1818
Please see (https://github.com/PHP-Open-Source-Saver/jwt-auth/releases/tag/2.8.0)
1919

2020
### Added
21+
- #268 Implement config variable to allow iat to remain unchanged claim when refreshing a token
2122
- Adds support for Laravel 12
2223
- Adds CI testing for PHP 8.4
2324
- Don't show jwt secret if show option is false even if the key is updated

config/config.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,19 @@
9696
| Refresh time to live
9797
|--------------------------------------------------------------------------
9898
|
99-
| Specify the length of time (in minutes) that the token can be refreshed
100-
| within. I.E. The user can refresh their token within a 2 week window of
101-
| the original token being created until they must re-authenticate.
102-
| Defaults to 2 weeks.
99+
| Specify the length of time (in minutes) that the token can be refreshed within.
100+
| This defines the refresh window, during which the user can refresh their token
101+
| before re-authentication is required.
102+
|
103+
| By default, a refresh will NOT issue a new "iat" (issued at) timestamp. If changed
104+
| to true, each refresh will issue a new "iat" timestamp, extending the refresh
105+
| period from the most recent refresh. This results in a rolling refresh
106+
|
107+
| To retain a fluid refresh window from the last refresh action (i.e., the behavior between
108+
| version 2.5.0 and 2.8.2), set "refresh_iat" to true. With this setting, the refresh
109+
| window will renew with each subsequent refresh.
110+
|
111+
| The refresh ttl defaults to 2 weeks.
103112
|
104113
| You can also set this to null, to yield an infinite refresh time.
105114
| Some may want this instead of never expiring tokens for e.g. a mobile app.
@@ -108,6 +117,7 @@
108117
|
109118
*/
110119

120+
'refresh_iat' => env('JWT_REFRESH_IAT', false),
111121
'refresh_ttl' => (int) env('JWT_REFRESH_TTL', 20160),
112122

113123
/*

src/Manager.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ class Manager
5252
*/
5353
protected $blacklistEnabled = true;
5454

55+
/**
56+
* The refresh iat flag.
57+
*
58+
* @var bool
59+
*/
60+
protected $refreshIat = false;
61+
5562
/**
5663
* the persistent claims.
5764
*
@@ -182,7 +189,7 @@ protected function buildRefreshClaims(Payload $payload)
182189
$persistentClaims,
183190
[
184191
'sub' => $payload['sub'],
185-
'iat' => Utils::now()->timestamp,
192+
'iat' => $this->refreshIat ? Utils::now()->timestamp : $payload['iat'],
186193
]
187194
);
188195
}
@@ -267,4 +274,18 @@ public function setPersistentClaims(array $claims)
267274

268275
return $this;
269276
}
277+
278+
/**
279+
* Set whether the refresh iat is enabled.
280+
*
281+
* @param bool $enabled
282+
*
283+
* @return $this
284+
*/
285+
public function setRefreshIat($refreshIat)
286+
{
287+
$this->refreshIat = $refreshIat;
288+
289+
return $this;
290+
}
270291
}

src/Providers/AbstractServiceProvider.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ protected function registerManager()
213213
);
214214

215215
return $instance->setBlacklistEnabled((bool) $app->make('config')->get('jwt.blacklist_enabled'))
216+
->setRefreshIat((bool) $app->make('config')->get('jwt.refresh_iat', false))
216217
->setPersistentClaims($app->make('config')->get('jwt.persistent_claims'))
217218
->setBlackListExceptionEnabled((bool) $app->make('config')->get('jwt.show_black_list_exception', 0));
218219
});

tests/.ManagerTest.php.swp

24 KB
Binary file not shown.

tests/DefaultConfigValuesTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ public function testTtlShouldBeSet()
4444
$this->assertEquals(60, $this->configuration['ttl']);
4545
}
4646

47+
public function testRefreshIatShouldBeSet()
48+
{
49+
$this->assertEquals(false, $this->configuration['refresh_iat']);
50+
}
51+
4752
public function testRefreshTtlShouldBeSet()
4853
{
4954
$this->assertEquals(20160, $this->configuration['refresh_ttl']);

tests/ManagerTest.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ public function testBuildRefreshClaimsMethodWillRefreshTheIAT()
203203
$buildRefreshClaimsMethod = $managerClass->getMethod('buildRefreshClaims');
204204
$buildRefreshClaimsMethod->setAccessible(true);
205205
$managerInstance = new Manager($this->jwt, $this->blacklist, $this->factory);
206+
$managerInstance->setRefreshIat(true);
206207

207208
$firstResult = $buildRefreshClaimsMethod->invokeArgs($managerInstance, [$payload]);
208209
Carbon::setTestNow(Carbon::now()->addMinutes(2));
@@ -220,6 +221,42 @@ public function testBuildRefreshClaimsMethodWillRefreshTheIAT()
220221
$this->assertNotEquals($firstResult['iat'], $secondResult['iat']);
221222
}
222223

224+
public function testBuildRefreshClaimsMethodWillNotRefreshTheIAT()
225+
{
226+
$claims = [
227+
new Subject(1),
228+
new Issuer('http://example.com'),
229+
new Expiration($this->testNowTimestamp - 3600),
230+
new NotBefore($this->testNowTimestamp),
231+
new IssuedAt($this->testNowTimestamp),
232+
new JwtId('foo'),
233+
];
234+
$collection = Collection::make($claims);
235+
236+
$this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection);
237+
$payload = new Payload($collection, $this->validator);
238+
239+
$managerClass = new \ReflectionClass(Manager::class);
240+
$buildRefreshClaimsMethod = $managerClass->getMethod('buildRefreshClaims');
241+
$buildRefreshClaimsMethod->setAccessible(true);
242+
$managerInstance = new Manager($this->jwt, $this->blacklist, $this->factory);
243+
244+
$firstResult = $buildRefreshClaimsMethod->invokeArgs($managerInstance, [$payload]);
245+
Carbon::setTestNow(Carbon::now()->addMinutes(2));
246+
$secondResult = $buildRefreshClaimsMethod->invokeArgs($managerInstance, [$payload]);
247+
248+
$this->assertIsInt($firstResult['iat']);
249+
$this->assertIsInt($secondResult['iat']);
250+
251+
$carbonTimestamp = Carbon::createFromTimestamp($firstResult['iat']);
252+
$this->assertInstanceOf(Carbon::class, $carbonTimestamp);
253+
254+
$carbonTimestamp = Carbon::createFromTimestamp($secondResult['iat']);
255+
$this->assertInstanceOf(Carbon::class, $carbonTimestamp);
256+
257+
$this->assertEquals($firstResult['iat'], $secondResult['iat']);
258+
}
259+
223260
/**
224261
* @throws InvalidClaimException
225262
*/

0 commit comments

Comments
 (0)