@thecodeorigin/auth 0.0.1 → 0.0.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/module.d.mts +17 -3
- package/dist/module.d.ts +17 -3
- package/dist/module.json +1 -1
- package/dist/module.mjs +12 -12
- package/dist/runtime/server/api/_auth/stop-impersonating.post.js +3 -3
- package/dist/runtime/server/routes/callback.get.js +8 -7
- package/dist/runtime/server/routes/sign-in.get.js +10 -9
- package/dist/runtime/server/routes/sign-out.get.js +4 -4
- package/dist/runtime/server/utils/handlers.d.ts +9 -0
- package/dist/runtime/server/utils/handlers.js +21 -0
- package/dist/runtime/server/utils/idp.js +9 -8
- package/dist/runtime/server/utils/oidc.d.ts +25 -18
- package/dist/runtime/server/utils/oidc.js +10 -24
- package/dist/runtime/server/utils/session.js +15 -18
- package/package.json +1 -1
package/dist/module.d.mts
CHANGED
|
@@ -9,14 +9,28 @@ interface AuthRoutes {
|
|
|
9
9
|
}
|
|
10
10
|
interface ModuleOptions {
|
|
11
11
|
domain: string;
|
|
12
|
-
clientId: string;
|
|
13
|
-
clientSecret: string;
|
|
14
|
-
issuer?: string;
|
|
15
12
|
scopes?: string[];
|
|
16
13
|
sessionStorageBase?: string;
|
|
17
14
|
sessionCookieName?: string;
|
|
18
15
|
routes?: Partial<AuthRoutes>;
|
|
19
16
|
}
|
|
17
|
+
declare module '@nuxt/schema' {
|
|
18
|
+
interface RuntimeConfig {
|
|
19
|
+
auth: {
|
|
20
|
+
clientSecret: string;
|
|
21
|
+
sessionStorageBase: string;
|
|
22
|
+
sessionCookieName: string;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
interface PublicRuntimeConfig {
|
|
26
|
+
auth: {
|
|
27
|
+
domain: string;
|
|
28
|
+
clientId: string;
|
|
29
|
+
routes: AuthRoutes;
|
|
30
|
+
scopes: string[];
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
20
34
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
21
35
|
|
|
22
36
|
export { _default as default };
|
package/dist/module.d.ts
CHANGED
|
@@ -9,14 +9,28 @@ interface AuthRoutes {
|
|
|
9
9
|
}
|
|
10
10
|
interface ModuleOptions {
|
|
11
11
|
domain: string;
|
|
12
|
-
clientId: string;
|
|
13
|
-
clientSecret: string;
|
|
14
|
-
issuer?: string;
|
|
15
12
|
scopes?: string[];
|
|
16
13
|
sessionStorageBase?: string;
|
|
17
14
|
sessionCookieName?: string;
|
|
18
15
|
routes?: Partial<AuthRoutes>;
|
|
19
16
|
}
|
|
17
|
+
declare module '@nuxt/schema' {
|
|
18
|
+
interface RuntimeConfig {
|
|
19
|
+
auth: {
|
|
20
|
+
clientSecret: string;
|
|
21
|
+
sessionStorageBase: string;
|
|
22
|
+
sessionCookieName: string;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
interface PublicRuntimeConfig {
|
|
26
|
+
auth: {
|
|
27
|
+
domain: string;
|
|
28
|
+
clientId: string;
|
|
29
|
+
routes: AuthRoutes;
|
|
30
|
+
scopes: string[];
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
20
34
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
21
35
|
|
|
22
36
|
export { _default as default };
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -5,8 +5,6 @@ const module$1 = defineNuxtModule({
|
|
|
5
5
|
meta: { name: "@thecodeorigin/auth", configKey: "auth" },
|
|
6
6
|
defaults: {
|
|
7
7
|
domain: "",
|
|
8
|
-
clientId: "",
|
|
9
|
-
clientSecret: "",
|
|
10
8
|
scopes: ["openid", "profile", "email"],
|
|
11
9
|
sessionStorageBase: "auth",
|
|
12
10
|
sessionCookieName: "tco_auth",
|
|
@@ -14,16 +12,18 @@ const module$1 = defineNuxtModule({
|
|
|
14
12
|
},
|
|
15
13
|
setup(options, nuxt) {
|
|
16
14
|
const resolver = createResolver(import.meta.url);
|
|
17
|
-
const routes = options.routes;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
);
|
|
23
|
-
nuxt.options.runtimeConfig.public.auth = defu(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
15
|
+
const routes = { signIn: "/auth/sign-in", callback: "/auth/callback", signOut: "/auth/sign-out", home: "/", error: "/auth/sign-in", ...options.routes };
|
|
16
|
+
nuxt.options.runtimeConfig.auth = defu(nuxt.options.runtimeConfig.auth, {
|
|
17
|
+
clientSecret: "",
|
|
18
|
+
sessionStorageBase: options.sessionStorageBase,
|
|
19
|
+
sessionCookieName: options.sessionCookieName
|
|
20
|
+
});
|
|
21
|
+
nuxt.options.runtimeConfig.public.auth = defu(nuxt.options.runtimeConfig.public.auth, {
|
|
22
|
+
domain: options.domain,
|
|
23
|
+
clientId: "",
|
|
24
|
+
routes,
|
|
25
|
+
scopes: options.scopes
|
|
26
|
+
});
|
|
27
27
|
addServerHandler({ route: routes.signIn, handler: resolver.resolve("./runtime/server/routes/sign-in.get") });
|
|
28
28
|
addServerHandler({ route: routes.callback, handler: resolver.resolve("./runtime/server/routes/callback.get") });
|
|
29
29
|
addServerHandler({ route: routes.signOut, handler: resolver.resolve("./runtime/server/routes/sign-out.get") });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createError, defineEventHandler } from "h3";
|
|
2
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
2
3
|
import { useStorage } from "nitropack/runtime";
|
|
3
4
|
import { idpFetch } from "../../utils/idp.js";
|
|
4
|
-
import { resolveAuthConfig } from "../../utils/oidc.js";
|
|
5
5
|
import { readSessionRecord, readSessionRecordById, toPublicSession, writeSessionRecord } from "../../utils/session.js";
|
|
6
6
|
export default defineEventHandler(async (event) => {
|
|
7
7
|
const s = await readSessionRecord(event);
|
|
@@ -15,7 +15,7 @@ export default defineEventHandler(async (event) => {
|
|
|
15
15
|
if (!backup)
|
|
16
16
|
throw createError({ statusCode: 500, statusMessage: "Original session missing \u2014 sign in again" });
|
|
17
17
|
await writeSessionRecord(s.id, backup);
|
|
18
|
-
const
|
|
19
|
-
await useStorage(
|
|
18
|
+
const { auth: runtimeConfig } = useRuntimeConfig();
|
|
19
|
+
await useStorage(runtimeConfig.sessionStorageBase).removeItem(`session:${s.rec.backupId}`);
|
|
20
20
|
return toPublicSession(backup);
|
|
21
21
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { defineEventHandler, deleteCookie, getCookie, getQuery, sendRedirect } from "h3";
|
|
2
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
2
3
|
import { z } from "zod";
|
|
3
4
|
import { UserinfoClaimsSchema } from "../../../contract";
|
|
4
|
-
import { callbackRedirectUri, exchangeCode, fetchUserinfo,
|
|
5
|
+
import { callbackRedirectUri, exchangeCode, fetchUserinfo, safePath } from "../utils/oidc.js";
|
|
5
6
|
import { newSessionId, setSessionCookie, writeSessionRecord } from "../utils/session.js";
|
|
6
7
|
const RawUserinfoSchema = UserinfoClaimsSchema.extend({
|
|
7
8
|
sub: z.string(),
|
|
@@ -11,23 +12,23 @@ const RawUserinfoSchema = UserinfoClaimsSchema.extend({
|
|
|
11
12
|
picture: z.string().optional()
|
|
12
13
|
});
|
|
13
14
|
export default defineEventHandler(async (event) => {
|
|
14
|
-
const
|
|
15
|
+
const { public: { auth: publicRuntimeConfig } } = useRuntimeConfig();
|
|
15
16
|
const q = getQuery(event);
|
|
16
|
-
const fail = (e) => sendRedirect(event, `${
|
|
17
|
+
const fail = (e) => sendRedirect(event, `${publicRuntimeConfig.routes.error}?error=${encodeURIComponent(e)}`);
|
|
17
18
|
if (q.error)
|
|
18
19
|
return fail(String(q.error));
|
|
19
20
|
const state = getCookie(event, "tco_state");
|
|
20
21
|
const verifier = getCookie(event, "tco_verifier");
|
|
21
|
-
const redirectTo = safePath(getCookie(event, "tco_redirect"),
|
|
22
|
+
const redirectTo = safePath(getCookie(event, "tco_redirect"), publicRuntimeConfig.routes.home);
|
|
22
23
|
for (const c of ["tco_state", "tco_verifier", "tco_redirect"])
|
|
23
|
-
deleteCookie(event, c, { path:
|
|
24
|
+
deleteCookie(event, c, { path: publicRuntimeConfig.routes.callback });
|
|
24
25
|
if (!q.code || !q.state || !state || q.state !== state || !verifier)
|
|
25
26
|
return fail("invalid_state");
|
|
26
27
|
let tokens;
|
|
27
28
|
let userinfoRaw;
|
|
28
29
|
try {
|
|
29
|
-
tokens = await exchangeCode(
|
|
30
|
-
userinfoRaw = await fetchUserinfo(
|
|
30
|
+
tokens = await exchangeCode(String(q.code), verifier, callbackRedirectUri(event));
|
|
31
|
+
userinfoRaw = await fetchUserinfo(tokens.access_token);
|
|
31
32
|
} catch (err) {
|
|
32
33
|
const detail = err instanceof Error ? err.message : String(err);
|
|
33
34
|
console.error("[auth:callback] exchange failed:", detail);
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { createError, defineEventHandler, getQuery, sendRedirect, setCookie } from "h3";
|
|
2
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
2
3
|
import { withQuery } from "ufo";
|
|
3
|
-
import { callbackRedirectUri, pkceChallenge, randomString,
|
|
4
|
+
import { callbackRedirectUri, pkceChallenge, randomString, safePath } from "../utils/oidc.js";
|
|
4
5
|
export default defineEventHandler(async (event) => {
|
|
5
|
-
const
|
|
6
|
-
if (!
|
|
6
|
+
const { auth: runtimeConfig, public: { auth: publicRuntimeConfig } } = useRuntimeConfig();
|
|
7
|
+
if (!publicRuntimeConfig.domain || !publicRuntimeConfig.clientId || !runtimeConfig.clientSecret)
|
|
7
8
|
throw createError({ statusCode: 503, statusMessage: "Auth not configured" });
|
|
8
9
|
const state = randomString(32);
|
|
9
10
|
const verifier = randomString(64);
|
|
10
|
-
const redirectTo = safePath(getQuery(event).redirect,
|
|
11
|
-
const opts = { httpOnly: true, secure: !import.meta.dev, sameSite: "lax", maxAge: 600, path:
|
|
11
|
+
const redirectTo = safePath(getQuery(event).redirect, publicRuntimeConfig.routes.home);
|
|
12
|
+
const opts = { httpOnly: true, secure: !import.meta.dev, sameSite: "lax", maxAge: 600, path: publicRuntimeConfig.routes.callback };
|
|
12
13
|
setCookie(event, "tco_state", state, opts);
|
|
13
14
|
setCookie(event, "tco_verifier", verifier, opts);
|
|
14
15
|
setCookie(event, "tco_redirect", redirectTo, opts);
|
|
15
|
-
return sendRedirect(event, withQuery(
|
|
16
|
-
client_id:
|
|
17
|
-
redirect_uri: callbackRedirectUri(event
|
|
16
|
+
return sendRedirect(event, withQuery(`https://${publicRuntimeConfig.domain}/api/auth/oauth2/authorize`, {
|
|
17
|
+
client_id: publicRuntimeConfig.clientId,
|
|
18
|
+
redirect_uri: callbackRedirectUri(event),
|
|
18
19
|
response_type: "code",
|
|
19
|
-
scope:
|
|
20
|
+
scope: publicRuntimeConfig.scopes.join(" "),
|
|
20
21
|
state,
|
|
21
22
|
code_challenge: await pkceChallenge(verifier),
|
|
22
23
|
code_challenge_method: "S256"
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { defineEventHandler, sendRedirect } from "h3";
|
|
2
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
2
3
|
import { $fetch } from "ofetch";
|
|
3
|
-
import { resolveAuthConfig } from "../utils/oidc.js";
|
|
4
4
|
import { destroySession } from "../utils/session.js";
|
|
5
5
|
export default defineEventHandler(async (event) => {
|
|
6
|
-
const
|
|
6
|
+
const { public: { auth: publicRuntimeConfig } } = useRuntimeConfig();
|
|
7
7
|
const rec = await destroySession(event);
|
|
8
8
|
if (rec?.accessToken) {
|
|
9
9
|
try {
|
|
10
|
-
await $fetch(
|
|
10
|
+
await $fetch(`https://${publicRuntimeConfig.domain}/api/auth/oauth2/endsession`, {
|
|
11
11
|
method: "POST",
|
|
12
12
|
body: new URLSearchParams({ token: rec.refreshToken ?? rec.accessToken }).toString(),
|
|
13
13
|
headers: { "Content-Type": "application/x-www-form-urlencoded" }
|
|
@@ -15,5 +15,5 @@ export default defineEventHandler(async (event) => {
|
|
|
15
15
|
} catch {
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
return sendRedirect(event,
|
|
18
|
+
return sendRedirect(event, publicRuntimeConfig.routes.home);
|
|
19
19
|
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { H3Event } from 'h3';
|
|
2
|
+
import type { ServerAuthSession } from './session.js';
|
|
3
|
+
export declare function defineAuthenticatedHandler<T>(handler: (event: H3Event, session: NonNullable<ServerAuthSession>) => Promise<T> | T): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<T>>;
|
|
4
|
+
export declare function defineAuthorizedHandler<T>(_checks: string[], handler: (event: H3Event, ctx: {
|
|
5
|
+
session: NonNullable<ServerAuthSession>;
|
|
6
|
+
}) => Promise<T> | T): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<T>>;
|
|
7
|
+
export declare function defineAdminHandler<T>(_checks: string[], handler: (event: H3Event, ctx: {
|
|
8
|
+
session: NonNullable<ServerAuthSession>;
|
|
9
|
+
}) => Promise<T> | T): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<T>>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createError, defineEventHandler } from "h3";
|
|
2
|
+
import { getServerAuthSession } from "./session.js";
|
|
3
|
+
export function defineAuthenticatedHandler(handler) {
|
|
4
|
+
return defineEventHandler(async (event) => {
|
|
5
|
+
const session = await getServerAuthSession(event);
|
|
6
|
+
if (!session)
|
|
7
|
+
throw createError({ statusCode: 401, statusMessage: "Unauthorized" });
|
|
8
|
+
event.context.activeOrganizationId = session.activeOrg;
|
|
9
|
+
return handler(event, session);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
export function defineAuthorizedHandler(_checks, handler) {
|
|
13
|
+
return defineAuthenticatedHandler(async (event, session) => handler(event, { session }));
|
|
14
|
+
}
|
|
15
|
+
export function defineAdminHandler(_checks, handler) {
|
|
16
|
+
return defineAuthenticatedHandler(async (event, session) => {
|
|
17
|
+
if (session.systemRole !== "admin")
|
|
18
|
+
throw createError({ statusCode: 403, statusMessage: "Forbidden" });
|
|
19
|
+
return handler(event, { session });
|
|
20
|
+
});
|
|
21
|
+
}
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { createError } from "h3";
|
|
2
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
2
3
|
import { $fetch } from "ofetch";
|
|
3
|
-
import { resolveAuthConfig } from "./oidc.js";
|
|
4
4
|
import { readSessionRecordById, writeSessionRecord } from "./session.js";
|
|
5
5
|
const SKEW_MS = 6e4;
|
|
6
|
-
async function refresh(
|
|
6
|
+
async function refresh(rec) {
|
|
7
7
|
if (rec.isImpersonation || !rec.refreshToken)
|
|
8
8
|
return false;
|
|
9
|
+
const { auth: runtimeConfig, public: { auth: publicRuntimeConfig } } = useRuntimeConfig();
|
|
9
10
|
try {
|
|
10
11
|
const t = await $fetch(
|
|
11
|
-
|
|
12
|
+
`https://${publicRuntimeConfig.domain}/api/auth/oauth2/token`,
|
|
12
13
|
{
|
|
13
14
|
method: "POST",
|
|
14
15
|
headers: {
|
|
15
16
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
16
|
-
"Authorization": `Basic ${btoa(`${
|
|
17
|
+
"Authorization": `Basic ${btoa(`${publicRuntimeConfig.clientId}:${runtimeConfig.clientSecret}`)}`
|
|
17
18
|
},
|
|
18
19
|
body: new URLSearchParams({ grant_type: "refresh_token", refresh_token: rec.refreshToken }).toString()
|
|
19
20
|
}
|
|
@@ -27,12 +28,12 @@ async function refresh(cfg, rec) {
|
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
export async function idpFetch(event, id, rec, path, opts = {}) {
|
|
30
|
-
const
|
|
31
|
+
const { public: { auth: publicRuntimeConfig } } = useRuntimeConfig();
|
|
31
32
|
if (!rec.isImpersonation && Date.now() > rec.accessExpiresAt - SKEW_MS) {
|
|
32
|
-
if (await refresh(
|
|
33
|
+
if (await refresh(rec))
|
|
33
34
|
await writeSessionRecord(id, rec);
|
|
34
35
|
}
|
|
35
|
-
const call = () => $fetch(
|
|
36
|
+
const call = () => $fetch(`https://${publicRuntimeConfig.domain}${path}`, {
|
|
36
37
|
method: opts.method,
|
|
37
38
|
body: opts.body,
|
|
38
39
|
query: opts.query,
|
|
@@ -49,7 +50,7 @@ export async function idpFetch(event, id, rec, path, opts = {}) {
|
|
|
49
50
|
Object.assign(rec, fresh);
|
|
50
51
|
return call();
|
|
51
52
|
}
|
|
52
|
-
if (await refresh(
|
|
53
|
+
if (await refresh(rec)) {
|
|
53
54
|
await writeSessionRecord(id, rec);
|
|
54
55
|
return call();
|
|
55
56
|
}
|
|
@@ -1,29 +1,36 @@
|
|
|
1
1
|
import type { H3Event } from 'h3';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
2
|
+
declare module 'nitropack' {
|
|
3
|
+
interface NitroRuntimeConfig {
|
|
4
|
+
auth: {
|
|
5
|
+
clientSecret: string;
|
|
6
|
+
sessionStorageBase: string;
|
|
7
|
+
sessionCookieName: string;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
interface NitroRuntimePublicConfig {
|
|
11
|
+
auth: {
|
|
12
|
+
domain: string;
|
|
13
|
+
clientId: string;
|
|
14
|
+
routes: {
|
|
15
|
+
signIn: string;
|
|
16
|
+
callback: string;
|
|
17
|
+
signOut: string;
|
|
18
|
+
home: string;
|
|
19
|
+
error: string;
|
|
20
|
+
};
|
|
21
|
+
scopes: string[];
|
|
22
|
+
};
|
|
23
|
+
}
|
|
16
24
|
}
|
|
17
|
-
export declare function resolveAuthConfig(): ResolvedAuthConfig;
|
|
18
25
|
export declare function randomString(len?: number): string;
|
|
19
26
|
export declare function pkceChallenge(verifier: string): Promise<string>;
|
|
20
|
-
export declare function callbackRedirectUri(event: H3Event
|
|
21
|
-
export declare function exchangeCode(
|
|
27
|
+
export declare function callbackRedirectUri(event: H3Event): string;
|
|
28
|
+
export declare function exchangeCode(code: string, verifier: string, redirectUri: string): Promise<{
|
|
22
29
|
access_token: string;
|
|
23
30
|
refresh_token?: string;
|
|
24
31
|
expires_in?: number;
|
|
25
32
|
id_token?: string;
|
|
26
33
|
}>;
|
|
27
|
-
export declare function fetchUserinfo(
|
|
34
|
+
export declare function fetchUserinfo(accessToken: string): Promise<any>;
|
|
28
35
|
/** Same-origin, path-only redirect target (prevents open redirect). */
|
|
29
36
|
export declare function safePath(target: string | undefined, fallback: string): string;
|
|
@@ -1,21 +1,6 @@
|
|
|
1
1
|
import { getRequestHost, getRequestProtocol } from "h3";
|
|
2
2
|
import { useRuntimeConfig } from "nitropack/runtime";
|
|
3
3
|
import { $fetch } from "ofetch";
|
|
4
|
-
export function resolveAuthConfig() {
|
|
5
|
-
const rc = useRuntimeConfig();
|
|
6
|
-
const pub = rc.public.auth ?? {};
|
|
7
|
-
const priv = rc.auth ?? {};
|
|
8
|
-
const domain = process.env.NUXT_THECODEORIGIN_DOMAIN || pub.domain || "";
|
|
9
|
-
return {
|
|
10
|
-
issuer: process.env.NUXT_THECODEORIGIN_ISSUER || pub.issuer || (domain ? `https://${domain}/api/auth` : ""),
|
|
11
|
-
clientId: process.env.NUXT_THECODEORIGIN_CLIENT_ID || pub.clientId || "",
|
|
12
|
-
clientSecret: process.env.NUXT_THECODEORIGIN_CLIENT_SECRET || priv.clientSecret || "",
|
|
13
|
-
scopes: pub.scopes ?? ["openid", "profile", "email"],
|
|
14
|
-
routes: pub.routes,
|
|
15
|
-
cookieName: priv.sessionCookieName || "tco_auth",
|
|
16
|
-
storageBase: priv.sessionStorageBase || "auth"
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
4
|
function b64url(buf) {
|
|
20
5
|
return btoa(String.fromCharCode(...new Uint8Array(buf))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
21
6
|
}
|
|
@@ -27,19 +12,19 @@ export function randomString(len = 64) {
|
|
|
27
12
|
export async function pkceChallenge(verifier) {
|
|
28
13
|
return b64url(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier)));
|
|
29
14
|
}
|
|
30
|
-
export function callbackRedirectUri(event
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
return `${proto}://${host}${cfg.routes.callback}`;
|
|
15
|
+
export function callbackRedirectUri(event) {
|
|
16
|
+
const { public: { auth: publicRuntimeConfig } } = useRuntimeConfig();
|
|
17
|
+
return `${getRequestProtocol(event)}://${getRequestHost(event)}${publicRuntimeConfig.routes.callback}`;
|
|
34
18
|
}
|
|
35
|
-
export async function exchangeCode(
|
|
19
|
+
export async function exchangeCode(code, verifier, redirectUri) {
|
|
20
|
+
const { auth: runtimeConfig, public: { auth: publicRuntimeConfig } } = useRuntimeConfig();
|
|
36
21
|
return $fetch(
|
|
37
|
-
|
|
22
|
+
`https://${publicRuntimeConfig.domain}/api/auth/oauth2/token`,
|
|
38
23
|
{
|
|
39
24
|
method: "POST",
|
|
40
25
|
headers: {
|
|
41
26
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
42
|
-
"Authorization": `Basic ${btoa(`${
|
|
27
|
+
"Authorization": `Basic ${btoa(`${publicRuntimeConfig.clientId}:${runtimeConfig.clientSecret}`)}`
|
|
43
28
|
},
|
|
44
29
|
body: new URLSearchParams({
|
|
45
30
|
grant_type: "authorization_code",
|
|
@@ -50,8 +35,9 @@ export async function exchangeCode(cfg, code, verifier, redirectUri) {
|
|
|
50
35
|
}
|
|
51
36
|
);
|
|
52
37
|
}
|
|
53
|
-
export async function fetchUserinfo(
|
|
54
|
-
|
|
38
|
+
export async function fetchUserinfo(accessToken) {
|
|
39
|
+
const { public: { auth: publicRuntimeConfig } } = useRuntimeConfig();
|
|
40
|
+
return $fetch(`https://${publicRuntimeConfig.domain}/api/auth/oauth2/userinfo`, {
|
|
55
41
|
headers: { Authorization: `Bearer ${accessToken}` }
|
|
56
42
|
});
|
|
57
43
|
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { deleteCookie, getCookie, setCookie } from "h3";
|
|
2
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
2
3
|
import { useStorage } from "nitropack/runtime";
|
|
3
|
-
import { resolveAuthConfig } from "./oidc.js";
|
|
4
|
-
function store(base) {
|
|
5
|
-
return useStorage(base);
|
|
6
|
-
}
|
|
7
4
|
function key(id) {
|
|
8
5
|
return `session:${id}`;
|
|
9
6
|
}
|
|
@@ -13,20 +10,20 @@ export function newSessionId() {
|
|
|
13
10
|
return [...a].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
14
11
|
}
|
|
15
12
|
export async function writeSessionRecord(id, rec) {
|
|
16
|
-
const
|
|
17
|
-
await
|
|
13
|
+
const { auth: runtimeConfig } = useRuntimeConfig();
|
|
14
|
+
await useStorage(runtimeConfig.sessionStorageBase).setItem(key(id), rec);
|
|
18
15
|
}
|
|
19
16
|
export async function readSessionRecord(event) {
|
|
20
|
-
const
|
|
21
|
-
const id = getCookie(event,
|
|
17
|
+
const { auth: runtimeConfig } = useRuntimeConfig();
|
|
18
|
+
const id = getCookie(event, runtimeConfig.sessionCookieName);
|
|
22
19
|
if (!id)
|
|
23
20
|
return null;
|
|
24
|
-
const rec = await
|
|
21
|
+
const rec = await useStorage(runtimeConfig.sessionStorageBase).getItem(key(id));
|
|
25
22
|
return rec ? { id, rec } : null;
|
|
26
23
|
}
|
|
27
24
|
export async function setSessionCookie(event, id) {
|
|
28
|
-
const
|
|
29
|
-
setCookie(event,
|
|
25
|
+
const { auth: runtimeConfig } = useRuntimeConfig();
|
|
26
|
+
setCookie(event, runtimeConfig.sessionCookieName, id, {
|
|
30
27
|
httpOnly: true,
|
|
31
28
|
secure: !import.meta.dev,
|
|
32
29
|
sameSite: "lax",
|
|
@@ -35,18 +32,18 @@ export async function setSessionCookie(event, id) {
|
|
|
35
32
|
});
|
|
36
33
|
}
|
|
37
34
|
export async function destroySession(event) {
|
|
38
|
-
const
|
|
39
|
-
const id = getCookie(event,
|
|
35
|
+
const { auth: runtimeConfig } = useRuntimeConfig();
|
|
36
|
+
const id = getCookie(event, runtimeConfig.sessionCookieName);
|
|
40
37
|
if (!id)
|
|
41
38
|
return null;
|
|
42
|
-
const rec = await
|
|
43
|
-
await
|
|
44
|
-
deleteCookie(event,
|
|
39
|
+
const rec = await useStorage(runtimeConfig.sessionStorageBase).getItem(key(id));
|
|
40
|
+
await useStorage(runtimeConfig.sessionStorageBase).removeItem(key(id));
|
|
41
|
+
deleteCookie(event, runtimeConfig.sessionCookieName, { path: "/" });
|
|
45
42
|
return rec;
|
|
46
43
|
}
|
|
47
44
|
export async function readSessionRecordById(id) {
|
|
48
|
-
const
|
|
49
|
-
return
|
|
45
|
+
const { auth: runtimeConfig } = useRuntimeConfig();
|
|
46
|
+
return useStorage(runtimeConfig.sessionStorageBase).getItem(key(id));
|
|
50
47
|
}
|
|
51
48
|
export async function getServerAuthSession(event) {
|
|
52
49
|
const s = await readSessionRecord(event);
|
package/package.json
CHANGED