Skip to content

Commit 775f1fd

Browse files
committed
feat: change to retreive plugins with getter
1 parent 8d04ef1 commit 775f1fd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+937
-395
lines changed
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"elysia-openid-client": patch
3+
---
4+
5+
Add auto refresh to `userinfo`, `introspect`, `resource`, `status` and `claims` endpoints

.changeset/friendly-planes-greet.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"elysia-openid-client": patch
3+
---
4+
5+
(Breaking) Changed `getEndpoints()` and `getAuthHook()` to getter methods `endpoints` and `authHook`

.changeset/large-donuts-hope.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"elysia-openid-client": patch
3+
---
4+
5+
(Breaking) Move hook settings to client options

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
### Patch Changes
66

77
- 05731b2: Add defineConfig
8-
- 05731b2: Change factory method name from create to factory
8+
- 05731b2: (Breaking) Change factory method name from `create` to `factory`
99
- 6797fa2: Update docs

README.ja.md

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
詳しい情報は[公式ドキュメント](https://macropygia.github.io/elysia-openid-client/ja/getting-started/)を参照
2323

2424
- 仕様・機能・特徴: [Introduction](https://macropygia.github.io/elysia-openid-client/ja/getting-started/)
25-
- 出力サンプル: [Sample Output](https://macropygia.github.io/elysia-openid-client/ja/sample-output/)
2625
- クイックスタートガイド: [Getting Started](https://macropygia.github.io/elysia-openid-client/ja/getting-started/)
2726

2827
## Contributing

README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
- All authentication/authorization information is stored on the server side.
1212
- The status is passed to routing using the [resolve](https://elysiajs.com/life-cycle/before-handle.html#resolve) hook.
13-
- Use cookies to identify users.
13+
- Use Cookie to identify users.
1414
- Depends on [Bun](https://bun.sh/).
1515
- Only TypeScript files included.
1616
- [Only works as ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).
@@ -22,7 +22,6 @@
2222
Detailed information can be found in the [official documentation](https://macropygia.github.io/elysia-openid-client/).
2323

2424
- List of features and specifications: [Introduction](https://macropygia.github.io/elysia-openid-client/)
25-
- [Sample Output](https://macropygia.github.io/elysia-openid-client/ja/sample-output/)
2625
- Quick start guide: [Getting Started](https://macropygia.github.io/elysia-openid-client/getting-started/)
2726

2827
## Contributing

__mock__/const.ts

+19-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { mock } from "bun:test";
2-
import { defaultCookieSettings, defaultSettings } from "@/const";
2+
import {
3+
defaultAuthHookSettings,
4+
defaultCookieSettings,
5+
defaultSettings,
6+
} from "@/const";
37
import type { OidcClient } from "@/core/OidcClient";
48
import { consoleLogger } from "@/loggers/consoleLogger";
59
import type {
@@ -8,6 +12,7 @@ import type {
812
OIDCClientSession,
913
} from "@/types";
1014
import type { Cookie } from "elysia";
15+
import { t } from "elysia";
1116
import type { IdTokenClaims } from "openid-client";
1217

1318
export type DeepPartial<T> = T extends object
@@ -46,6 +51,7 @@ export const mockBaseOptions = {
4651
},
4752
authParams: {},
4853
settings: defaultSettings,
54+
authHookSettings: defaultAuthHookSettings,
4955
cookieSettings: {
5056
...defaultCookieSettings,
5157
secure: false,
@@ -107,13 +113,18 @@ export const mockActiveSessionWithRealIdToken: OIDCClientActiveSession = {
107113
sessionExpiresAt: 5000000000000,
108114
};
109115

116+
export const mockActiveSessionWithRealIdTokenRefreshed: OIDCClientActiveSession =
117+
{
118+
...mockActiveSessionWithRealIdToken,
119+
accessToken: "mock-access-token-refreshed",
120+
refreshToken: "mock-refresh-token-refreshed",
121+
sessionExpiresAt: 5000000000001,
122+
};
123+
110124
export const mockActiveSessionWithRealIdTokenExpired: OIDCClientActiveSession =
111125
{
112-
sessionId: "mock-session-id",
126+
...mockActiveSessionWithRealIdToken,
113127
idToken: mockIdTokenExpired,
114-
accessToken: "mock-access-token",
115-
refreshToken: "mock-refresh-token",
116-
sessionExpiresAt: 5000000000000,
117128
};
118129

119130
export const mockPostInit = (sid?: string): RequestInit => ({
@@ -153,10 +164,9 @@ export const mockBaseClient = {
153164
updateSession: mock(),
154165
fetchSession: mock(),
155166
deleteSession: mock(),
156-
getSessionIdCookieType: mock(),
157-
getCookieDefinition: mock(),
158-
getAuthHook: mock(),
159-
getEndpoints: mock(),
167+
cookieTypeBox: t.Cookie({ "mock-cookie-name": t.String() }),
168+
createAuthHook: mock(),
169+
createEndpoints: mock(),
160170
logger: mockLogger,
161171
initialized: true,
162172
client: {},

__test__/general.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ describe("Integration/general", async () => {
2626
},
2727
authParams: {},
2828
});
29-
const endpoints = oidcClient.getEndpoints();
29+
const endpoints = oidcClient.endpoints;
3030
const app = new Elysia()
3131
.get("/", () => "home")
3232
.use(endpoints)
@@ -128,6 +128,6 @@ describe("Integration/general", async () => {
128128
});
129129

130130
test("beforeHandle", () => {
131-
expect(oidcClient.getAuthHook({ scope: "scoped" })).toBeTruthy();
131+
expect(oidcClient.authHook).toBeTruthy();
132132
});
133133
});

biome.json

+17-1
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,21 @@
3333
},
3434
"javascript": {
3535
"globals": ["Astro", "Bun"]
36-
}
36+
},
37+
"overrides": [
38+
{
39+
"include": ["*.test.ts"],
40+
"linter": {
41+
"rules": {
42+
"suspicious": {
43+
"noEmptyBlockStatements": "off",
44+
"noExplicitAny": "off"
45+
},
46+
"performance": {
47+
"noDelete": "off"
48+
}
49+
}
50+
}
51+
}
52+
]
3753
}

src/const.ts

+27-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import type { OIDCClientCookieSettings, OIDCClientSettings } from "@/types";
1+
import type {
2+
OIDCClientAuthHookSettings,
3+
OIDCClientCookieSettings,
4+
OIDCClientSettings,
5+
} from "@/types";
6+
import { t } from "elysia";
27
import type { LoggerOptions } from "pino";
38

49
/**
@@ -33,6 +38,19 @@ export const defaultCookieSettings: OIDCClientCookieSettings = {
3338
path: "/",
3439
};
3540

41+
/**
42+
* Auth hook settings
43+
*/
44+
export const defaultAuthHookSettings: Omit<
45+
OIDCClientAuthHookSettings,
46+
"loginRedirectUrl"
47+
> = {
48+
scope: "scoped",
49+
// loginRedirectUrl: `${pathPrefix}${loginPath}`,
50+
disableRedirect: false,
51+
autoRefresh: true,
52+
};
53+
3654
/**
3755
* Default pino options
3856
* - Do not add `never`
@@ -66,3 +84,11 @@ export const defaultLoggerOptions: Record<string, LoggerOptions> = {
6684
},
6785
},
6886
};
87+
88+
export const sessionDataTypeBox = t.Object({
89+
sessionId: t.String(),
90+
sessionExpiresAt: t.Number(),
91+
idToken: t.String(),
92+
accessToken: t.String(),
93+
refreshToken: t.Optional(t.String()),
94+
});

src/core/BaseOidcClient.ts

+16-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
import { defaultCookieSettings, defaultSettings } from "@/const";
1+
import {
2+
defaultAuthHookSettings,
3+
defaultCookieSettings,
4+
defaultSettings,
5+
} from "@/const";
26
import { SQLiteAdapter } from "@/dataAdapters/SQLiteAdapter";
37
import { consoleLogger } from "@/loggers/consoleLogger";
48
import { initialize } from "@/methods/initialize";
59
import type {
10+
OIDCClientAuthHookSettings,
611
OIDCClientCookieSettings,
712
OIDCClientDataAdapter,
813
OIDCClientLogger,
@@ -34,6 +39,8 @@ export class BaseOidcClient {
3439
settings: OIDCClientSettings;
3540
/** Cookie settings */
3641
cookieSettings: OIDCClientCookieSettings;
42+
/** Cookie settings */
43+
authHookSettings: OIDCClientAuthHookSettings;
3744
/** OIDC Issuer (Initialize at factory()) */
3845
issuer!: Issuer<BaseClient>;
3946
/** OIDC Issuer metadata (Initialize at factory()) */
@@ -61,6 +68,7 @@ export class BaseOidcClient {
6168
dataAdapter,
6269
settings,
6370
cookieSettings,
71+
authHookSettings,
6472
logger,
6573
} = options;
6674

@@ -80,6 +88,11 @@ export class BaseOidcClient {
8088
...defaultCookieSettings,
8189
...cookieSettings,
8290
};
91+
this.authHookSettings = {
92+
...defaultAuthHookSettings,
93+
loginRedirectUrl: `${this.settings.pathPrefix}${this.settings.loginPath}`,
94+
...authHookSettings,
95+
};
8396

8497
this.sessions = dataAdapter || new SQLiteAdapter();
8598

@@ -110,7 +123,7 @@ export class BaseOidcClient {
110123
* @public
111124
* @returns Record<string, string>
112125
*/
113-
public getPaths = (): OIDCClientPaths => {
126+
public get paths(): OIDCClientPaths {
114127
const {
115128
settings,
116129
settings: { pathPrefix },
@@ -127,5 +140,5 @@ export class BaseOidcClient {
127140
status: `${pathPrefix}${settings.statusPath}`,
128141
userinfo: `${pathPrefix}${settings.userinfoPath}`,
129142
};
130-
};
143+
}
131144
}

src/core/OidcClient.ts

+31-31
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1+
import { createAuthHook } from "@/methods/createAuthHook";
2+
import { createEndpoints } from "@/methods/createEndpoints";
13
import { createSession } from "@/methods/createSession";
24
import { deleteSession } from "@/methods/deleteSession";
35
import { fetchSession } from "@/methods/fetchSession";
4-
import { getAuthHook } from "@/methods/getAuthHook";
5-
import { getEndpoints } from "@/methods/getEndpoints";
66
import { updateSession } from "@/methods/updateSession";
7-
import type {
8-
AuthHookOptions,
9-
OIDCClientActiveSession,
10-
OIDCClientOptions,
11-
} from "@/types";
7+
import type { OIDCClientActiveSession, OIDCClientOptions } from "@/types";
128
import { t } from "elysia";
139
import type { TokenSet } from "openid-client";
1410
import { BaseOidcClient } from "./BaseOidcClient";
@@ -17,10 +13,19 @@ import { BaseOidcClient } from "./BaseOidcClient";
1713
* OpenID Connect client plugin for ElysiaJS
1814
* - Usage:
1915
* - `const client = await BaseOidcClient.factory(options);`
20-
* - `const endpoints = client.getEndpoints();`
21-
* - `const hook = client.getAuthHook();`
16+
* - `const endpoints = client.createEndpoints();`
17+
* - `const hook = client.createAuthHook();`
2218
*/
2319
export class OidcClient extends BaseOidcClient {
20+
protected constructor(options: OIDCClientOptions) {
21+
super(options);
22+
23+
this.createSession = createSession.bind(this);
24+
this.updateSession = updateSession.bind(this);
25+
this.fetchSession = fetchSession.bind(this);
26+
this.deleteSession = deleteSession.bind(this);
27+
}
28+
2429
/**
2530
* Create OidcClient instance
2631
* @param options
@@ -38,66 +43,61 @@ export class OidcClient extends BaseOidcClient {
3843
* @public
3944
* @returns [sessionId, authorizationUrl]
4045
*/
41-
public createSession = () => createSession.call(this);
46+
public createSession: () => Promise<[string, string]>;
4247

4348
/**
4449
* Update session in DB
4550
* @public
4651
* @param sessionId Session ID
4752
* @param tokenSet TokenSet
4853
*/
49-
public updateSession = async (
54+
public updateSession: (
5055
sessionId: string,
5156
tokenSet: TokenSet,
52-
): Promise<OIDCClientActiveSession | null> =>
53-
updateSession.call(this, sessionId, tokenSet);
57+
) => Promise<OIDCClientActiveSession | null>;
5458

5559
/**
5660
* Find and validate session from cookie and DB
5761
* @public
5862
* @param sessionId Sessison ID
5963
* @returns Session data or false
6064
*/
61-
public fetchSession = async (
65+
public fetchSession: (
6266
sessionId: string | undefined,
63-
): Promise<OIDCClientActiveSession | null> =>
64-
fetchSession.call(this, sessionId);
67+
) => Promise<OIDCClientActiveSession | null>;
6568

6669
/**
6770
* Delete session from DB
6871
* @protected
6972
* @param sessionId Session ID
7073
*/
71-
public deleteSession = async (sessionId: string) =>
72-
deleteSession.call(this, sessionId);
73-
74-
/**
75-
* Get session id cookie type definition for schema
76-
* @returns Type definition
77-
*/
78-
public getSessionIdCookieType = () => ({
79-
[this.cookieSettings.sessionIdName]: t.Optional(t.String()),
80-
});
74+
public deleteSession: (sessionId: string) => Promise<void>;
8175

8276
/**
8377
* Cookie definition for ElysiaJS
8478
* @public
8579
*/
86-
public getCookieDefinition = () => t.Cookie(this.getSessionIdCookieType());
80+
public get cookieTypeBox() {
81+
return t.Cookie({
82+
[this.cookieSettings.sessionIdName]: t.Optional(t.String()),
83+
});
84+
}
8785

8886
/**
8987
* Get onBeforeHandle for restricted endpoints
9088
* @public
91-
* @param options Options
9289
* @returns ElysiaJS Plugin
9390
*/
94-
public getAuthHook = (options?: Partial<AuthHookOptions>) =>
95-
getAuthHook.call(this, options);
91+
public get authHook() {
92+
return createAuthHook.call(this);
93+
}
9694

9795
/**
9896
* OpenID Connect client plugin for ElysiaJS
9997
* @public
10098
* @returns ElysiaJS Plugin
10199
*/
102-
public getEndpoints = () => getEndpoints.call(this);
100+
public get endpoints() {
101+
return createEndpoints.call(this);
102+
}
103103
}

src/core/baseOidcClient.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ describe("Unit/core/BaseOidcClient", () => {
2121
cookieSettings: defaultCookieSettings,
2222
});
2323
const { pathPrefix } = defaultSettings;
24-
expect(client.getPaths()).toMatchObject({
24+
expect(client.paths).toMatchObject({
2525
callback: `${pathPrefix}${defaultSettings.callbackPath}`,
2626
introspect: `${pathPrefix}${defaultSettings.introspectPath}`,
2727
login: `${pathPrefix}${defaultSettings.loginPath}`,

0 commit comments

Comments
 (0)