@elysiajs/jwt 0.6.0 → 0.6.2
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.
- package/dist/cjs/index.d.ts +1 -2
- package/dist/index.d.ts +1 -2
- package/package.json +54 -54
- package/src/index.ts +177 -0
package/dist/cjs/index.d.ts
CHANGED
|
@@ -18,8 +18,7 @@ export interface JWTOption<Name extends string | undefined = 'jwt', Schema exten
|
|
|
18
18
|
nbf?: string | number;
|
|
19
19
|
exp?: string | number;
|
|
20
20
|
}
|
|
21
|
-
export declare const jwt: <Name extends string = "jwt", Schema extends TSchema | undefined = undefined>({ name, secret, alg, crit, schema, nbf, exp, ...payload }: JWTOption<Name, Schema>) => Elysia<{
|
|
22
|
-
path: "";
|
|
21
|
+
export declare const jwt: <Name extends string = "jwt", Schema extends TSchema | undefined = undefined>({ name, secret, alg, crit, schema, nbf, exp, ...payload }: JWTOption<Name, Schema>) => Elysia<"", {
|
|
23
22
|
store: {};
|
|
24
23
|
error: {};
|
|
25
24
|
request: Record<Name extends string ? Name : "jwt", {
|
package/dist/index.d.ts
CHANGED
|
@@ -18,8 +18,7 @@ export interface JWTOption<Name extends string | undefined = 'jwt', Schema exten
|
|
|
18
18
|
nbf?: string | number;
|
|
19
19
|
exp?: string | number;
|
|
20
20
|
}
|
|
21
|
-
export declare const jwt: <Name extends string = "jwt", Schema extends TSchema | undefined = undefined>({ name, secret, alg, crit, schema, nbf, exp, ...payload }: JWTOption<Name, Schema>) => Elysia<{
|
|
22
|
-
path: "";
|
|
21
|
+
export declare const jwt: <Name extends string = "jwt", Schema extends TSchema | undefined = undefined>({ name, secret, alg, crit, schema, nbf, exp, ...payload }: JWTOption<Name, Schema>) => Elysia<"", {
|
|
23
22
|
store: {};
|
|
24
23
|
error: {};
|
|
25
24
|
request: Record<Name extends string ? Name : "jwt", {
|
package/package.json
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
2
|
+
"name": "@elysiajs/jwt",
|
|
3
|
+
"description": "Plugin for Elysia for using JWT Authentication",
|
|
4
|
+
"version": "0.6.2",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "saltyAom",
|
|
7
|
+
"url": "https://github.com/SaltyAom",
|
|
8
|
+
"email": "saltyaom@gmail.com"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/elysiajs/elysia-jwt"
|
|
13
|
+
},
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"exports": {
|
|
16
|
+
"bun": "./dist/index.js",
|
|
17
|
+
"node": "./dist/cjs/index.js",
|
|
18
|
+
"require": "./dist/cjs/index.js",
|
|
19
|
+
"import": "./dist/index.js",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"types": "./dist/index.ts",
|
|
23
|
+
"bugs": "https://github.com/elysiajs/elysia-jwt/issues",
|
|
24
|
+
"homepage": "https://github.com/elysiajs/elysia-jwt",
|
|
25
|
+
"keywords": [
|
|
26
|
+
"elysia",
|
|
27
|
+
"jwt",
|
|
28
|
+
"auth",
|
|
29
|
+
"authentication"
|
|
30
|
+
],
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"scripts": {
|
|
33
|
+
"dev": "bun run --hot example/index.ts",
|
|
34
|
+
"test": "bun wiptest && npm run test:node",
|
|
35
|
+
"test:node": "npm install --prefix ./test/node/cjs/ && npm install --prefix ./test/node/esm/ && node ./test/node/cjs/index.js && node ./test/node/esm/index.js",
|
|
36
|
+
"build": "rimraf dist && tsc --project tsconfig.esm.json && tsc --project tsconfig.cjs.json",
|
|
37
|
+
"release": "npm run build && npm run test && npm publish --access public"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"jose": "^4.14.4"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@elysiajs/cookie": "^0.3.0",
|
|
44
|
+
"@sinclair/typebox": "^0.30.4",
|
|
45
|
+
"@types/node": "^20.1.4",
|
|
46
|
+
"bun-types": "^0.5.8",
|
|
47
|
+
"elysia": "0.6.6",
|
|
48
|
+
"eslint": "^8.40.0",
|
|
49
|
+
"rimraf": "4.3",
|
|
50
|
+
"typescript": "^5.1.6"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"elysia": ">= 0.5.12"
|
|
54
|
+
}
|
|
55
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ValidationError,
|
|
3
|
+
getSchemaValidator,
|
|
4
|
+
Elysia,
|
|
5
|
+
type Context,
|
|
6
|
+
ElysiaInstance
|
|
7
|
+
} from 'elysia'
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
SignJWT,
|
|
11
|
+
jwtVerify,
|
|
12
|
+
type JWTPayload,
|
|
13
|
+
type JWSHeaderParameters
|
|
14
|
+
} from 'jose'
|
|
15
|
+
|
|
16
|
+
import { Type as t } from '@sinclair/typebox'
|
|
17
|
+
import type { Static, TObject, TSchema } from '@sinclair/typebox'
|
|
18
|
+
|
|
19
|
+
type UnwrapSchema<
|
|
20
|
+
Schema extends TSchema | undefined,
|
|
21
|
+
Fallback = unknown
|
|
22
|
+
> = Schema extends TSchema ? Static<NonNullable<Schema>> : Fallback
|
|
23
|
+
|
|
24
|
+
export interface JWTPayloadSpec {
|
|
25
|
+
iss?: string
|
|
26
|
+
sub?: string
|
|
27
|
+
aud?: string | string[]
|
|
28
|
+
jti?: string
|
|
29
|
+
nbf?: number
|
|
30
|
+
exp?: number
|
|
31
|
+
iat?: number
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface JWTOption<
|
|
35
|
+
Name extends string | undefined = 'jwt',
|
|
36
|
+
Schema extends TSchema | undefined = undefined
|
|
37
|
+
> extends JWSHeaderParameters,
|
|
38
|
+
Omit<JWTPayload, 'nbf' | 'exp'> {
|
|
39
|
+
/**
|
|
40
|
+
* Name to decorate method as
|
|
41
|
+
*
|
|
42
|
+
* ---
|
|
43
|
+
* @example
|
|
44
|
+
* For example, `jwt` will decorate Context with `Context.jwt`
|
|
45
|
+
*
|
|
46
|
+
* ```typescript
|
|
47
|
+
* app
|
|
48
|
+
* .decorate({
|
|
49
|
+
* name: 'myJWTNamespace',
|
|
50
|
+
* secret: process.env.JWT_SECRETS
|
|
51
|
+
* })
|
|
52
|
+
* .get('/sign/:name', ({ myJWTNamespace, params }) => {
|
|
53
|
+
* return myJWTNamespace.sign(params)
|
|
54
|
+
* })
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
name?: Name
|
|
58
|
+
/**
|
|
59
|
+
* JWT Secret
|
|
60
|
+
*/
|
|
61
|
+
secret: string
|
|
62
|
+
/**
|
|
63
|
+
* Type strict validation for JWT payload
|
|
64
|
+
*/
|
|
65
|
+
schema?: Schema
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* JWT Not Before
|
|
69
|
+
*
|
|
70
|
+
* @see [RFC7519#section-4.1.5](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.5)
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
nbf?: string | number
|
|
74
|
+
/**
|
|
75
|
+
* JWT Expiration Time
|
|
76
|
+
*
|
|
77
|
+
* @see [RFC7519#section-4.1.4](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4)
|
|
78
|
+
*/
|
|
79
|
+
exp?: string | number
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export const jwt = <
|
|
83
|
+
Name extends string = 'jwt',
|
|
84
|
+
Schema extends TSchema | undefined = undefined
|
|
85
|
+
>({
|
|
86
|
+
name = 'jwt' as Name,
|
|
87
|
+
secret,
|
|
88
|
+
// Start JWT Header
|
|
89
|
+
alg = 'HS256',
|
|
90
|
+
crit,
|
|
91
|
+
schema,
|
|
92
|
+
// End JWT Header
|
|
93
|
+
// Start JWT Payload
|
|
94
|
+
nbf,
|
|
95
|
+
exp,
|
|
96
|
+
...payload
|
|
97
|
+
}: // End JWT Payload
|
|
98
|
+
JWTOption<Name, Schema>) => {
|
|
99
|
+
if (!secret) throw new Error("Secret can't be empty")
|
|
100
|
+
|
|
101
|
+
const key = new TextEncoder().encode(secret)
|
|
102
|
+
|
|
103
|
+
const validator = schema
|
|
104
|
+
? getSchemaValidator(
|
|
105
|
+
t.Union([
|
|
106
|
+
schema as any,
|
|
107
|
+
t.Object({
|
|
108
|
+
iss: t.Optional(t.String()),
|
|
109
|
+
sub: t.Optional(t.String()),
|
|
110
|
+
aud: t.Optional(
|
|
111
|
+
t.Union([t.String(), t.Array(t.String())])
|
|
112
|
+
),
|
|
113
|
+
jti: t.Optional(t.String()),
|
|
114
|
+
nbf: t.Optional(t.Union([t.String(), t.Number()])),
|
|
115
|
+
exp: t.Optional(t.Union([t.String(), t.Number()])),
|
|
116
|
+
iat: t.Optional(t.String())
|
|
117
|
+
})
|
|
118
|
+
]) as any,
|
|
119
|
+
{}
|
|
120
|
+
)
|
|
121
|
+
: undefined
|
|
122
|
+
|
|
123
|
+
return new Elysia({
|
|
124
|
+
name: '@elysiajs/jwt',
|
|
125
|
+
seed: {
|
|
126
|
+
name,
|
|
127
|
+
secret,
|
|
128
|
+
alg,
|
|
129
|
+
crit,
|
|
130
|
+
schema,
|
|
131
|
+
nbf,
|
|
132
|
+
exp,
|
|
133
|
+
...payload
|
|
134
|
+
}
|
|
135
|
+
}).decorate(name as Name extends string ? Name : 'jwt', {
|
|
136
|
+
sign: (
|
|
137
|
+
morePayload: UnwrapSchema<Schema, Record<string, string>> &
|
|
138
|
+
JWTPayloadSpec
|
|
139
|
+
) => {
|
|
140
|
+
let jwt = new SignJWT({
|
|
141
|
+
...payload,
|
|
142
|
+
...morePayload,
|
|
143
|
+
nbf: undefined,
|
|
144
|
+
exp: undefined
|
|
145
|
+
}).setProtectedHeader({
|
|
146
|
+
alg,
|
|
147
|
+
crit
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
if (nbf) jwt = jwt.setNotBefore(nbf)
|
|
151
|
+
if (exp) jwt = jwt.setExpirationTime(exp)
|
|
152
|
+
|
|
153
|
+
return jwt.sign(key)
|
|
154
|
+
},
|
|
155
|
+
verify: async (
|
|
156
|
+
jwt?: string
|
|
157
|
+
): Promise<
|
|
158
|
+
| (UnwrapSchema<Schema, Record<string, string>> & JWTPayloadSpec)
|
|
159
|
+
| false
|
|
160
|
+
> => {
|
|
161
|
+
if (!jwt) return false
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
const data: any = (await jwtVerify(jwt, key)).payload
|
|
165
|
+
|
|
166
|
+
if (validator && !validator!.Check(data))
|
|
167
|
+
throw new ValidationError('JWT', validator, data)
|
|
168
|
+
|
|
169
|
+
return data
|
|
170
|
+
} catch (_) {
|
|
171
|
+
return false
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export default jwt
|