@absolutejs/auth 0.3.2 → 0.5.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.
- package/.env.example +9 -0
- package/README.md +3 -3
- package/dist/index.js +2026 -1
- package/dist/src/authorize.d.ts +34 -3
- package/dist/src/callback.d.ts +4 -4
- package/dist/src/index.d.ts +77 -32
- package/dist/src/profile.d.ts +47 -0
- package/dist/src/protectRoute.d.ts +1 -1
- package/dist/src/refresh.d.ts +11 -8
- package/dist/src/revoke.d.ts +19 -18
- package/dist/src/{logout.d.ts → signout.d.ts} +7 -5
- package/dist/src/status.d.ts +4 -2
- package/dist/src/typeGuards.d.ts +0 -10
- package/dist/src/types.d.ts +46 -26
- package/dist/src/utils.d.ts +2 -14
- package/drizzle.config.ts +12 -0
- package/eslint.config.mjs +245 -0
- package/package.json +21 -6
- package/dist/src/providers.d.ts +0 -51
- package/src/authorize.ts +0 -119
- package/src/callback.ts +0 -117
- package/src/constants.ts +0 -13
- package/src/index.ts +0 -88
- package/src/logout.ts +0 -39
- package/src/protectRoute.ts +0 -33
- package/src/providers.ts +0 -109
- package/src/refresh.ts +0 -63
- package/src/revoke.ts +0 -61
- package/src/sessionStore.ts +0 -10
- package/src/status.ts +0 -100
- package/src/typeGuards.ts +0 -32
- package/src/types.ts +0 -78
- package/src/utils.ts +0 -47
- package/tsconfig.json +0 -17
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
// eslint.config.mjs
|
|
2
|
+
import { dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
|
|
6
|
+
import pluginJs from '@eslint/js';
|
|
7
|
+
import stylisticTs from '@stylistic/eslint-plugin-ts';
|
|
8
|
+
import tsParser from '@typescript-eslint/parser';
|
|
9
|
+
import absolutePlugin from 'eslint-plugin-absolute';
|
|
10
|
+
import importPlugin from 'eslint-plugin-import';
|
|
11
|
+
import jsxA11yPlugin from 'eslint-plugin-jsx-a11y';
|
|
12
|
+
import promisePlugin from 'eslint-plugin-promise';
|
|
13
|
+
import reactPlugin from 'eslint-plugin-react';
|
|
14
|
+
import reactCompilerPlugin from 'eslint-plugin-react-compiler';
|
|
15
|
+
import reactHooksPlugin from 'eslint-plugin-react-hooks';
|
|
16
|
+
import securityPlugin from 'eslint-plugin-security';
|
|
17
|
+
import globals from 'globals';
|
|
18
|
+
import tseslint from 'typescript-eslint';
|
|
19
|
+
|
|
20
|
+
export default [
|
|
21
|
+
{
|
|
22
|
+
ignores: ['example/build/**']
|
|
23
|
+
},
|
|
24
|
+
pluginJs.configs.recommended,
|
|
25
|
+
|
|
26
|
+
...tseslint.configs.recommended,
|
|
27
|
+
|
|
28
|
+
{
|
|
29
|
+
files: ['**/*.{ts,tsx}'],
|
|
30
|
+
languageOptions: {
|
|
31
|
+
globals: globals.browser,
|
|
32
|
+
parser: tsParser,
|
|
33
|
+
parserOptions: {
|
|
34
|
+
createDefaultProgram: true,
|
|
35
|
+
project: './tsconfig.json',
|
|
36
|
+
tsconfigRootDir: __dirname
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
{
|
|
42
|
+
files: ['**/*.{ts,tsx}'],
|
|
43
|
+
plugins: { '@stylistic/ts': stylisticTs },
|
|
44
|
+
rules: {
|
|
45
|
+
'@stylistic/ts/padding-line-between-statements': [
|
|
46
|
+
'error',
|
|
47
|
+
{ blankLine: 'always', next: 'return', prev: '*' }
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
{
|
|
53
|
+
files: ['**/*.{js,mjs,cjs,ts,tsx,jsx}'],
|
|
54
|
+
ignores: ['example/build/**'],
|
|
55
|
+
plugins: {
|
|
56
|
+
absolute: absolutePlugin,
|
|
57
|
+
import: importPlugin,
|
|
58
|
+
promise: promisePlugin,
|
|
59
|
+
security: securityPlugin
|
|
60
|
+
},
|
|
61
|
+
rules: {
|
|
62
|
+
'absolute/explicit-object-types': 'error',
|
|
63
|
+
'absolute/localize-react-props': 'error',
|
|
64
|
+
'absolute/max-depth-extended': ['error', 1],
|
|
65
|
+
'absolute/max-jsxnesting': ['error', 5],
|
|
66
|
+
'absolute/min-var-length': [
|
|
67
|
+
'error',
|
|
68
|
+
{ allowedVars: ['_', 'id', 'db', 'OK'], minLength: 3 }
|
|
69
|
+
],
|
|
70
|
+
'absolute/no-button-navigation': 'error',
|
|
71
|
+
'absolute/no-explicit-return-type': 'error',
|
|
72
|
+
'absolute/no-inline-prop-types': 'error',
|
|
73
|
+
'absolute/no-multi-style-objects': 'error',
|
|
74
|
+
'absolute/no-nested-jsx-return': 'error',
|
|
75
|
+
'absolute/no-or-none-component': 'error',
|
|
76
|
+
'absolute/no-transition-cssproperties': 'error',
|
|
77
|
+
'absolute/no-type-cast': 'error',
|
|
78
|
+
'absolute/no-unnecessary-div': 'error',
|
|
79
|
+
'absolute/no-unnecessary-key': 'error',
|
|
80
|
+
'absolute/no-useless-function': 'error',
|
|
81
|
+
'absolute/seperate-style-files': 'error',
|
|
82
|
+
'absolute/sort-exports': [
|
|
83
|
+
'error',
|
|
84
|
+
{
|
|
85
|
+
caseSensitive: true,
|
|
86
|
+
natural: true,
|
|
87
|
+
order: 'asc',
|
|
88
|
+
variablesBeforeFunctions: true
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
'absolute/sort-keys-fixable': [
|
|
92
|
+
'error',
|
|
93
|
+
{
|
|
94
|
+
caseSensitive: true,
|
|
95
|
+
natural: true,
|
|
96
|
+
order: 'asc',
|
|
97
|
+
variablesBeforeFunctions: true
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
'arrow-body-style': ['error', 'as-needed'],
|
|
101
|
+
'consistent-return': 'error',
|
|
102
|
+
eqeqeq: 'error',
|
|
103
|
+
'func-style': [
|
|
104
|
+
'error',
|
|
105
|
+
'expression',
|
|
106
|
+
{ allowArrowFunctions: true }
|
|
107
|
+
],
|
|
108
|
+
'import/no-cycle': 'error',
|
|
109
|
+
'import/no-default-export': 'error',
|
|
110
|
+
'import/no-relative-packages': 'error',
|
|
111
|
+
'import/no-unused-modules': ['error', { missingExports: true }],
|
|
112
|
+
'import/order': ['error', { alphabetize: { order: 'asc' } }],
|
|
113
|
+
'no-await-in-loop': 'error',
|
|
114
|
+
'no-console': ['error', { allow: ['warn', 'error'] }],
|
|
115
|
+
'no-debugger': 'error',
|
|
116
|
+
'no-duplicate-case': 'error',
|
|
117
|
+
'no-duplicate-imports': 'error',
|
|
118
|
+
'no-else-return': 'error',
|
|
119
|
+
'no-empty-function': 'error',
|
|
120
|
+
'no-empty-pattern': 'error',
|
|
121
|
+
'no-empty-static-block': 'error',
|
|
122
|
+
'no-fallthrough': 'error',
|
|
123
|
+
'no-floating-decimal': 'error',
|
|
124
|
+
'no-global-assign': 'error',
|
|
125
|
+
'no-implicit-coercion': 'error',
|
|
126
|
+
'no-implicit-globals': 'error',
|
|
127
|
+
'no-loop-func': 'error',
|
|
128
|
+
'no-magic-numbers': [
|
|
129
|
+
'warn',
|
|
130
|
+
{ detectObjects: false, enforceConst: true, ignore: [0, 1] }
|
|
131
|
+
],
|
|
132
|
+
'no-misleading-character-class': 'error',
|
|
133
|
+
'no-nested-ternary': 'error',
|
|
134
|
+
'no-new-native-nonconstructor': 'error',
|
|
135
|
+
'no-new-wrappers': 'error',
|
|
136
|
+
'no-param-reassign': 'error',
|
|
137
|
+
'no-restricted-imports': [
|
|
138
|
+
'error',
|
|
139
|
+
{
|
|
140
|
+
paths: [
|
|
141
|
+
{
|
|
142
|
+
importNames: ['default'],
|
|
143
|
+
message:
|
|
144
|
+
'Import only named React exports for tree-shaking.',
|
|
145
|
+
name: 'react'
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
importNames: ['default'],
|
|
149
|
+
message: 'Import only the required Bun exports.',
|
|
150
|
+
name: 'bun'
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
],
|
|
155
|
+
'no-return-await': 'error',
|
|
156
|
+
'no-shadow': 'error',
|
|
157
|
+
'no-undef': 'error',
|
|
158
|
+
'no-unneeded-ternary': 'error',
|
|
159
|
+
'no-unreachable': 'error',
|
|
160
|
+
'no-useless-assignment': 'error',
|
|
161
|
+
'no-useless-concat': 'error',
|
|
162
|
+
'no-useless-return': 'error',
|
|
163
|
+
'no-var': 'error',
|
|
164
|
+
'prefer-arrow-callback': 'error',
|
|
165
|
+
'prefer-const': 'error',
|
|
166
|
+
'prefer-destructuring': [
|
|
167
|
+
'error',
|
|
168
|
+
{ array: true, object: true },
|
|
169
|
+
{ enforceForRenamedProperties: false }
|
|
170
|
+
],
|
|
171
|
+
'prefer-template': 'error',
|
|
172
|
+
'promise/always-return': 'warn',
|
|
173
|
+
'promise/avoid-new': 'warn',
|
|
174
|
+
'promise/catch-or-return': 'error',
|
|
175
|
+
'promise/no-callback-in-promise': 'warn',
|
|
176
|
+
'promise/no-nesting': 'warn',
|
|
177
|
+
'promise/no-promise-in-callback': 'warn',
|
|
178
|
+
'promise/no-return-wrap': 'error',
|
|
179
|
+
'promise/param-names': 'error'
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
files: ['example/**/*.{js,jsx,ts,tsx}'],
|
|
184
|
+
plugins: {
|
|
185
|
+
'jsx-a11y': jsxA11yPlugin,
|
|
186
|
+
react: reactPlugin,
|
|
187
|
+
'react-compiler': reactCompilerPlugin,
|
|
188
|
+
'react-hooks': reactHooksPlugin
|
|
189
|
+
},
|
|
190
|
+
rules: {
|
|
191
|
+
'jsx-a11y/prefer-tag-over-role': 'error',
|
|
192
|
+
'react-compiler/react-compiler': 'error',
|
|
193
|
+
'react-hooks/exhaustive-deps': 'warn',
|
|
194
|
+
'react-hooks/rules-of-hooks': 'error',
|
|
195
|
+
'react/checked-requires-onchange-or-readonly': 'error',
|
|
196
|
+
'react/destructuring-assignment': ['error', 'always'],
|
|
197
|
+
'react/jsx-filename-extension': ['error', { extensions: ['.tsx'] }],
|
|
198
|
+
'react/jsx-no-leaked-render': 'error',
|
|
199
|
+
'react/jsx-no-target-blank': 'error',
|
|
200
|
+
'react/jsx-no-useless-fragment': 'error',
|
|
201
|
+
'react/jsx-pascal-case': ['error', { allowAllCaps: true }],
|
|
202
|
+
'react/no-multi-comp': 'error',
|
|
203
|
+
'react/no-unknown-property': 'off',
|
|
204
|
+
'react/react-in-jsx-scope': 'off',
|
|
205
|
+
'react/self-closing-comp': 'error'
|
|
206
|
+
},
|
|
207
|
+
settings: {
|
|
208
|
+
react: { version: 'detect' }
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
files: [
|
|
213
|
+
'example/server.ts',
|
|
214
|
+
'example/indexes/*.tsx',
|
|
215
|
+
'example/db/migrate.ts'
|
|
216
|
+
],
|
|
217
|
+
rules: {
|
|
218
|
+
'import/no-unused-modules': 'off'
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
files: ['example/db/migrate.ts','example/server.ts'],
|
|
223
|
+
rules: {
|
|
224
|
+
'no-console': 'off'
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
files: ['eslint.config.mjs'],
|
|
229
|
+
rules: {
|
|
230
|
+
'no-magic-numbers': 'off'
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
files: ['eslint.config.mjs'],
|
|
235
|
+
rules: {
|
|
236
|
+
'import/no-default-export': 'off'
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
files: ['example/db/schema.ts'],
|
|
241
|
+
rules: {
|
|
242
|
+
'absolute/explicit-object-types': 'off'
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
];
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.5.0",
|
|
3
3
|
"name": "@absolutejs/auth",
|
|
4
4
|
"description": "An authorization library for absolutejs",
|
|
5
5
|
"repository": {
|
|
@@ -10,13 +10,15 @@
|
|
|
10
10
|
"license": "CC BY-NC 4.0",
|
|
11
11
|
"author": "Alex Kahn",
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build": "rm -rf dist && bun build src/index.ts --outdir dist --
|
|
13
|
+
"build": "rm -rf dist && bun build src/index.ts --outdir dist --target=bun --external elysia && tsc --emitDeclarationOnly --project tsconfig.json",
|
|
14
14
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
15
15
|
"format": "prettier --write \"./**/*.{js,jsx,ts,tsx,css,json}\"",
|
|
16
16
|
"dev": "bun run --watch example/server.ts",
|
|
17
17
|
"db:generate": "drizzle-kit generate --schema ./example/db/schema.ts --dialect postgresql",
|
|
18
18
|
"db:migrate": "bun run ./example/db/migrate.ts",
|
|
19
19
|
"db:studio": "drizzle-kit studio",
|
|
20
|
+
"lint": "eslint ./src ./example ./eslint.config.mjs",
|
|
21
|
+
"typecheck": "bun run tsc --noEmit",
|
|
20
22
|
"release": "bun run format && bun run build && bun publish"
|
|
21
23
|
},
|
|
22
24
|
"keywords": [
|
|
@@ -28,23 +30,36 @@
|
|
|
28
30
|
],
|
|
29
31
|
"types": "dist/src/index.d.ts",
|
|
30
32
|
"peerDependencies": {
|
|
31
|
-
"arctic": ">= 3.6.0",
|
|
32
33
|
"elysia": ">= 1.2.0"
|
|
33
34
|
},
|
|
34
35
|
"devDependencies": {
|
|
35
|
-
"
|
|
36
|
+
"@absolutejs/absolute": "0.4.0",
|
|
36
37
|
"@elysiajs/static": "1.2.0",
|
|
37
38
|
"@neondatabase/serverless": "1.0.0",
|
|
39
|
+
"@react-spring/web": "10.0.0-beta.0",
|
|
40
|
+
"@stylistic/eslint-plugin-ts": "4.2.0",
|
|
38
41
|
"@types/bun": "1.2.9",
|
|
39
42
|
"@types/react": "19.1.1",
|
|
40
43
|
"@types/react-dom": "19.1.2",
|
|
44
|
+
"citra": "0.15.1",
|
|
41
45
|
"drizzle-kit": "0.30.6",
|
|
42
46
|
"drizzle-orm": "0.41.0",
|
|
47
|
+
"elysia": "1.2.25",
|
|
48
|
+
"eslint": "9.26.0",
|
|
49
|
+
"eslint-plugin-absolute": "0.0.3",
|
|
50
|
+
"eslint-plugin-import": "2.31.0",
|
|
51
|
+
"eslint-plugin-jsx-a11y": "6.10.2",
|
|
52
|
+
"eslint-plugin-promise": "7.2.1",
|
|
53
|
+
"eslint-plugin-react": "7.37.5",
|
|
54
|
+
"eslint-plugin-react-compiler": "19.1.0-rc.1",
|
|
55
|
+
"eslint-plugin-react-hooks": "5.2.0",
|
|
56
|
+
"eslint-plugin-security": "3.0.1",
|
|
43
57
|
"prettier": "3.5.3",
|
|
44
58
|
"react": "19.1.0",
|
|
45
59
|
"react-dom": "19.1.0",
|
|
46
|
-
"
|
|
47
|
-
"typescript": "5.8.3"
|
|
60
|
+
"react-icons": "5.5.0",
|
|
61
|
+
"typescript": "5.8.3",
|
|
62
|
+
"typescript-eslint": "8.32.0"
|
|
48
63
|
},
|
|
49
64
|
"module": "dist/index.js"
|
|
50
65
|
}
|
package/dist/src/providers.d.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { AmazonCognito, AniList, Apple, Atlassian, Auth0, Authentik, Bitbucket, Box, Coinbase, Discord, Dribbble, Dropbox, Facebook, Figma, Intuit, GitHub, GitLab, Google, Kakao, KeyCloak, Lichess, Line, Linear, LinkedIn, MicrosoftEntraId, MyAnimeList, Notion, Okta, Osu, Patreon, Reddit, Roblox, Salesforce, Shikimori, Slack, Spotify, Strava, Tiltify, Tumblr, Twitch, Twitter, VK, WorkOS, Yahoo, Yandex, Zoom, FortyTwo } from 'arctic';
|
|
2
|
-
export declare const providers: {
|
|
3
|
-
AmazonCognito: typeof AmazonCognito;
|
|
4
|
-
AniList: typeof AniList;
|
|
5
|
-
Apple: typeof Apple;
|
|
6
|
-
Atlassian: typeof Atlassian;
|
|
7
|
-
Auth0: typeof Auth0;
|
|
8
|
-
Authentik: typeof Authentik;
|
|
9
|
-
Bitbucket: typeof Bitbucket;
|
|
10
|
-
Box: typeof Box;
|
|
11
|
-
Coinbase: typeof Coinbase;
|
|
12
|
-
Discord: typeof Discord;
|
|
13
|
-
Dribbble: typeof Dribbble;
|
|
14
|
-
Dropbox: typeof Dropbox;
|
|
15
|
-
Facebook: typeof Facebook;
|
|
16
|
-
Figma: typeof Figma;
|
|
17
|
-
FortyTwo: typeof FortyTwo;
|
|
18
|
-
GitHub: typeof GitHub;
|
|
19
|
-
GitLab: typeof GitLab;
|
|
20
|
-
Google: typeof Google;
|
|
21
|
-
Intuit: typeof Intuit;
|
|
22
|
-
Kakao: typeof Kakao;
|
|
23
|
-
KeyCloak: typeof KeyCloak;
|
|
24
|
-
Lichess: typeof Lichess;
|
|
25
|
-
Line: typeof Line;
|
|
26
|
-
Linear: typeof Linear;
|
|
27
|
-
LinkedIn: typeof LinkedIn;
|
|
28
|
-
MicrosoftEntraId: typeof MicrosoftEntraId;
|
|
29
|
-
MyAnimeList: typeof MyAnimeList;
|
|
30
|
-
Notion: typeof Notion;
|
|
31
|
-
Okta: typeof Okta;
|
|
32
|
-
Osu: typeof Osu;
|
|
33
|
-
Patreon: typeof Patreon;
|
|
34
|
-
Reddit: typeof Reddit;
|
|
35
|
-
Roblox: typeof Roblox;
|
|
36
|
-
Salesforce: typeof Salesforce;
|
|
37
|
-
Shikimori: typeof Shikimori;
|
|
38
|
-
Slack: typeof Slack;
|
|
39
|
-
Spotify: typeof Spotify;
|
|
40
|
-
Strava: typeof Strava;
|
|
41
|
-
Tiltify: typeof Tiltify;
|
|
42
|
-
Tumblr: typeof Tumblr;
|
|
43
|
-
Twitch: typeof Twitch;
|
|
44
|
-
Twitter: typeof Twitter;
|
|
45
|
-
VK: typeof VK;
|
|
46
|
-
WorkOS: typeof WorkOS;
|
|
47
|
-
Yahoo: typeof Yahoo;
|
|
48
|
-
Yandex: typeof Yandex;
|
|
49
|
-
Zoom: typeof Zoom;
|
|
50
|
-
};
|
|
51
|
-
export declare const normalizedProviderKeys: Record<string, string>;
|
package/src/authorize.ts
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { generateState, generateCodeVerifier } from 'arctic';
|
|
2
|
-
import { Elysia } from 'elysia';
|
|
3
|
-
import { isValidProviderKey } from './typeGuards';
|
|
4
|
-
import { ClientProviders } from './types';
|
|
5
|
-
import { COOKIE_DURATION } from './constants';
|
|
6
|
-
|
|
7
|
-
type AuthorizeProps = {
|
|
8
|
-
clientProviders: ClientProviders;
|
|
9
|
-
authorizeRoute?: string;
|
|
10
|
-
onAuthorize?: () => void;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export const authorize = ({
|
|
14
|
-
clientProviders,
|
|
15
|
-
authorizeRoute = 'authorize',
|
|
16
|
-
onAuthorize
|
|
17
|
-
}: AuthorizeProps) =>
|
|
18
|
-
new Elysia().get(
|
|
19
|
-
`/${authorizeRoute}/:provider`,
|
|
20
|
-
({
|
|
21
|
-
error,
|
|
22
|
-
redirect,
|
|
23
|
-
cookie: { state, code_verifier, auth_provider, redirect_url },
|
|
24
|
-
params: { provider },
|
|
25
|
-
headers
|
|
26
|
-
}) => {
|
|
27
|
-
if (provider === undefined)
|
|
28
|
-
return error('Bad Request', 'Provider is required');
|
|
29
|
-
|
|
30
|
-
if (!isValidProviderKey(provider)) {
|
|
31
|
-
return error('Bad Request', 'Invalid provider');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
const normalizedProvider = provider.toLowerCase();
|
|
36
|
-
const { providerInstance, scopes, searchParams } =
|
|
37
|
-
clientProviders[normalizedProvider];
|
|
38
|
-
|
|
39
|
-
const redirectUrl = headers['referer'] ?? '/';
|
|
40
|
-
|
|
41
|
-
redirect_url.set({
|
|
42
|
-
httpOnly: true,
|
|
43
|
-
maxAge: COOKIE_DURATION,
|
|
44
|
-
path: '/',
|
|
45
|
-
sameSite: 'lax',
|
|
46
|
-
secure: true,
|
|
47
|
-
value: redirectUrl
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
auth_provider.set({
|
|
51
|
-
httpOnly: true,
|
|
52
|
-
maxAge: COOKIE_DURATION,
|
|
53
|
-
path: '/',
|
|
54
|
-
sameSite: 'lax',
|
|
55
|
-
secure: true,
|
|
56
|
-
value: provider
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const currentState = generateState();
|
|
60
|
-
|
|
61
|
-
state.set({
|
|
62
|
-
httpOnly: true,
|
|
63
|
-
maxAge: COOKIE_DURATION,
|
|
64
|
-
path: '/',
|
|
65
|
-
sameSite: 'lax',
|
|
66
|
-
secure: true,
|
|
67
|
-
value: currentState
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
const usesCodeVerifier = providerInstance.createAuthorizationURL
|
|
71
|
-
.toString()
|
|
72
|
-
.includes('codeVerifier');
|
|
73
|
-
const verifier = usesCodeVerifier
|
|
74
|
-
? generateCodeVerifier()
|
|
75
|
-
: undefined;
|
|
76
|
-
void (
|
|
77
|
-
usesCodeVerifier &&
|
|
78
|
-
code_verifier.set({
|
|
79
|
-
httpOnly: true,
|
|
80
|
-
maxAge: COOKIE_DURATION,
|
|
81
|
-
path: '/',
|
|
82
|
-
sameSite: 'lax',
|
|
83
|
-
secure: true,
|
|
84
|
-
value: verifier ?? ''
|
|
85
|
-
})
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
const authorizationURL = usesCodeVerifier
|
|
89
|
-
? providerInstance.createAuthorizationURL(
|
|
90
|
-
currentState,
|
|
91
|
-
// @ts-expect-error - This is a dynamic check
|
|
92
|
-
verifier,
|
|
93
|
-
scopes
|
|
94
|
-
)
|
|
95
|
-
: // @ts-expect-error - This is a dynamic check
|
|
96
|
-
providerInstance.createAuthorizationURL(
|
|
97
|
-
currentState,
|
|
98
|
-
scopes
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
searchParams.forEach(([key, value]) => {
|
|
102
|
-
authorizationURL.searchParams.set(key, value);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
onAuthorize?.();
|
|
106
|
-
|
|
107
|
-
return redirect(authorizationURL.toString());
|
|
108
|
-
} catch (err) {
|
|
109
|
-
if (err instanceof Error) {
|
|
110
|
-
return error(
|
|
111
|
-
'Internal Server Error',
|
|
112
|
-
`${err.message} - ${err.stack ?? ''}`
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return error('Internal Server Error', `Unknown error: ${err}`);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
);
|
package/src/callback.ts
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { decodeIdToken } from 'arctic';
|
|
2
|
-
import { Elysia } from 'elysia';
|
|
3
|
-
import { sessionStore } from './sessionStore';
|
|
4
|
-
import { isNonEmptyString, isValidProviderKey } from './typeGuards';
|
|
5
|
-
import { ClientProviders, OnCallback } from './types';
|
|
6
|
-
|
|
7
|
-
type CallbackProps<UserType> = {
|
|
8
|
-
clientProviders: ClientProviders;
|
|
9
|
-
callbackRoute?: string;
|
|
10
|
-
onCallback?: OnCallback<UserType>;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export const callback = <UserType>({
|
|
14
|
-
clientProviders,
|
|
15
|
-
callbackRoute = 'authorize/callback',
|
|
16
|
-
onCallback
|
|
17
|
-
}: CallbackProps<UserType>) =>
|
|
18
|
-
new Elysia()
|
|
19
|
-
.use(sessionStore<UserType>())
|
|
20
|
-
.get(
|
|
21
|
-
`/${callbackRoute}`,
|
|
22
|
-
async ({
|
|
23
|
-
error,
|
|
24
|
-
redirect,
|
|
25
|
-
store: { session },
|
|
26
|
-
cookie: {
|
|
27
|
-
state: stored_state,
|
|
28
|
-
code_verifier,
|
|
29
|
-
redirect_url,
|
|
30
|
-
user_session_id,
|
|
31
|
-
auth_provider
|
|
32
|
-
},
|
|
33
|
-
query: { code, state: callback_state }
|
|
34
|
-
}) => {
|
|
35
|
-
if (
|
|
36
|
-
!isNonEmptyString(code) ||
|
|
37
|
-
stored_state.value === undefined
|
|
38
|
-
) {
|
|
39
|
-
return error('Bad Request', 'Invalid callback request');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (callback_state !== stored_state.value) {
|
|
43
|
-
return error('Bad Request', 'Invalid state mismatch');
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (auth_provider.value === undefined) {
|
|
47
|
-
return error('Unauthorized', 'No auth provider found');
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (!isValidProviderKey(auth_provider.value)) {
|
|
51
|
-
return error('Unauthorized', 'Invalid provider');
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const normalizedProvider = auth_provider.value.toLowerCase();
|
|
55
|
-
const { providerInstance } =
|
|
56
|
-
clientProviders[normalizedProvider];
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
// Clear the stored state so the next request doesn't use it
|
|
60
|
-
stored_state.remove();
|
|
61
|
-
|
|
62
|
-
const hasCodeVerifier =
|
|
63
|
-
providerInstance.validateAuthorizationCode
|
|
64
|
-
.toString()
|
|
65
|
-
.includes('codeVerifier');
|
|
66
|
-
const verifier = code_verifier.value;
|
|
67
|
-
if (hasCodeVerifier && verifier === undefined)
|
|
68
|
-
return error(
|
|
69
|
-
'Bad Request',
|
|
70
|
-
'Code verifier not found and is required'
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
const safeVerifier = verifier ?? '';
|
|
74
|
-
const tokens = await (hasCodeVerifier
|
|
75
|
-
? providerInstance.validateAuthorizationCode(
|
|
76
|
-
code,
|
|
77
|
-
safeVerifier
|
|
78
|
-
)
|
|
79
|
-
: // @ts-expect-error - This is a dynamic check
|
|
80
|
-
providerInstance.validateAuthorizationCode(code));
|
|
81
|
-
if (hasCodeVerifier) code_verifier.remove();
|
|
82
|
-
|
|
83
|
-
const decodedIdToken = Object.fromEntries(
|
|
84
|
-
Object.entries(decodeIdToken(tokens.idToken())).map(
|
|
85
|
-
([key, value]) => [
|
|
86
|
-
key,
|
|
87
|
-
typeof value === 'string' ? value : undefined
|
|
88
|
-
]
|
|
89
|
-
)
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
const authProvider = auth_provider.value;
|
|
93
|
-
|
|
94
|
-
await onCallback?.({
|
|
95
|
-
authProvider,
|
|
96
|
-
decodedIdToken,
|
|
97
|
-
session,
|
|
98
|
-
user_session_id
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
const redirectUrl = redirect_url.value ?? '/';
|
|
102
|
-
|
|
103
|
-
return redirect(redirectUrl);
|
|
104
|
-
} catch (err) {
|
|
105
|
-
if (err instanceof Error)
|
|
106
|
-
return error(
|
|
107
|
-
'Internal Server Error',
|
|
108
|
-
`${err.message} - ${err.stack ?? ''}`
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
return error(
|
|
112
|
-
'Internal Server Error',
|
|
113
|
-
`Failed to validate authorization code: Unknown error: ${err}`
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
);
|
package/src/constants.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export const SECONDS_IN_A_MINUTE = 60;
|
|
2
|
-
export const MILLISECONDS_IN_A_SECOND = 1000;
|
|
3
|
-
export const MILLISECONDS_IN_A_MINUTE =
|
|
4
|
-
MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE;
|
|
5
|
-
export const MINUTES_IN_AN_HOUR = 60;
|
|
6
|
-
export const HOURS_IN_A_DAY = 24;
|
|
7
|
-
export const MILLISECONDS_IN_A_DAY =
|
|
8
|
-
MILLISECONDS_IN_A_SECOND *
|
|
9
|
-
SECONDS_IN_A_MINUTE *
|
|
10
|
-
MINUTES_IN_AN_HOUR *
|
|
11
|
-
HOURS_IN_A_DAY;
|
|
12
|
-
export const COOKIE_MINUTES = 30; // TODO : See if i can remove
|
|
13
|
-
export const COOKIE_DURATION = SECONDS_IN_A_MINUTE * COOKIE_MINUTES;
|
package/src/index.ts
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { OAuth2RequestError, ArcticFetchError } from 'arctic';
|
|
2
|
-
import { Elysia } from 'elysia';
|
|
3
|
-
import { authorize } from './authorize';
|
|
4
|
-
import { callback } from './callback';
|
|
5
|
-
import { logout } from './logout';
|
|
6
|
-
import { protectRoute } from './protectRoute';
|
|
7
|
-
import { normalizedProviderKeys, providers } from './providers';
|
|
8
|
-
import { refresh } from './refresh';
|
|
9
|
-
import { revoke } from './revoke';
|
|
10
|
-
import { status } from './status';
|
|
11
|
-
import { isValidProviderKey } from './typeGuards';
|
|
12
|
-
import { AbsoluteAuthProps, ClientProviders } from './types';
|
|
13
|
-
|
|
14
|
-
export const absoluteAuth = <UserType>({
|
|
15
|
-
config,
|
|
16
|
-
authorizeRoute,
|
|
17
|
-
callbackRoute,
|
|
18
|
-
logoutRoute,
|
|
19
|
-
statusRoute,
|
|
20
|
-
refreshRoute,
|
|
21
|
-
revokeRoute,
|
|
22
|
-
onAuthorize,
|
|
23
|
-
onCallback,
|
|
24
|
-
onStatus,
|
|
25
|
-
onRefresh,
|
|
26
|
-
onLogout,
|
|
27
|
-
onRevoke
|
|
28
|
-
}: AbsoluteAuthProps<UserType>) => {
|
|
29
|
-
const clientProviders = Object.keys(config).reduce<ClientProviders>(
|
|
30
|
-
(acc, key) => {
|
|
31
|
-
if (!Object.prototype.hasOwnProperty.call(config, key)) return acc;
|
|
32
|
-
|
|
33
|
-
if (!isValidProviderKey(key)) {
|
|
34
|
-
console.error(`Provider ${key} is not supported`);
|
|
35
|
-
|
|
36
|
-
return acc;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const options = config[key];
|
|
40
|
-
if (!options) return acc;
|
|
41
|
-
|
|
42
|
-
const normalizedProvider = key.toLowerCase();
|
|
43
|
-
const originalProviderKey =
|
|
44
|
-
normalizedProviderKeys[normalizedProvider];
|
|
45
|
-
|
|
46
|
-
if (!isValidProviderKey(originalProviderKey)) {
|
|
47
|
-
console.error(`Provider ${key} is not supported`);
|
|
48
|
-
|
|
49
|
-
return acc;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const Provider = providers[originalProviderKey];
|
|
53
|
-
const { credentials, scopes = [], searchParams = [] } = options;
|
|
54
|
-
|
|
55
|
-
// @ts-expect-error: dynamic constructor parameters
|
|
56
|
-
const providerInstance = new Provider(...credentials);
|
|
57
|
-
|
|
58
|
-
acc[normalizedProvider] = {
|
|
59
|
-
providerInstance,
|
|
60
|
-
scopes,
|
|
61
|
-
searchParams
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
return acc;
|
|
65
|
-
},
|
|
66
|
-
{}
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
return new Elysia()
|
|
70
|
-
.error('OAUTH2_REQUEST_ERROR', OAuth2RequestError)
|
|
71
|
-
.error('ARCTIC_FETCH_ERROR', ArcticFetchError)
|
|
72
|
-
.use(logout({ logoutRoute, onLogout }))
|
|
73
|
-
.use(revoke({ clientProviders, onRevoke, revokeRoute }))
|
|
74
|
-
.use(status<UserType>({ clientProviders, onStatus, statusRoute }))
|
|
75
|
-
.use(refresh({ clientProviders, onRefresh, refreshRoute }))
|
|
76
|
-
.use(authorize({ authorizeRoute, clientProviders, onAuthorize }))
|
|
77
|
-
.use(
|
|
78
|
-
callback<UserType>({
|
|
79
|
-
callbackRoute,
|
|
80
|
-
clientProviders,
|
|
81
|
-
onCallback
|
|
82
|
-
})
|
|
83
|
-
)
|
|
84
|
-
.use(protectRoute())
|
|
85
|
-
.as('plugin');
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
export * from './utils';
|