Skip to content

Commit 134df7c

Browse files
committed
feat: add support for fastify token sources
Implement a new adapter pattern to work with cookies and headers and create an express and fastify adapter (separate packages). For now this should be 100% backwards compatible, since the express adapter is still part of the of the core module, but in the future we would move this out of the package
1 parent a4515eb commit 134df7c

30 files changed

+1525
-305
lines changed

.changeset/neat-tigers-taste.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@labdigital/federated-token-express-adapter": minor
3+
"@labdigital/federated-token-fastify-adapter": minor
4+
"@labdigital/federated-token-apollo": minor
5+
"@labdigital/federated-token": minor
6+
---
7+
8+
Add ability to support multiple http frameworks and implement fastify

.vscode/settings.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"editor.codeActionsOnSave": {
3+
"quickfix.biome": "explicit",
4+
"source.fixAll.eslint": "never",
5+
"source.organizeImports": "never",
6+
"source.organizeImports.biome": "explicit"
7+
},
8+
"[json]": {
9+
"editor.defaultFormatter": "biomejs.biome"
10+
},
11+
"[typescriptreact]": {
12+
"editor.defaultFormatter": "biomejs.biome"
13+
},
14+
"[javascript]": {
15+
"editor.defaultFormatter": "biomejs.biome"
16+
}
17+
}

packages/apollo/src/gateway.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import type { PublicFederatedTokenContext } from "./context";
1313

1414
type GatewayOptions = {
1515
signer: TokenSigner;
16-
source: TokenSource;
16+
source: TokenSource<unknown, unknown>;
1717
};
1818

