@revojs/auth 0.1.58
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/index.d.ts +123 -0
- package/dist/index.js +190 -0
- package/dist/module/index.d.ts +10 -0
- package/dist/module/index.js +62 -0
- package/dist/routes/auth/provider/apple/get.d.ts +2 -0
- package/dist/routes/auth/provider/apple/get.js +22 -0
- package/dist/routes/auth/provider/github/get.d.ts +2 -0
- package/dist/routes/auth/provider/github/get.js +37 -0
- package/dist/routes/auth/provider/google/get.d.ts +2 -0
- package/dist/routes/auth/provider/google/get.js +19 -0
- package/dist/routes/auth/provider/microsoft/get.d.ts +2 -0
- package/dist/routes/auth/provider/microsoft/get.js +19 -0
- package/dist/routes/auth/sessions/delete.d.ts +4 -0
- package/dist/routes/auth/sessions/delete.js +12 -0
- package/dist/routes/auth/sessions/get.d.ts +4 -0
- package/dist/routes/auth/sessions/get.js +10 -0
- package/dist/routes/auth/sessions/post.d.ts +4 -0
- package/dist/routes/auth/sessions/post.js +19 -0
- package/dist/types/index.d.ts +23 -0
- package/package.json +38 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { type Route } from "@revojs/server";
|
|
2
|
+
import { type Scope } from "revojs";
|
|
3
|
+
import type { Awaitable } from "revojs/shared";
|
|
4
|
+
import { type InferInput } from "valibot";
|
|
5
|
+
export type Principal = InferInput<typeof principalSchema>;
|
|
6
|
+
export type PasswordMethod = InferInput<typeof passwordMethodSchema>;
|
|
7
|
+
export type PasskeyMethod = InferInput<typeof passkeyMethodSchema>;
|
|
8
|
+
export type ProviderMethod = InferInput<typeof providerMethodSchema>;
|
|
9
|
+
export type Method = InferInput<typeof methodSchema>;
|
|
10
|
+
export type Providers = "apple" | "github" | "google" | "microsoft";
|
|
11
|
+
export interface Token {
|
|
12
|
+
access_token: string;
|
|
13
|
+
token_type: string;
|
|
14
|
+
expires_in: number;
|
|
15
|
+
refresh_token?: string;
|
|
16
|
+
id_token?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ProviderEndpoint {
|
|
19
|
+
url: string;
|
|
20
|
+
parameters?: Record<string, string>;
|
|
21
|
+
headers?: Record<string, string>;
|
|
22
|
+
}
|
|
23
|
+
export interface ProviderUserInfo {
|
|
24
|
+
sub?: string | number | null;
|
|
25
|
+
id?: string | number | null;
|
|
26
|
+
email?: string | null;
|
|
27
|
+
email_verified?: boolean | null;
|
|
28
|
+
given_name?: string | null;
|
|
29
|
+
first_name?: string | null;
|
|
30
|
+
name?: string | null;
|
|
31
|
+
family_name?: string | null;
|
|
32
|
+
last_name?: string | null;
|
|
33
|
+
picture?: string | null;
|
|
34
|
+
avatar_url?: string | null;
|
|
35
|
+
preferred_username?: string | null;
|
|
36
|
+
login?: string | null;
|
|
37
|
+
username?: string | null;
|
|
38
|
+
}
|
|
39
|
+
export interface AuthProviderOptions {
|
|
40
|
+
issuer: string;
|
|
41
|
+
scope: string;
|
|
42
|
+
clientKey: string;
|
|
43
|
+
clientSecret: string;
|
|
44
|
+
authorize: ProviderEndpoint;
|
|
45
|
+
token: ProviderEndpoint;
|
|
46
|
+
userInfo: ProviderEndpoint;
|
|
47
|
+
toPrincipal?: (principal: ProviderUserInfo) => Principal;
|
|
48
|
+
}
|
|
49
|
+
export interface AuthProvider {
|
|
50
|
+
setup: (scope: Scope) => AuthProviderOptions;
|
|
51
|
+
}
|
|
52
|
+
export declare function useAuth(scope: Scope): {
|
|
53
|
+
signInWithCredentials(credential: PasswordMethod | PasskeyMethod): Promise<unknown>;
|
|
54
|
+
signInWithProvider(provider: Providers | (string & {}), redirectUrl: string): Promise<void>;
|
|
55
|
+
signOut(): Promise<unknown>;
|
|
56
|
+
};
|
|
57
|
+
export declare function requireSession<T>(scope: Scope, redirectUrl: string): Promise<T>;
|
|
58
|
+
export declare function getCryptoKey(scope: Scope): Promise<CryptoKey>;
|
|
59
|
+
export declare function getSession<T>(scope: Scope): Promise<T | undefined>;
|
|
60
|
+
export declare function setSession<T>(scope: Scope, session: T): Promise<void>;
|
|
61
|
+
export declare function clearSession(scope: Scope): void;
|
|
62
|
+
export declare function defineAuthProvider(provider: AuthProvider): Route;
|
|
63
|
+
export declare const GET_PRINCIPAL_HOOK: import("revojs").Descriptor<(method: Method) => Awaitable<Principal | undefined>>;
|
|
64
|
+
export declare const CREATE_PRINCIPAL_HOOK: import("revojs").Descriptor<(method: Method) => Awaitable<Principal | undefined>>;
|
|
65
|
+
export declare const CREATE_SESSION_HOOK: import("revojs").Descriptor<(principal: Principal) => Awaitable<unknown>>;
|
|
66
|
+
export declare const DELETE_SESSION_HOOK: import("revojs").Descriptor<(session: any) => Awaitable<unknown>>;
|
|
67
|
+
export declare const registerAuthHooks: (scope: Scope, hooks: import("revojs").Hooks<{
|
|
68
|
+
getPrincipal: import("revojs").Descriptor<(method: Method) => Awaitable<Principal | undefined>>;
|
|
69
|
+
createPrincipal: import("revojs").Descriptor<(method: Method) => Awaitable<Principal | undefined>>;
|
|
70
|
+
createSession: import("revojs").Descriptor<(principal: Principal) => Awaitable<unknown>>;
|
|
71
|
+
deleteSession: import("revojs").Descriptor<(session: any) => Awaitable<unknown>>;
|
|
72
|
+
}>) => void;
|
|
73
|
+
export declare const principalSchema: import("valibot").ObjectSchema<{
|
|
74
|
+
readonly sub: import("valibot").StringSchema<undefined>;
|
|
75
|
+
readonly email: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
76
|
+
readonly email_verified: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
77
|
+
readonly given_name: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
78
|
+
readonly family_name: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
79
|
+
readonly picture: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
80
|
+
readonly preferred_username: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
81
|
+
}, undefined>;
|
|
82
|
+
export declare const passwordMethodSchema: import("valibot").ObjectSchema<{
|
|
83
|
+
readonly type: import("valibot").LiteralSchema<"PASSWORD", undefined>;
|
|
84
|
+
readonly email: import("valibot").StringSchema<undefined>;
|
|
85
|
+
readonly password: import("valibot").StringSchema<undefined>;
|
|
86
|
+
readonly register: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, true>;
|
|
87
|
+
}, undefined>;
|
|
88
|
+
export declare const passkeyMethodSchema: import("valibot").ObjectSchema<{
|
|
89
|
+
readonly type: import("valibot").LiteralSchema<"PASSKEY", undefined>;
|
|
90
|
+
}, undefined>;
|
|
91
|
+
export declare const providerMethodSchema: import("valibot").ObjectSchema<{
|
|
92
|
+
readonly type: import("valibot").LiteralSchema<"PROVIDER", undefined>;
|
|
93
|
+
readonly issuer: import("valibot").StringSchema<undefined>;
|
|
94
|
+
readonly principal: import("valibot").ObjectSchema<{
|
|
95
|
+
readonly sub: import("valibot").StringSchema<undefined>;
|
|
96
|
+
readonly email: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
97
|
+
readonly email_verified: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
98
|
+
readonly given_name: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
99
|
+
readonly family_name: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
100
|
+
readonly picture: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
101
|
+
readonly preferred_username: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
102
|
+
}, undefined>;
|
|
103
|
+
}, undefined>;
|
|
104
|
+
export declare const methodSchema: import("valibot").UnionSchema<[import("valibot").ObjectSchema<{
|
|
105
|
+
readonly type: import("valibot").LiteralSchema<"PASSWORD", undefined>;
|
|
106
|
+
readonly email: import("valibot").StringSchema<undefined>;
|
|
107
|
+
readonly password: import("valibot").StringSchema<undefined>;
|
|
108
|
+
readonly register: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, true>;
|
|
109
|
+
}, undefined>, import("valibot").ObjectSchema<{
|
|
110
|
+
readonly type: import("valibot").LiteralSchema<"PASSKEY", undefined>;
|
|
111
|
+
}, undefined>, import("valibot").ObjectSchema<{
|
|
112
|
+
readonly type: import("valibot").LiteralSchema<"PROVIDER", undefined>;
|
|
113
|
+
readonly issuer: import("valibot").StringSchema<undefined>;
|
|
114
|
+
readonly principal: import("valibot").ObjectSchema<{
|
|
115
|
+
readonly sub: import("valibot").StringSchema<undefined>;
|
|
116
|
+
readonly email: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
117
|
+
readonly email_verified: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
118
|
+
readonly given_name: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
119
|
+
readonly family_name: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
120
|
+
readonly picture: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
121
|
+
readonly preferred_username: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
122
|
+
}, undefined>;
|
|
123
|
+
}, undefined>], undefined>;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import options from "#config/auth";
|
|
2
|
+
import { isClient, isServer } from "#variables";
|
|
3
|
+
import { deleteCookie, fetch, sendRedirect, setCookie, useCookies, useHeaders, useQuery, useUrl, withQuery } from "@revojs/server";
|
|
4
|
+
import { createRegisterHooks, defineHook, dispatchHookSingle, useVariables } from "revojs";
|
|
5
|
+
import { boolean, literal, nullish, number, object, optional, parse, pipe, string, transform, union } from "valibot";
|
|
6
|
+
//#region src/index.ts
|
|
7
|
+
function useAuth(scope) {
|
|
8
|
+
return {
|
|
9
|
+
async signInWithCredentials(credential) {
|
|
10
|
+
return await fetch(scope, `/auth/sessions`, {
|
|
11
|
+
method: "POST",
|
|
12
|
+
headers: { "Content-Type": "application/json" },
|
|
13
|
+
body: JSON.stringify(credential)
|
|
14
|
+
});
|
|
15
|
+
},
|
|
16
|
+
async signInWithProvider(provider, redirectUrl) {
|
|
17
|
+
globalThis.location.href = `/auth/provider/${provider}?redirect=${encodeURIComponent(redirectUrl)}`;
|
|
18
|
+
},
|
|
19
|
+
async signOut() {
|
|
20
|
+
return await fetch(scope, `/auth/sessions`, { method: "DELETE" });
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
async function requireSession(scope, redirectUrl) {
|
|
25
|
+
if (isClient) {
|
|
26
|
+
const { pathname } = useUrl(scope);
|
|
27
|
+
try {
|
|
28
|
+
return await fetch(scope, "/auth/sessions", {
|
|
29
|
+
method: "GET",
|
|
30
|
+
headers: useHeaders(scope)
|
|
31
|
+
});
|
|
32
|
+
} catch {
|
|
33
|
+
if (redirectUrl !== pathname) globalThis.location.href = redirectUrl;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (isServer) {
|
|
37
|
+
const session = await getSession(scope);
|
|
38
|
+
if (session) return session;
|
|
39
|
+
throw sendRedirect(scope, redirectUrl);
|
|
40
|
+
}
|
|
41
|
+
throw new Error("Session is unavailable");
|
|
42
|
+
}
|
|
43
|
+
async function getCryptoKey(scope) {
|
|
44
|
+
const { sessionSecret } = useVariables(scope);
|
|
45
|
+
return crypto.subtle.importKey("raw", encoder.encode(sessionSecret), {
|
|
46
|
+
name: "HMAC",
|
|
47
|
+
hash: "SHA-256"
|
|
48
|
+
}, false, ["sign", "verify"]);
|
|
49
|
+
}
|
|
50
|
+
async function getSession(scope) {
|
|
51
|
+
const session = useCookies(scope)[options.session.name];
|
|
52
|
+
if (session) {
|
|
53
|
+
const index = session.lastIndexOf(".");
|
|
54
|
+
if (index > 0) try {
|
|
55
|
+
const payload = session.slice(0, index);
|
|
56
|
+
if (await crypto.subtle.verify("HMAC", await getCryptoKey(scope), Uint8Array.fromBase64(session.slice(index + 1), BASE64_VERIFY), Uint8Array.fromBase64(payload, BASE64_VERIFY))) return JSON.parse(decoder.decode(Uint8Array.fromBase64(payload, BASE64_VERIFY)));
|
|
57
|
+
} catch {}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function setSession(scope, session) {
|
|
61
|
+
const value = encoder.encode(JSON.stringify(session));
|
|
62
|
+
const cookie = value.toBase64(BASE64_SIGN) + "." + new Uint8Array(await crypto.subtle.sign("HMAC", await getCryptoKey(scope), value)).toBase64(BASE64_SIGN);
|
|
63
|
+
setCookie(scope, options.session.name, cookie, options.session.cookie);
|
|
64
|
+
}
|
|
65
|
+
function clearSession(scope) {
|
|
66
|
+
deleteCookie(scope, options.session.name, options.session.cookie);
|
|
67
|
+
}
|
|
68
|
+
function defineAuthProvider(provider) {
|
|
69
|
+
return { async fetch(scope) {
|
|
70
|
+
const options = provider.setup(scope);
|
|
71
|
+
const { origin } = useUrl(scope);
|
|
72
|
+
const { code, state, redirect } = useQuery(scope);
|
|
73
|
+
const target = state ?? redirect ?? "/";
|
|
74
|
+
const redirectUri = `${origin}/auth/provider/${options.issuer}`;
|
|
75
|
+
const successPath = target.startsWith("/") && !target.startsWith("//") ? target : "/";
|
|
76
|
+
if (code) {
|
|
77
|
+
const token = await fetch(scope, options.token.url, {
|
|
78
|
+
method: "POST",
|
|
79
|
+
headers: {
|
|
80
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
81
|
+
...options.token.headers
|
|
82
|
+
},
|
|
83
|
+
body: new URLSearchParams({
|
|
84
|
+
grant_type: "authorization_code",
|
|
85
|
+
client_id: options.clientKey,
|
|
86
|
+
client_secret: options.clientSecret,
|
|
87
|
+
redirect_uri: redirectUri,
|
|
88
|
+
code,
|
|
89
|
+
...options.token.parameters
|
|
90
|
+
})
|
|
91
|
+
});
|
|
92
|
+
const method = {
|
|
93
|
+
type: "PROVIDER",
|
|
94
|
+
issuer: options.issuer,
|
|
95
|
+
principal: (options.toPrincipal ?? ((user) => parse(userInfoSchema, user)))(await fetch(scope, options.userInfo.url, { headers: {
|
|
96
|
+
Authorization: `Bearer ${token.access_token}`,
|
|
97
|
+
...options.userInfo.headers
|
|
98
|
+
} }))
|
|
99
|
+
};
|
|
100
|
+
const principal = await dispatchHookSingle(scope, GET_PRINCIPAL_HOOK, method) ?? await dispatchHookSingle(scope, CREATE_PRINCIPAL_HOOK, method);
|
|
101
|
+
if (principal) {
|
|
102
|
+
const session = await dispatchHookSingle(scope, CREATE_SESSION_HOOK, principal);
|
|
103
|
+
if (session) {
|
|
104
|
+
await setSession(scope, session);
|
|
105
|
+
return sendRedirect(scope, successPath);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return sendRedirect(scope, withQuery(scope, options.authorize.url, {
|
|
110
|
+
response_type: "code",
|
|
111
|
+
client_id: options.clientKey,
|
|
112
|
+
redirect_uri: redirectUri,
|
|
113
|
+
scope: options.scope,
|
|
114
|
+
state: successPath,
|
|
115
|
+
...options.authorize.parameters
|
|
116
|
+
}));
|
|
117
|
+
} };
|
|
118
|
+
}
|
|
119
|
+
var GET_PRINCIPAL_HOOK = defineHook("GET_PRINCIPAL_HOOK");
|
|
120
|
+
var CREATE_PRINCIPAL_HOOK = defineHook("CREATE_PRINCIPAL_HOOK");
|
|
121
|
+
var CREATE_SESSION_HOOK = defineHook("CREATE_SESSION_HOOK");
|
|
122
|
+
var DELETE_SESSION_HOOK = defineHook("DELETE_SESSION_HOOK");
|
|
123
|
+
var registerAuthHooks = createRegisterHooks({
|
|
124
|
+
getPrincipal: GET_PRINCIPAL_HOOK,
|
|
125
|
+
createPrincipal: CREATE_PRINCIPAL_HOOK,
|
|
126
|
+
createSession: CREATE_SESSION_HOOK,
|
|
127
|
+
deleteSession: DELETE_SESSION_HOOK
|
|
128
|
+
});
|
|
129
|
+
var principalSchema = object({
|
|
130
|
+
sub: string(),
|
|
131
|
+
email: optional(string()),
|
|
132
|
+
email_verified: optional(boolean()),
|
|
133
|
+
given_name: optional(string()),
|
|
134
|
+
family_name: optional(string()),
|
|
135
|
+
picture: optional(string()),
|
|
136
|
+
preferred_username: optional(string())
|
|
137
|
+
});
|
|
138
|
+
var passwordMethodSchema = object({
|
|
139
|
+
type: literal("PASSWORD"),
|
|
140
|
+
email: string(),
|
|
141
|
+
password: string(),
|
|
142
|
+
register: optional(boolean(), true)
|
|
143
|
+
});
|
|
144
|
+
var passkeyMethodSchema = object({ type: literal("PASSKEY") });
|
|
145
|
+
var providerMethodSchema = object({
|
|
146
|
+
type: literal("PROVIDER"),
|
|
147
|
+
issuer: string(),
|
|
148
|
+
principal: principalSchema
|
|
149
|
+
});
|
|
150
|
+
var methodSchema = union([
|
|
151
|
+
passwordMethodSchema,
|
|
152
|
+
passkeyMethodSchema,
|
|
153
|
+
providerMethodSchema
|
|
154
|
+
]);
|
|
155
|
+
var nullableStringSchema = nullish(string());
|
|
156
|
+
var nullableIdentifierSchema = nullish(union([string(), number()]));
|
|
157
|
+
var nullableBooleanSchema = nullish(boolean());
|
|
158
|
+
var userInfoSchema = pipe(object({
|
|
159
|
+
sub: nullableIdentifierSchema,
|
|
160
|
+
id: nullableIdentifierSchema,
|
|
161
|
+
email: nullableStringSchema,
|
|
162
|
+
email_verified: nullableBooleanSchema,
|
|
163
|
+
given_name: nullableStringSchema,
|
|
164
|
+
first_name: nullableStringSchema,
|
|
165
|
+
name: nullableStringSchema,
|
|
166
|
+
family_name: nullableStringSchema,
|
|
167
|
+
last_name: nullableStringSchema,
|
|
168
|
+
picture: nullableStringSchema,
|
|
169
|
+
avatar_url: nullableStringSchema,
|
|
170
|
+
preferred_username: nullableStringSchema,
|
|
171
|
+
login: nullableStringSchema,
|
|
172
|
+
username: nullableStringSchema
|
|
173
|
+
}), transform((user) => ({
|
|
174
|
+
sub: String(user.sub ?? user.id ?? ""),
|
|
175
|
+
email: user.email ?? void 0,
|
|
176
|
+
email_verified: user.email_verified ?? void 0,
|
|
177
|
+
given_name: user.given_name ?? user.first_name ?? user.name ?? void 0,
|
|
178
|
+
family_name: user.family_name ?? user.last_name ?? void 0,
|
|
179
|
+
picture: user.picture ?? user.avatar_url ?? void 0,
|
|
180
|
+
preferred_username: user.preferred_username ?? user.login ?? user.username ?? void 0
|
|
181
|
+
})));
|
|
182
|
+
var BASE64_SIGN = {
|
|
183
|
+
alphabet: "base64url",
|
|
184
|
+
omitPadding: true
|
|
185
|
+
};
|
|
186
|
+
var BASE64_VERIFY = { alphabet: "base64url" };
|
|
187
|
+
var encoder = new TextEncoder();
|
|
188
|
+
var decoder = new TextDecoder();
|
|
189
|
+
//#endregion
|
|
190
|
+
export { CREATE_PRINCIPAL_HOOK, CREATE_SESSION_HOOK, DELETE_SESSION_HOOK, GET_PRINCIPAL_HOOK, clearSession, defineAuthProvider, getCryptoKey, getSession, methodSchema, passkeyMethodSchema, passwordMethodSchema, principalSchema, providerMethodSchema, registerAuthHooks, requireSession, setSession, useAuth };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CookieOptions } from "@revojs/server";
|
|
2
|
+
export interface SessionOptions {
|
|
3
|
+
name: string;
|
|
4
|
+
cookie: CookieOptions;
|
|
5
|
+
}
|
|
6
|
+
export interface AuthConfig {
|
|
7
|
+
session: SessionOptions;
|
|
8
|
+
}
|
|
9
|
+
declare const _default: import("revojs/module").Module<"auth", AuthConfig, []>;
|
|
10
|
+
export default _default;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { defineModule, useModule } from "revojs/module";
|
|
2
|
+
//#region src/module/index.ts
|
|
3
|
+
var module_default = defineModule({
|
|
4
|
+
name: "auth",
|
|
5
|
+
config: () => ({ session: {
|
|
6
|
+
name: "session",
|
|
7
|
+
cookie: {
|
|
8
|
+
path: "/",
|
|
9
|
+
secure: true,
|
|
10
|
+
httpOnly: true,
|
|
11
|
+
sameSite: "Lax",
|
|
12
|
+
maxAge: 604800
|
|
13
|
+
}
|
|
14
|
+
} }),
|
|
15
|
+
setup() {
|
|
16
|
+
const { fromModule } = useModule(import.meta.url);
|
|
17
|
+
return {
|
|
18
|
+
variables: { server: {
|
|
19
|
+
sessionSecret: { type: "string" },
|
|
20
|
+
appleClientKey: {
|
|
21
|
+
type: "string",
|
|
22
|
+
optional: true
|
|
23
|
+
},
|
|
24
|
+
appleClientSecret: {
|
|
25
|
+
type: "string",
|
|
26
|
+
optional: true
|
|
27
|
+
},
|
|
28
|
+
githubClientKey: {
|
|
29
|
+
type: "string",
|
|
30
|
+
optional: true
|
|
31
|
+
},
|
|
32
|
+
githubClientSecret: {
|
|
33
|
+
type: "string",
|
|
34
|
+
optional: true
|
|
35
|
+
},
|
|
36
|
+
googleClientKey: {
|
|
37
|
+
type: "string",
|
|
38
|
+
optional: true
|
|
39
|
+
},
|
|
40
|
+
googleClientSecret: {
|
|
41
|
+
type: "string",
|
|
42
|
+
optional: true
|
|
43
|
+
},
|
|
44
|
+
microsoftClientKey: {
|
|
45
|
+
type: "string",
|
|
46
|
+
optional: true
|
|
47
|
+
},
|
|
48
|
+
microsoftClientSecret: {
|
|
49
|
+
type: "string",
|
|
50
|
+
optional: true
|
|
51
|
+
},
|
|
52
|
+
microsoftTenant: {
|
|
53
|
+
type: "string",
|
|
54
|
+
optional: true
|
|
55
|
+
}
|
|
56
|
+
} },
|
|
57
|
+
sources: { routes: { from: [fromModule("../routes")] } }
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
//#endregion
|
|
62
|
+
export { module_default as default };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { defineAuthProvider } from "../../../../index.js";
|
|
2
|
+
import { sendNotFound } from "@revojs/server";
|
|
3
|
+
import { useVariables } from "revojs";
|
|
4
|
+
//#region src/routes/auth/provider/apple/get.ts
|
|
5
|
+
var get_default = defineAuthProvider({ setup(scope) {
|
|
6
|
+
const { appleClientKey, appleClientSecret } = useVariables(scope);
|
|
7
|
+
if (!appleClientKey || !appleClientSecret) throw sendNotFound(scope);
|
|
8
|
+
return {
|
|
9
|
+
issuer: "apple",
|
|
10
|
+
scope: "name email",
|
|
11
|
+
clientKey: appleClientKey,
|
|
12
|
+
clientSecret: appleClientSecret,
|
|
13
|
+
authorize: {
|
|
14
|
+
url: "https://appleid.apple.com/auth/authorize",
|
|
15
|
+
parameters: { response_mode: "query" }
|
|
16
|
+
},
|
|
17
|
+
token: { url: "https://appleid.apple.com/auth/token" },
|
|
18
|
+
userInfo: { url: "https://appleid.apple.com/auth/userinfo" }
|
|
19
|
+
};
|
|
20
|
+
} });
|
|
21
|
+
//#endregion
|
|
22
|
+
export { get_default as default };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { defineAuthProvider } from "../../../../index.js";
|
|
2
|
+
import { sendNotFound } from "@revojs/server";
|
|
3
|
+
import { useVariables } from "revojs";
|
|
4
|
+
//#region src/routes/auth/provider/github/get.ts
|
|
5
|
+
var get_default = defineAuthProvider({ setup(scope) {
|
|
6
|
+
const { githubClientKey, githubClientSecret } = useVariables(scope);
|
|
7
|
+
if (!githubClientKey || !githubClientSecret) throw sendNotFound(scope);
|
|
8
|
+
return {
|
|
9
|
+
issuer: "github",
|
|
10
|
+
scope: "read:user user:email",
|
|
11
|
+
clientKey: githubClientKey,
|
|
12
|
+
clientSecret: githubClientSecret,
|
|
13
|
+
authorize: { url: "https://github.com/login/oauth/authorize" },
|
|
14
|
+
token: {
|
|
15
|
+
url: "https://github.com/login/oauth/access_token",
|
|
16
|
+
headers: { Accept: "application/json" }
|
|
17
|
+
},
|
|
18
|
+
userInfo: {
|
|
19
|
+
url: "https://api.github.com/user",
|
|
20
|
+
headers: {
|
|
21
|
+
Accept: "application/vnd.github+json",
|
|
22
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
toPrincipal(principal) {
|
|
26
|
+
return {
|
|
27
|
+
sub: String(principal.id),
|
|
28
|
+
email: principal.email ?? void 0,
|
|
29
|
+
given_name: principal.name ?? void 0,
|
|
30
|
+
picture: principal.avatar_url ?? void 0,
|
|
31
|
+
preferred_username: principal.login ?? void 0
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
} });
|
|
36
|
+
//#endregion
|
|
37
|
+
export { get_default as default };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineAuthProvider } from "../../../../index.js";
|
|
2
|
+
import { sendNotFound } from "@revojs/server";
|
|
3
|
+
import { useVariables } from "revojs";
|
|
4
|
+
//#region src/routes/auth/provider/google/get.ts
|
|
5
|
+
var get_default = defineAuthProvider({ setup(scope) {
|
|
6
|
+
const { googleClientKey, googleClientSecret } = useVariables(scope);
|
|
7
|
+
if (!googleClientKey || !googleClientSecret) throw sendNotFound(scope);
|
|
8
|
+
return {
|
|
9
|
+
issuer: "google",
|
|
10
|
+
scope: "email profile",
|
|
11
|
+
clientKey: googleClientKey,
|
|
12
|
+
clientSecret: googleClientSecret,
|
|
13
|
+
authorize: { url: "https://accounts.google.com/o/oauth2/v2/auth" },
|
|
14
|
+
token: { url: "https://oauth2.googleapis.com/token" },
|
|
15
|
+
userInfo: { url: "https://www.googleapis.com/oauth2/v3/userinfo" }
|
|
16
|
+
};
|
|
17
|
+
} });
|
|
18
|
+
//#endregion
|
|
19
|
+
export { get_default as default };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineAuthProvider } from "../../../../index.js";
|
|
2
|
+
import { sendNotFound } from "@revojs/server";
|
|
3
|
+
import { useVariables } from "revojs";
|
|
4
|
+
//#region src/routes/auth/provider/microsoft/get.ts
|
|
5
|
+
var get_default = defineAuthProvider({ setup(scope) {
|
|
6
|
+
const { microsoftClientKey, microsoftClientSecret, microsoftTenant } = useVariables(scope);
|
|
7
|
+
if (!microsoftClientKey || !microsoftClientSecret) throw sendNotFound(scope);
|
|
8
|
+
return {
|
|
9
|
+
issuer: "microsoft",
|
|
10
|
+
scope: "openid email profile",
|
|
11
|
+
clientKey: microsoftClientKey,
|
|
12
|
+
clientSecret: microsoftClientSecret,
|
|
13
|
+
authorize: { url: `https://login.microsoftonline.com/${microsoftTenant ?? "common"}/oauth2/v2.0/authorize` },
|
|
14
|
+
token: { url: `https://login.microsoftonline.com/${microsoftTenant ?? "common"}/oauth2/v2.0/token` },
|
|
15
|
+
userInfo: { url: "https://graph.microsoft.com/oidc/userinfo" }
|
|
16
|
+
};
|
|
17
|
+
} });
|
|
18
|
+
//#endregion
|
|
19
|
+
export { get_default as default };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { DELETE_SESSION_HOOK, clearSession, getSession } from "../../../index.js";
|
|
2
|
+
import { defineRoute, sendOk } from "@revojs/server";
|
|
3
|
+
import { dispatchHook } from "revojs";
|
|
4
|
+
//#region src/routes/auth/sessions/delete.ts
|
|
5
|
+
var delete_default = defineRoute({ async fetch(scope) {
|
|
6
|
+
const session = await getSession(scope);
|
|
7
|
+
if (session) await dispatchHook(scope, DELETE_SESSION_HOOK, session);
|
|
8
|
+
clearSession(scope);
|
|
9
|
+
return sendOk(scope);
|
|
10
|
+
} });
|
|
11
|
+
//#endregion
|
|
12
|
+
export { delete_default as default };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getSession } from "../../../index.js";
|
|
2
|
+
import { defineRoute, sendOk, sendUnauthorized } from "@revojs/server";
|
|
3
|
+
//#region src/routes/auth/sessions/get.ts
|
|
4
|
+
var get_default = defineRoute({ async fetch(scope) {
|
|
5
|
+
const session = await getSession(scope);
|
|
6
|
+
if (session) return sendOk(scope, session);
|
|
7
|
+
return sendUnauthorized(scope);
|
|
8
|
+
} });
|
|
9
|
+
//#endregion
|
|
10
|
+
export { get_default as default };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CREATE_PRINCIPAL_HOOK, CREATE_SESSION_HOOK, GET_PRINCIPAL_HOOK, passkeyMethodSchema, passwordMethodSchema, setSession } from "../../../index.js";
|
|
2
|
+
import { defineRoute, sendNotFound, sendOk, useBody } from "@revojs/server";
|
|
3
|
+
import { dispatchHookSingle } from "revojs";
|
|
4
|
+
import { union } from "valibot";
|
|
5
|
+
//#region src/routes/auth/sessions/post.ts
|
|
6
|
+
var post_default = defineRoute({ async fetch(scope) {
|
|
7
|
+
const method = await useBody(scope, union([passwordMethodSchema, passkeyMethodSchema]));
|
|
8
|
+
const principal = await dispatchHookSingle(scope, GET_PRINCIPAL_HOOK, method) ?? (method.type !== "PASSWORD" || method.register ? await dispatchHookSingle(scope, CREATE_PRINCIPAL_HOOK, method) : void 0);
|
|
9
|
+
if (principal) {
|
|
10
|
+
const session = await dispatchHookSingle(scope, CREATE_SESSION_HOOK, principal);
|
|
11
|
+
if (session) {
|
|
12
|
+
await setSession(scope, session);
|
|
13
|
+
return sendOk(scope);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return sendNotFound(scope);
|
|
17
|
+
} });
|
|
18
|
+
//#endregion
|
|
19
|
+
export { post_default as default };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
declare module "#variables" {
|
|
2
|
+
export const sessionSecret: string;
|
|
3
|
+
|
|
4
|
+
export const appleClientKey: string | undefined;
|
|
5
|
+
export const appleClientSecret: string | undefined;
|
|
6
|
+
|
|
7
|
+
export const githubClientKey: string | undefined;
|
|
8
|
+
export const githubClientSecret: string | undefined;
|
|
9
|
+
|
|
10
|
+
export const googleClientKey: string | undefined;
|
|
11
|
+
export const googleClientSecret: string | undefined;
|
|
12
|
+
|
|
13
|
+
export const microsoftClientKey: string | undefined;
|
|
14
|
+
export const microsoftClientSecret: string | undefined;
|
|
15
|
+
export const microsoftTenant: string | undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
declare module "#config/auth" {
|
|
19
|
+
import type { AuthConfig } from "@revojs/auth/module";
|
|
20
|
+
|
|
21
|
+
const config: AuthConfig;
|
|
22
|
+
export default config;
|
|
23
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@revojs/auth",
|
|
3
|
+
"version": "0.1.58",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/tellua/revojs.git"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"module": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"import": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./module": {
|
|
22
|
+
"types": "./dist/module/index.d.ts",
|
|
23
|
+
"import": "./dist/module/index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "vite build",
|
|
28
|
+
"watch": "vite build --watch"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@revojs/server": "*",
|
|
32
|
+
"revojs": "*",
|
|
33
|
+
"valibot": "^1.5.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@revojs/tsconfig": "*"
|
|
37
|
+
}
|
|
38
|
+
}
|