Skip to content

Commit 5b74d58

Browse files
committed
feat: Clean up expired tokens
1 parent e1f25c5 commit 5b74d58

6 files changed

Lines changed: 14 additions & 18 deletions

File tree

packages/uma/config/credentials/verifiers/default.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"TypedVerifier:_verifiers_value": {
3939
"@id": "urn:uma:default:RefreshTokenVerifier",
4040
"@type": "RefreshTokenVerifier",
41-
"refreshStore": { "@id": "urn:uma:default:RefreshTokenStore" }
41+
"refreshStore": { "@id": "urn:uma:default:TokenStore" }
4242
}
4343
},
4444
{

packages/uma/config/dialog/negotiators/default.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"refreshTokenIssuer": {
1919
"@id": "urn:uma:default:RefreshTokenIssuer",
2020
"@type": "StoredRefreshTokenIssuer",
21-
"refreshStore": { "@id": "urn:uma:default:RefreshTokenStore" }
21+
"refreshStore": { "@id": "urn:uma:default:TokenStore" }
2222
}
2323
}
2424
}

packages/uma/config/routes/tokens.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"refreshTokenHandler": {
2121
"@id": "urn:uma:default:RefreshTokenHandler",
2222
"@type": "RefreshTokenHandler",
23-
"refreshStore": { "@id": "urn:uma:default:RefreshTokenStore" },
23+
"refreshStore": { "@id": "urn:uma:default:TokenStore" },
2424
"negotiator": { "@id": "urn:uma:default:Negotiator" }
2525
}
2626
},

packages/uma/config/tokens/storage/default.json

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
"@graph": [
66
{
77
"@id": "urn:uma:default:TokenStore",
8-
"@type": "MemoryMapStorage"
9-
},
10-
{
11-
"@id": "urn:uma:default:RefreshTokenStore",
12-
"@type": "MemoryMapStorage"
8+
"@type": "WrappedExpiringStorage",
9+
"source": {
10+
"@type": "MemoryMapStorage"
11+
}
1312
}
1413
]
1514
}

packages/uma/src/tokens/JwtTokenFactory.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { BadRequestHttpError, createErrorMessage, JwkGenerator, KeyValueStorage } from '@solid/community-server';
1+
import { BadRequestHttpError, createErrorMessage, ExpiringStorage, JwkGenerator, } from '@solid/community-server';
22
import { getLoggerFor } from 'global-logger-factory';
33
import { importJWK, jwtVerify, SignJWT } from 'jose';
4+
import ms, { StringValue } from 'ms';
45
import { randomUUID } from 'node:crypto';
56
import { array, reType } from '../util/ReType';
67
import { Permission } from '../views/Permission';
@@ -30,7 +31,7 @@ export class JwtTokenFactory extends TokenFactory {
3031
constructor(
3132
protected readonly keyGen: JwkGenerator,
3233
protected readonly issuer: string,
33-
protected readonly tokenStore: KeyValueStorage<string, AccessToken>,
34+
protected readonly tokenStore: ExpiringStorage<string, AccessToken>,
3435
protected readonly params: JwtTokenParams = { expirationTime: '30m', aud: 'solid' },
3536
) {
3637
super();
@@ -54,9 +55,7 @@ export class JwtTokenFactory extends TokenFactory {
5455
.sign(jwk);
5556

5657
this.logger.debug(`Issued new JWT Token ${JSON.stringify(token)}`);
57-
// TODO: tokenstore should expire tokens eventually; can use expiring storage,
58-
// or just normal store with timer-based cleanup.
59-
await this.tokenStore.set(jwt, token);
58+
await this.tokenStore.set(jwt, token, ms(this.params.expirationTime as StringValue));
6059
return { token: jwt, tokenType: 'Bearer' };
6160
}
6261

packages/uma/src/tokens/StoredRefreshTokenIssuer.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { KeyValueStorage } from '@solid/community-server';
1+
import { ExpiringStorage } from '@solid/community-server';
22
import ms, { StringValue } from 'ms';
33
import { randomUUID } from 'node:crypto';
44
import { ClaimSet } from '../credentials/ClaimSet';
@@ -14,21 +14,19 @@ export class StoredRefreshTokenIssuer implements RefreshTokenIssuer {
1414
protected readonly refreshExpiration: number;
1515

1616
public constructor(
17-
protected readonly refreshStore: KeyValueStorage<string, RefreshInformation>,
17+
protected readonly refreshStore: ExpiringStorage<string, RefreshInformation>,
1818
refreshExpiration: string = '7d',
1919
) {
2020
this.refreshExpiration = ms(refreshExpiration as StringValue);
2121
}
2222

2323
public async issue(claims: ClaimSet, permissions: Permission[]): Promise<string> {
2424
const refreshToken = randomUUID();
25-
// TODO: expired tokens should be removed; can use expiring storage,
26-
// or just normal store with timer-based cleanup.
2725
await this.refreshStore.set(refreshToken, {
2826
claims,
2927
permissions,
3028
expiration: Date.now() + this.refreshExpiration,
31-
});
29+
}, this.refreshExpiration);
3230
return refreshToken;
3331
}
3432
}

0 commit comments

Comments
 (0)