1919
/**
@@ -27,7 +27,7 @@ export class GatewayAuthPlugin<TContext extends PublicFederatedTokenContext>
2727
implements ApolloServerPlugin, GraphQLRequestListener<TContext>
2828
{
2929
private signer: TokenSigner;
30-
private tokenSource: TokenSource;
30+
private tokenSource: TokenSource<unknown, unknown>;
3131

3232
constructor(options: GatewayOptions) {
3333
this.signer = options.signer;

packages/core/package.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,20 @@
55
"module": "./dist/index.js",
66
"main": "./dist/index.cjs",
77
"types": "./dist/index.d.ts",
8+
"type": "module",
89
"exports": {
910
"./package.json": "./package.json",
1011
".": {
1112
"import": "./dist/index.js",
12-
"require": "./dist/index.cjs"
13+
"require": "./dist/index.cjs",
14+
"types": "./dist/index.d.ts"
15+
},
16+
"./tokensource": {
17+
"import": "./dist/tokensource/index.js",
18+
"require": "./dist/tokensource/index.cjs",
19+
"types": "./dist/tokensource/index.d.ts"
1320
}
1421
},
15-
"type": "module",
1622
"keywords": ["graphql", "authentication"],
1723
"author": "Lab Digital <[email protected]>",
1824
"license": "MIT",

packages/core/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ export { PublicFederatedToken } from "./jwt";
22
export { KeyManager, TokenSigner, type KeyManagerInterface } from "./sign";
33
export { FederatedToken } from "./token";
44
export {
5+
type BaseCookieSourceOptions,
6+
BaseCookieTokenSource,
57
CompositeTokenSource,
68
CookieTokenSource,
79
HeaderTokenSource,

packages/core/src/tokensource/base.ts

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,27 @@
1-
import type { Request, Response } from "express";
1+
export interface TokenSource<TRequest, TResponse> {
2+
deleteAccessToken(request: TRequest, response: TResponse): void;
3+
deleteRefreshToken(request: TRequest, response: TResponse): void;
4+
deleteDataToken(request: TRequest, response: TResponse): void;
25

3-
export interface TokenSource {
4-
deleteAccessToken(request: Request, response: Response): void;
5-
deleteRefreshToken(request: Request, response: Response): void;
6-
deleteDataToken(
7-
request: Request,
8-
response: Response<any, Record<string, any>>,
9-
): void;
10-
11-
getAccessToken(request: Request): string | undefined;
12-
getDataToken(request: Request): string | undefined;
13-
getRefreshToken(request: Request): string | undefined;
6+
getAccessToken(request: TRequest): string | undefined;
7+
getDataToken(request: TRequest): string | undefined;
8+
getRefreshToken(request: TRequest): string | undefined;
149

1510
setDataToken(
16-
request: Request,
17-
response: Response,
11+
request: TRequest,
12+
response: TResponse,
1813
token: string,
1914
isAuthenticated?: boolean,
2015
): void;
2116
setAccessToken(
22-
request: Request,
23-
response: Response,
17+
request: TRequest,
18+
response: TResponse,
2419
token: string,
2520
isAuthenticated?: boolean,
2621
): void;
2722
setRefreshToken(
28-
request: Request,
29-
response: Response,
23+
request: TRequest,
24+
response: TResponse,
3025
token: string,
3126
isAuthenticated?: boolean,
3227
): void;

packages/core/src/tokensource/composite.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
import type { Request, Response } from "express";
22
import type { TokenSource } from "./base";
33

4-
export class CompositeTokenSource implements TokenSource {
5-
private sources: TokenSource[];
4+
export class CompositeTokenSource<TRequest = Request, TResponse = Response>
5+
implements TokenSource<TRequest, TResponse>
6+
{
7+
private sources: TokenSource<TRequest, TResponse>[];
68

7-
constructor(sources: TokenSource[]) {
9+
constructor(sources: TokenSource<TRequest, TResponse>[]) {
810
this.sources = sources;
911
}
1012

11-
deleteAccessToken(request: Request, response: Response): void {
13+
deleteAccessToken(request: TRequest, response: TResponse): void {
1214
for (const source of this.sources) {
1315
source.deleteAccessToken(request, response);
1416
}
1517
}
1618

17-
deleteRefreshToken(request: Request, response: Response): void {
19+
deleteRefreshToken(request: TRequest, response: TResponse): void {
1820
for (const source of this.sources) {
1921
source.deleteRefreshToken(request, response);
2022
}
2123
}
2224

23-
getAccessToken(request: Request): string {
25+
getAccessToken(request: TRequest): string {
2426
for (const source of this.sources) {
2527
const token = source.getAccessToken(request);
2628
if (token) {
@@ -30,7 +32,7 @@ export class CompositeTokenSource implements TokenSource {
3032
return "";
3133
}
3234

33-
getRefreshToken(request: Request): string {
35+
getRefreshToken(request: TRequest): string {
3436
for (const source of this.sources) {
3537
const token = source.getRefreshToken(request);
3638
if (token) {
@@ -40,7 +42,7 @@ export class CompositeTokenSource implements TokenSource {
4042
return "";
4143
}
4244

43-
getDataToken(request: Request): string {
45+
getDataToken(request: TRequest): string {
4446
for (const source of this.sources) {
4547
const token = source.getDataToken(request);
4648
if (token) {
@@ -51,8 +53,8 @@ export class CompositeTokenSource implements TokenSource {
5153
}
5254

5355
setAccessToken(
54-
request: Request,
55-
response: Response,
56+
request: TRequest,
57+
response: TResponse,
5658
token: string,
5759
isAuthenticated = false,
5860
) {
@@ -62,8 +64,8 @@ export class CompositeTokenSource implements TokenSource {
6264
}
6365

6466
setRefreshToken(
65-
request: Request,
66-
response: Response,
67+
request: TRequest,
68+
response: TResponse,
6769
token: string,
6870
isAuthenticated = false,
6971
) {
@@ -73,8 +75,8 @@ export class CompositeTokenSource implements TokenSource {
7375
}
7476

7577
setDataToken(
76-
request: Request,
77-
response: Response,
78+
request: TRequest,
79+
response: TResponse,
7880
token: string,
7981
isAuthenticated = false,
8082
) {
@@ -83,7 +85,7 @@ export class CompositeTokenSource implements TokenSource {
8385
}
8486
}
8587

86-
deleteDataToken(request: Request, response: Response): void {
88+
deleteDataToken(request: TRequest, response: TResponse): void {
8789
for (const source of this.sources) {
8890
source.deleteDataToken(request, response);
8991
}

0 commit comments

Comments
 (0)