@go-mondo/nextjs-auth 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,71 @@
1
+ import { C as Claims, S as SessionInterface, U as UserProfile, a as SessionAuthorization, b as SessionAuthentication } from './types-CbrOw4QQ.cjs';
2
+ export { A as AnyRequest, c as AnyResponse, I as IdTokenClaims, d as SessionPart } from './types-CbrOw4QQ.cjs';
3
+
4
+ /**
5
+ * Serializable session payload stored across sealed cookies.
6
+ */
7
+ type SerializedSession<UserClaims extends Claims = Claims> = SessionInterface<UserClaims> & {
8
+ authentication?: SessionAuthentication;
9
+ authorization?: SessionAuthorization;
10
+ };
11
+ /**
12
+ * The user's session.
13
+ *
14
+ * The public session shape combines the base user claims cookie with optional
15
+ * authentication and authorization cookies.
16
+ *
17
+ * @category Server
18
+ */
19
+ declare class Session<UserClaims extends Claims = Claims> implements SessionInterface<UserClaims> {
20
+ /**
21
+ * The authenticated user (claims from the `id_token`)
22
+ */
23
+ user: UserProfile<UserClaims>;
24
+ /**
25
+ * A timestamp when authentication / session occurred
26
+ */
27
+ issuedAt: number;
28
+ /**
29
+ * A timestamp when authentication / session was last updated (touched)
30
+ */
31
+ updatedAt: number;
32
+ /**
33
+ * A timestamp when the authentication / session is set to expire
34
+ */
35
+ expiresAt: number;
36
+ /**
37
+ * OAuth access-token state stored separately from the base session payload.
38
+ */
39
+ authorization?: SessionAuthorization;
40
+ /**
41
+ * OIDC authentication token state stored separately from the base session
42
+ * payload.
43
+ */
44
+ authentication?: SessionAuthentication;
45
+ [key: string]: any;
46
+ /**
47
+ * Creates a normalized session object from sealed cookie payloads.
48
+ */
49
+ constructor(props: SerializedSession<UserClaims>);
50
+ }
51
+
52
+ interface SessionOptions<UserClaims extends Claims = Claims> {
53
+ /**
54
+ * Whether this route should also roll the session expiry forward.
55
+ *
56
+ * Defaults to `true`.
57
+ */
58
+ touch?: boolean;
59
+ /**
60
+ * Transform the session prior to returning it
61
+ *
62
+ * @param session - Current session, or `undefined` when missing or expired.
63
+ */
64
+ transform?: (session: Session<UserClaims> | undefined) => unknown;
65
+ }
66
+ /**
67
+ * Builds a route handler for the configured session route.
68
+ */
69
+ type SessionHandler<UserClaims extends Claims = Claims> = (options?: SessionOptions<UserClaims>) => (req: Request) => Promise<Response>;
70
+
71
+ export { Claims, type SerializedSession, Session, SessionAuthentication, SessionAuthorization, type SessionHandler, SessionInterface, type SessionOptions, UserProfile };
@@ -0,0 +1,71 @@
1
+ import { C as Claims, S as SessionInterface, U as UserProfile, a as SessionAuthorization, b as SessionAuthentication } from './types-CbrOw4QQ.js';
2
+ export { A as AnyRequest, c as AnyResponse, I as IdTokenClaims, d as SessionPart } from './types-CbrOw4QQ.js';
3
+
4
+ /**
5
+ * Serializable session payload stored across sealed cookies.
6
+ */
7
+ type SerializedSession<UserClaims extends Claims = Claims> = SessionInterface<UserClaims> & {
8
+ authentication?: SessionAuthentication;
9
+ authorization?: SessionAuthorization;
10
+ };
11
+ /**
12
+ * The user's session.
13
+ *
14
+ * The public session shape combines the base user claims cookie with optional
15
+ * authentication and authorization cookies.
16
+ *
17
+ * @category Server
18
+ */
19
+ declare class Session<UserClaims extends Claims = Claims> implements SessionInterface<UserClaims> {
20
+ /**
21
+ * The authenticated user (claims from the `id_token`)
22
+ */
23
+ user: UserProfile<UserClaims>;
24
+ /**
25
+ * A timestamp when authentication / session occurred
26
+ */
27
+ issuedAt: number;
28
+ /**
29
+ * A timestamp when authentication / session was last updated (touched)
30
+ */
31
+ updatedAt: number;
32
+ /**
33
+ * A timestamp when the authentication / session is set to expire
34
+ */
35
+ expiresAt: number;
36
+ /**
37
+ * OAuth access-token state stored separately from the base session payload.
38
+ */
39
+ authorization?: SessionAuthorization;
40
+ /**
41
+ * OIDC authentication token state stored separately from the base session
42
+ * payload.
43
+ */
44
+ authentication?: SessionAuthentication;
45
+ [key: string]: any;
46
+ /**
47
+ * Creates a normalized session object from sealed cookie payloads.
48
+ */
49
+ constructor(props: SerializedSession<UserClaims>);
50
+ }
51
+
52
+ interface SessionOptions<UserClaims extends Claims = Claims> {
53
+ /**
54
+ * Whether this route should also roll the session expiry forward.
55
+ *
56
+ * Defaults to `true`.
57
+ */
58
+ touch?: boolean;
59
+ /**
60
+ * Transform the session prior to returning it
61
+ *
62
+ * @param session - Current session, or `undefined` when missing or expired.
63
+ */
64
+ transform?: (session: Session<UserClaims> | undefined) => unknown;
65
+ }
66
+ /**
67
+ * Builds a route handler for the configured session route.
68
+ */
69
+ type SessionHandler<UserClaims extends Claims = Claims> = (options?: SessionOptions<UserClaims>) => (req: Request) => Promise<Response>;
70
+
71
+ export { Claims, type SerializedSession, Session, SessionAuthentication, SessionAuthorization, type SessionHandler, SessionInterface, type SessionOptions, UserProfile };
@@ -0,0 +1,43 @@
1
+ // src/session/model.ts
2
+ var Session = class {
3
+ /**
4
+ * The authenticated user (claims from the `id_token`)
5
+ */
6
+ user;
7
+ /**
8
+ * A timestamp when authentication / session occurred
9
+ */
10
+ issuedAt;
11
+ /**
12
+ * A timestamp when authentication / session was last updated (touched)
13
+ */
14
+ updatedAt;
15
+ /**
16
+ * A timestamp when the authentication / session is set to expire
17
+ */
18
+ expiresAt;
19
+ /**
20
+ * OAuth access-token state stored separately from the base session payload.
21
+ */
22
+ authorization;
23
+ /**
24
+ * OIDC authentication token state stored separately from the base session
25
+ * payload.
26
+ */
27
+ authentication;
28
+ /**
29
+ * Creates a normalized session object from sealed cookie payloads.
30
+ */
31
+ constructor(props) {
32
+ this.user = props.user;
33
+ this.issuedAt = props.issuedAt;
34
+ this.updatedAt = props.updatedAt;
35
+ this.expiresAt = props.expiresAt;
36
+ this.authentication = props.authentication;
37
+ this.authorization = props.authorization;
38
+ }
39
+ };
40
+
41
+ export { Session };
42
+ //# sourceMappingURL=session.js.map
43
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/session/model.ts"],"names":[],"mappings":";AA2BO,IAAM,UAAN,MAEP;AAAA;AAAA;AAAA;AAAA,EAIE,IAAA;AAAA;AAAA;AAAA;AAAA,EAKA,QAAA;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA;AAAA;AAAA;AAAA;AAAA,EAKA,aAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,KAAA,EAAsC;AAChD,IAAA,IAAA,CAAK,OAAO,KAAA,CAAM,IAAA;AAClB,IAAA,IAAA,CAAK,WAAW,KAAA,CAAM,QAAA;AACtB,IAAA,IAAA,CAAK,YAAY,KAAA,CAAM,SAAA;AACvB,IAAA,IAAA,CAAK,YAAY,KAAA,CAAM,SAAA;AACvB,IAAA,IAAA,CAAK,iBAAiB,KAAA,CAAM,cAAA;AAC5B,IAAA,IAAA,CAAK,gBAAgB,KAAA,CAAM,aAAA;AAAA,EAC7B;AACF","file":"session.js","sourcesContent":["import type { TokenEndpointResponse } from '../oauth/types';\nimport type {\n Claims,\n IdTokenClaims,\n SessionAuthentication,\n SessionAuthorization,\n SessionInterface,\n UserProfile,\n} from './types';\n\n/**\n * Serializable session payload stored across sealed cookies.\n */\nexport type SerializedSession<UserClaims extends Claims = Claims> =\n SessionInterface<UserClaims> & {\n authentication?: SessionAuthentication;\n authorization?: SessionAuthorization;\n };\n\n/**\n * The user's session.\n *\n * The public session shape combines the base user claims cookie with optional\n * authentication and authorization cookies.\n *\n * @category Server\n */\nexport class Session<UserClaims extends Claims = Claims>\n implements SessionInterface<UserClaims>\n{\n /**\n * The authenticated user (claims from the `id_token`)\n */\n user: UserProfile<UserClaims>;\n\n /**\n * A timestamp when authentication / session occurred\n */\n issuedAt: number;\n\n /**\n * A timestamp when authentication / session was last updated (touched)\n */\n updatedAt: number;\n\n /**\n * A timestamp when the authentication / session is set to expire\n */\n expiresAt: number;\n\n /**\n * OAuth access-token state stored separately from the base session payload.\n */\n authorization?: SessionAuthorization;\n\n /**\n * OIDC authentication token state stored separately from the base session\n * payload.\n */\n authentication?: SessionAuthentication;\n\n [key: string]: any;\n\n /**\n * Creates a normalized session object from sealed cookie payloads.\n */\n constructor(props: SerializedSession<UserClaims>) {\n this.user = props.user;\n this.issuedAt = props.issuedAt;\n this.updatedAt = props.updatedAt;\n this.expiresAt = props.expiresAt;\n this.authentication = props.authentication;\n this.authorization = props.authorization;\n }\n}\n\n/**\n * Converts an OIDC token endpoint response into the session model stored in\n * sealed cookies.\n *\n * @param tokenEndpointResponse - Token endpoint response returned by\n * `openid-client`.\n */\nexport function fromTokenEndpointResponse<UserClaims extends Claims = Claims>(\n tokenEndpointResponse: TokenEndpointResponse,\n): Session<UserClaims> {\n const { iat, exp, aud, iss, nonce, ...user } = decodeJwt<IdTokenClaims>(\n tokenEndpointResponse.id_token as string,\n );\n\n const {\n id_token,\n access_token,\n scope,\n expires_in,\n expires_at,\n refresh_token,\n token_type,\n ...remainder\n } = tokenEndpointResponse;\n\n const authorization = access_token\n ? {\n accessToken: access_token,\n scope,\n expiresAt: Math.floor(Date.now() / 1000) + Number(expires_in),\n refreshToken: refresh_token,\n type: token_type,\n }\n : undefined;\n\n const authentication = id_token\n ? {\n idToken: id_token,\n }\n : undefined;\n\n return Object.assign(\n new Session({\n user: user as UserProfile<UserClaims>,\n issuedAt: iat,\n updatedAt: iat,\n expiresAt: exp,\n authorization,\n authentication,\n }),\n remainder,\n );\n}\n\nfunction decodeJwt<TClaims>(jwt: string): TClaims {\n const [, payload] = jwt.split('.');\n\n if (!payload) {\n throw new TypeError('Invalid JWT payload.');\n }\n\n const normalized = payload.replace(/-/g, '+').replace(/_/g, '/');\n const padded = normalized.padEnd(\n normalized.length + ((4 - (normalized.length % 4)) % 4),\n '=',\n );\n\n const decoded =\n typeof atob === 'function'\n ? atob(padded)\n : Buffer.from(padded, 'base64').toString('binary');\n\n const json = decodeURIComponent(\n Array.from(\n decoded,\n (char) => `%${char.charCodeAt(0).toString(16).padStart(2, '0')}`,\n ).join(''),\n );\n\n return JSON.parse(json) as TClaims;\n}\n"]}
@@ -0,0 +1,108 @@
1
+ type AnyRequest = Request;
2
+ type AnyResponse = Response;
3
+ /**
4
+ * Key-value store for the user's claims.
5
+ *
6
+ * @category Server
7
+ */
8
+ interface Claims {
9
+ [key: string]: any;
10
+ }
11
+ /**
12
+ * Claims decoded from an OIDC `id_token`.
13
+ */
14
+ type IdTokenClaims<ExtraClaims extends Claims = Claims> = UserProfile<ExtraClaims> & {
15
+ nonce: string;
16
+ iat: number;
17
+ iss: string;
18
+ aud: string;
19
+ exp: number;
20
+ };
21
+ /**
22
+ * Normalized user profile claims exposed on a session.
23
+ */
24
+ type UserProfile<ExtraClaims extends Claims> = {
25
+ /**
26
+ * The tenant context
27
+ */
28
+ tnt: string;
29
+ /**
30
+ * The user's name
31
+ */
32
+ name?: string;
33
+ /**
34
+ * The user's family / last name
35
+ */
36
+ family_name?: string;
37
+ /**
38
+ * The user's given / first name
39
+ */
40
+ given_name?: string;
41
+ /**
42
+ * The user's primary email address
43
+ */
44
+ email?: string;
45
+ /**
46
+ * Identifies whether the email is verified
47
+ */
48
+ email_verified?: boolean;
49
+ /**
50
+ * The user's primary phone number
51
+ */
52
+ phone_number?: string;
53
+ /**
54
+ * Identifies whether the phone number is verified
55
+ */
56
+ phone_number_verified?: boolean;
57
+ } & ExtraClaims;
58
+ interface SessionInterface<UserClaims extends Claims> {
59
+ /**
60
+ * The authenticated user
61
+ */
62
+ user: UserProfile<UserClaims>;
63
+ /**
64
+ * A timestamp when authentication / session occurred
65
+ */
66
+ issuedAt: number;
67
+ /**
68
+ * A timestamp when authentication / session was last updated (touched)
69
+ */
70
+ updatedAt: number;
71
+ /**
72
+ * A timestamp when the authentication / session is set to expire
73
+ */
74
+ expiresAt: number;
75
+ }
76
+ interface SessionAuthentication {
77
+ /**
78
+ * The raw OIDC token
79
+ */
80
+ idToken: string;
81
+ }
82
+ interface SessionAuthorization {
83
+ /**
84
+ * Bearer token value used for authorized resource requests.
85
+ */
86
+ accessToken: string;
87
+ /**
88
+ * Space-delimited scopes granted to the access token.
89
+ */
90
+ scope?: string | undefined;
91
+ /**
92
+ * Epoch seconds when the access token expires.
93
+ */
94
+ expiresAt: number;
95
+ /**
96
+ * A refresh token, used to obtain a new access token.
97
+ *
98
+ * This token is only populated if the `refresh_token` scope is requested
99
+ */
100
+ refreshToken?: string | undefined;
101
+ /**
102
+ * Token type returned by the identity provider, usually `Bearer`.
103
+ */
104
+ type?: string | undefined;
105
+ }
106
+ type SessionPart<UserClaims extends Claims = Claims> = SessionInterface<UserClaims> | SessionAuthentication | SessionAuthorization;
107
+
108
+ export type { AnyRequest as A, Claims as C, IdTokenClaims as I, SessionInterface as S, UserProfile as U, SessionAuthorization as a, SessionAuthentication as b, AnyResponse as c, SessionPart as d };
@@ -0,0 +1,108 @@
1
+ type AnyRequest = Request;
2
+ type AnyResponse = Response;
3
+ /**
4
+ * Key-value store for the user's claims.
5
+ *
6
+ * @category Server
7
+ */
8
+ interface Claims {
9
+ [key: string]: any;
10
+ }
11
+ /**
12
+ * Claims decoded from an OIDC `id_token`.
13
+ */
14
+ type IdTokenClaims<ExtraClaims extends Claims = Claims> = UserProfile<ExtraClaims> & {
15
+ nonce: string;
16
+ iat: number;
17
+ iss: string;
18
+ aud: string;
19
+ exp: number;
20
+ };
21
+ /**
22
+ * Normalized user profile claims exposed on a session.
23
+ */
24
+ type UserProfile<ExtraClaims extends Claims> = {
25
+ /**
26
+ * The tenant context
27
+ */
28
+ tnt: string;
29
+ /**
30
+ * The user's name
31
+ */
32
+ name?: string;
33
+ /**
34
+ * The user's family / last name
35
+ */
36
+ family_name?: string;
37
+ /**
38
+ * The user's given / first name
39
+ */
40
+ given_name?: string;
41
+ /**
42
+ * The user's primary email address
43
+ */
44
+ email?: string;
45
+ /**
46
+ * Identifies whether the email is verified
47
+ */
48
+ email_verified?: boolean;
49
+ /**
50
+ * The user's primary phone number
51
+ */
52
+ phone_number?: string;
53
+ /**
54
+ * Identifies whether the phone number is verified
55
+ */
56
+ phone_number_verified?: boolean;
57
+ } & ExtraClaims;
58
+ interface SessionInterface<UserClaims extends Claims> {
59
+ /**
60
+ * The authenticated user
61
+ */
62
+ user: UserProfile<UserClaims>;
63
+ /**
64
+ * A timestamp when authentication / session occurred
65
+ */
66
+ issuedAt: number;
67
+ /**
68
+ * A timestamp when authentication / session was last updated (touched)
69
+ */
70
+ updatedAt: number;
71
+ /**
72
+ * A timestamp when the authentication / session is set to expire
73
+ */
74
+ expiresAt: number;
75
+ }
76
+ interface SessionAuthentication {
77
+ /**
78
+ * The raw OIDC token
79
+ */
80
+ idToken: string;
81
+ }
82
+ interface SessionAuthorization {
83
+ /**
84
+ * Bearer token value used for authorized resource requests.
85
+ */
86
+ accessToken: string;
87
+ /**
88
+ * Space-delimited scopes granted to the access token.
89
+ */
90
+ scope?: string | undefined;
91
+ /**
92
+ * Epoch seconds when the access token expires.
93
+ */
94
+ expiresAt: number;
95
+ /**
96
+ * A refresh token, used to obtain a new access token.
97
+ *
98
+ * This token is only populated if the `refresh_token` scope is requested
99
+ */
100
+ refreshToken?: string | undefined;
101
+ /**
102
+ * Token type returned by the identity provider, usually `Bearer`.
103
+ */
104
+ type?: string | undefined;
105
+ }
106
+ type SessionPart<UserClaims extends Claims = Claims> = SessionInterface<UserClaims> | SessionAuthentication | SessionAuthorization;
107
+
108
+ export type { AnyRequest as A, Claims as C, IdTokenClaims as I, SessionInterface as S, UserProfile as U, SessionAuthorization as a, SessionAuthentication as b, AnyResponse as c, SessionPart as d };
package/package.json ADDED
@@ -0,0 +1,146 @@
1
+ {
2
+ "name": "@go-mondo/nextjs-auth",
3
+ "version": "0.1.0",
4
+ "description": "Next.js authentication helpers for Mondo Identity.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "main": "./dist/client.cjs",
9
+ "module": "./dist/client.js",
10
+ "types": "./dist/client.d.ts",
11
+ "packageManager": "pnpm@10.32.1",
12
+ "engines": {
13
+ "node": ">=20"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/go-mondo/nextjs-auth.git"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/go-mondo/nextjs-auth/issues"
21
+ },
22
+ "homepage": "https://github.com/go-mondo/nextjs-auth#readme",
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "exports": {
30
+ ".": {
31
+ "import": {
32
+ "types": "./dist/client.d.ts",
33
+ "default": "./dist/client.js"
34
+ },
35
+ "require": {
36
+ "types": "./dist/client.d.cts",
37
+ "default": "./dist/client.cjs"
38
+ }
39
+ },
40
+ "./client": {
41
+ "import": {
42
+ "types": "./dist/client.d.ts",
43
+ "default": "./dist/client.js"
44
+ },
45
+ "require": {
46
+ "types": "./dist/client.d.cts",
47
+ "default": "./dist/client.cjs"
48
+ }
49
+ },
50
+ "./config": {
51
+ "import": {
52
+ "types": "./dist/config.d.ts",
53
+ "default": "./dist/config.js"
54
+ },
55
+ "require": {
56
+ "types": "./dist/config.d.cts",
57
+ "default": "./dist/config.cjs"
58
+ }
59
+ },
60
+ "./errors": {
61
+ "import": {
62
+ "types": "./dist/errors.d.ts",
63
+ "default": "./dist/errors.js"
64
+ },
65
+ "require": {
66
+ "types": "./dist/errors.d.cts",
67
+ "default": "./dist/errors.cjs"
68
+ }
69
+ },
70
+ "./oauth": {
71
+ "import": {
72
+ "types": "./dist/oauth.d.ts",
73
+ "default": "./dist/oauth.js"
74
+ },
75
+ "require": {
76
+ "types": "./dist/oauth.d.cts",
77
+ "default": "./dist/oauth.cjs"
78
+ }
79
+ },
80
+ "./hooks": {
81
+ "import": {
82
+ "types": "./dist/hooks.d.ts",
83
+ "default": "./dist/hooks.js"
84
+ },
85
+ "require": {
86
+ "types": "./dist/hooks.d.cts",
87
+ "default": "./dist/hooks.cjs"
88
+ }
89
+ },
90
+ "./session": {
91
+ "import": {
92
+ "types": "./dist/session.d.ts",
93
+ "default": "./dist/session.js"
94
+ },
95
+ "require": {
96
+ "types": "./dist/session.d.cts",
97
+ "default": "./dist/session.cjs"
98
+ }
99
+ },
100
+ "./package.json": "./package.json"
101
+ },
102
+ "scripts": {
103
+ "build": "tsup",
104
+ "check": "pnpm run type-check && pnpm run build && pnpm run type-check:examples && pnpm run lint && pnpm run format:check && pnpm run test",
105
+ "clean": "rimraf dist",
106
+ "dev:example:client": "pnpm --filter @go-mondo/nextjs-auth-example-client-profile dev",
107
+ "dev:example:server": "pnpm --filter @go-mondo/nextjs-auth-example-server-profile dev",
108
+ "format": "biome format --write .",
109
+ "format:check": "biome format .",
110
+ "lint": "biome lint .",
111
+ "lint:fix": "biome lint --write .",
112
+ "prepare": "husky",
113
+ "commitlint": "commitlint",
114
+ "test": "vitest run",
115
+ "test:coverage": "vitest run --coverage",
116
+ "test:watch": "vitest",
117
+ "type-check": "tsc --noEmit",
118
+ "type-check:examples": "pnpm --filter @go-mondo/nextjs-auth-example-server-profile type-check && pnpm --filter @go-mondo/nextjs-auth-example-client-profile type-check",
119
+ "prepack": "pnpm run build"
120
+ },
121
+ "dependencies": {
122
+ "cookie": "^1.0.2",
123
+ "iron-session": "^8.0.4",
124
+ "openid-client": "^6.8.1",
125
+ "zod": "4.4.3"
126
+ },
127
+ "peerDependencies": {
128
+ "@tanstack/react-query": ">=5",
129
+ "react": ">=18",
130
+ "next": ">=15"
131
+ },
132
+ "devDependencies": {
133
+ "@biomejs/biome": "^2.2.0",
134
+ "@commitlint/cli": "^19.8.1",
135
+ "@commitlint/config-conventional": "^19.8.1",
136
+ "@tanstack/react-query": "^5.95.2",
137
+ "@types/node": "^20.19.37",
138
+ "@vitest/coverage-v8": "^3.2.3",
139
+ "husky": "^9.1.7",
140
+ "next": "^16.0.3",
141
+ "rimraf": "^6.1.2",
142
+ "tsup": "^8.5.1",
143
+ "typescript": "^5.9.3",
144
+ "vitest": "^3.2.3"
145
+ }
146
+ }