Skip to content

Commit

Permalink
feat: token-set (#48)
Browse files Browse the repository at this point in the history
* feat: token-set

* refactor: nowRoundToSec
  • Loading branch information
wangsijie authored Oct 18, 2021
1 parent 12e0891 commit 2e98b05
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 0 deletions.
64 changes: 64 additions & 0 deletions packages/client/src/token-set.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { SignJWT } from 'jose/jwt/sign';
import { generateKeyPair } from 'jose/util/generate_key_pair';

import TokenSet from './token-set';
import { nowRoundToSec } from './utils';

describe('TokenSet', () => {
test('sets the expire_at automatically from expires_in', () => {
const ts = new TokenSet({
access_token: 'at',
expires_in: 300,
refresh_token: 'rt',
id_token: 'it',
});

expect(ts).toHaveProperty('expiresAt', nowRoundToSec() + 300);
expect(ts).toHaveProperty('expiresIn', 300);
expect(ts.expired()).toBeFalsy();
});

test('expired token sets expires_in to -30', () => {
const ts = new TokenSet({
access_token: 'at',
expires_in: -30,
refresh_token: 'rt',
id_token: 'it',
});

expect(ts).toHaveProperty('expiresAt', nowRoundToSec() - 30);
expect(ts).toHaveProperty('expiresIn', 0);
expect(ts.expired()).toBeTruthy();
});

test('provides a #claims getter', async () => {
const ts = new TokenSet({
access_token: 'at',
expires_in: -30,
refresh_token: 'rt',
id_token: await new SignJWT({})
.setProtectedHeader({ alg: 'RS256' })
.setAudience('foo')
.setSubject('foz')
.setIssuer('logto')
.setIssuedAt()
.setExpirationTime('2h')
.sign((await generateKeyPair('RS256')).privateKey),
});

expect(ts.claims().aud).toEqual('foo');
expect(ts.claims().sub).toEqual('foz');
expect(ts.claims().iss).toEqual('logto');
});

test('#claims throws if no id_token is present', () => {
const ts = new TokenSet({
access_token: 'at',
expires_in: 300,
refresh_token: 'rt',
id_token: '',
});

expect(() => ts.claims()).toThrowError('id_token not present in TokenSet');
});
});
35 changes: 35 additions & 0 deletions packages/client/src/token-set.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { TokenSetParameters } from './grant-token';
import { decodeToken, IDToken, nowRoundToSec } from './utils';

export default class TokenSet {
public accessToken: string;
public idToken: string;
public refreshToken: string;
public expiresAt = 0;
constructor(tokenSet: TokenSetParameters) {
this.accessToken = tokenSet.access_token;
this.expiresIn = tokenSet.expires_in;
this.idToken = tokenSet.id_token;
this.refreshToken = tokenSet.refresh_token;
}

get expiresIn(): number {
return Math.max(this.expiresAt - nowRoundToSec(), 0);
}

set expiresIn(value: number) {
this.expiresAt = nowRoundToSec() + value;
}

public expired(): boolean {
return this.expiresIn === 0;
}

public claims(): IDToken {
if (!this.idToken) {
throw new TypeError('id_token not present in TokenSet');
}

return decodeToken(this.idToken);
}
}
2 changes: 2 additions & 0 deletions packages/client/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,5 @@ export const decodeToken = (token: string): IDToken => {
throw new Error('invalid token: JSON parse failed');
}
};

export const nowRoundToSec = () => Math.floor(Date.now() / 1000);

0 comments on commit 2e98b05

Please sign in to comment.