Skip to content

Commit ede342e

Browse files
committed
Only return refresh tokens if modified
Before the refresh token was always returned if the access token was modified. But since they can be modified independently of each other we should also check that.
1 parent ba552cb commit ede342e

File tree

6 files changed

+54
-25
lines changed

6 files changed

+54
-25
lines changed

.changeset/eight-clouds-sleep.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@labdigital/federated-token": minor
3+
---
4+
5+
Only return refresh tokens if modified

src/gateway.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ describe("GatewayAuthPlugin", () => {
1919
const typeDefs = `#graphql
2020
type Query {
2121
testToken(create: Boolean): String!
22+
refreshToken: String!
2223
}
2324
`;
2425
const resolvers = {
@@ -33,9 +34,20 @@ describe("GatewayAuthPlugin", () => {
3334
token: "bar",
3435
exp: Date.now() + 1000,
3536
});
37+
context.federatedToken?.setRefreshToken("foo", "bar");
3638
}
3739
return JSON.stringify(context.federatedToken);
3840
},
41+
refreshToken: (
42+
_: any,
43+
context: PublicFederatedTokenContext
44+
) => {
45+
context.federatedToken?.setAccessToken("foo", {
46+
token: "bar",
47+
exp: Date.now() + 1000,
48+
});
49+
return JSON.stringify(context.federatedToken);
50+
},
3951
},
4052
};
4153

src/gateway.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export class GatewayAuthPlugin<TContext extends PublicFederatedTokenContext>
4646
}
4747
}
4848

49-
const rt = request.http?.headers.get("x-refresh-token")
49+
const rt = request.http?.headers.get("x-refresh-token");
5050
if (rt) {
5151
await contextValue.federatedToken?.loadRefreshJWT(this.signer, rt);
5252
}
@@ -58,17 +58,18 @@ export class GatewayAuthPlugin<TContext extends PublicFederatedTokenContext>
5858
const { contextValue, response } = requestContext;
5959
const token = contextValue?.federatedToken;
6060

61-
if (!token?.isModified()) {
62-
return;
63-
}
64-
const accessToken = await token.createAccessJWT(this.signer);
65-
if (accessToken) {
66-
response.http.headers.set("X-Access-Token", accessToken);
61+
if (token?.isAccessTokenModified()) {
62+
const accessToken = await token.createAccessJWT(this.signer);
63+
if (accessToken) {
64+
response.http.headers.set("X-Access-Token", accessToken);
65+
}
6766
}
6867

69-
const refreshToken = await token.createRefreshJWT(this.signer);
70-
if (refreshToken) {
71-
response.http.headers.set("X-Refresh-Token", refreshToken);
68+
if (token?.isRefreshTokenModified()) {
69+
const refreshToken = await token.createRefreshJWT(this.signer);
70+
if (refreshToken) {
71+
response.http.headers.set("X-Refresh-Token", refreshToken);
72+
}
7273
}
7374
}
7475
}

src/plugin.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ export class FederatedAuthPlugin<TContext extends FederatedTokenContext>
4040

4141
const t = contextValue.federatedToken;
4242

43-
if (t.isModified()) {
43+
if (t.isAccessTokenModified()) {
4444
const val = t.dumpAccessToken();
4545
if (val) {
4646
response.http.headers.set("X-Access-Token", val);
4747
}
4848
}
4949

50-
if (t.refreshTokens) {
50+
if (t.isRefreshTokenModified()) {
5151
const val = t.dumpRefreshToken();
5252
if (val) {
5353
response.http.headers.set("X-Refresh-Token", val);

src/token.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ describe("FederatedToken", () => {
1111
};
1212
federatedToken.setAccessToken("exampleName", token);
1313
assert.equal(federatedToken.tokens.exampleName, token);
14-
assert.isTrue(federatedToken.isModified());
14+
assert.isTrue(federatedToken.isAccessTokenModified());
1515
});
1616

1717
test("setRefreshToken", () => {
@@ -20,14 +20,14 @@ describe("FederatedToken", () => {
2020
assert.equal(federatedToken.refreshTokens.exampleName, "exampleToken");
2121
});
2222

23-
test("isModified", () => {
23+
test("isAccessTokenModified", () => {
2424
const federatedToken = new FederatedToken();
25-
assert.isFalse(federatedToken.isModified());
25+
assert.isFalse(federatedToken.isAccessTokenModified());
2626
federatedToken.setAccessToken("exampleName", {
2727
token: "exampleToken",
2828
exp: 1234567890,
2929
});
30-
assert.isTrue(federatedToken.isModified());
30+
assert.isTrue(federatedToken.isAccessTokenModified());
3131
});
3232

3333
test("loadAccessToken", () => {
@@ -66,7 +66,7 @@ describe("FederatedToken", () => {
6666
);
6767

6868
assert.isFalse(
69-
federatedToken.isModified(),
69+
federatedToken.isAccessTokenModified(),
7070
"isModified should be false when trackModified is false and token is modified"
7171
);
7272
});
@@ -107,7 +107,7 @@ describe("FederatedToken", () => {
107107
);
108108

109109
assert.isTrue(
110-
federatedToken.isModified(),
110+
federatedToken.isAccessTokenModified(),
111111
"isModified should be true when trackModified is true and token is modified"
112112
);
113113
});

src/token.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,33 @@ export class FederatedToken {
1515
refreshTokens: Record<string, string>;
1616
values: Record<string, any>;
1717

18-
private _modified: boolean;
18+
private _accessTokenModified: boolean;
19+
private _refreshTokenModified: boolean;
1920

2021
constructor() {
2122
this.tokens = {};
2223
this.refreshTokens = {};
2324
this.values = {};
24-
this._modified = false;
25+
this._accessTokenModified = false;
26+
this._refreshTokenModified = false;
2527
}
2628

2729
setAccessToken(name: string, token: AccessToken) {
2830
this.tokens[name] = token;
29-
this._modified = true;
31+
this._accessTokenModified = true;
3032
}
3133

3234
setRefreshToken(name: string, token: string) {
3335
this.refreshTokens[name] = token;
36+
this._refreshTokenModified = true;
3437
}
3538

36-
isModified() {
37-
return this._modified;
39+
isAccessTokenModified() {
40+
return this._accessTokenModified;
41+
}
42+
43+
isRefreshTokenModified() {
44+
return this._refreshTokenModified;
3845
}
3946

4047
loadAccessToken(at: string, trackModified = false) {
@@ -49,7 +56,7 @@ export class FederatedToken {
4956
// Merge tokens into this object
5057
for (const k in token.tokens) {
5158
if (trackModified && !isEqual(this.tokens[k], token.tokens[k])) {
52-
this._modified = true;
59+
this._accessTokenModified = true;
5360
}
5461

5562
this.tokens[k] = token.tokens[k];
@@ -76,7 +83,7 @@ export class FederatedToken {
7683
}
7784

7885

79-
loadRefreshToken(value: string) {
86+
loadRefreshToken(value: string, trackModified = false) {
8087
const refreshTokens: Record<string, string> = JSON.parse(
8188
Buffer.from(value, "base64").toString("ascii")
8289
);
@@ -86,6 +93,10 @@ export class FederatedToken {
8693
// Merge tokens in object
8794
for (const k in refreshTokens) {
8895
this.refreshTokens[k] = refreshTokens[k];
96+
97+
if (trackModified && !isEqual(this.refreshTokens[k], refreshTokens[k])) {
98+
this._refreshTokenModified = true;
99+
}
89100
}
90101
}
91102

0 commit comments

Comments
 (0)