Skip to content

Instantly share code, notes, and snippets.

@arisris
Last active March 28, 2023 15:09
Show Gist options
  • Save arisris/14eb27242cce7a8126c596f8502923a9 to your computer and use it in GitHub Desktop.
Save arisris/14eb27242cce7a8126c596f8502923a9 to your computer and use it in GitHub Desktop.
save: @auth/core implementation in fresh framework

how to use it?

To resolve dependencies defined by @auth/core First you need to modify ./import_map.json and add this scope

{
  "imports": {...},
  "scopes": {
    ...
    "https://cdn.jsdelivr.net/npm/@auth/core@0.5.1/": {
      "@panva/hkdf": "https://deno.land/x/hkdf@v1.0.4/index.ts",
      "oauth4webapi": "https://deno.land/x/oauth4webapi@v2.2.0/mod.ts",
      "cookie": "https://esm.sh/v113/cookie@0.5.0"
    },
  }
}
// see the original implementation: https://github.com/nextauthjs/next-auth/blob/main/packages/frameworks-solid-start/src/index.ts
// Note: Any dependencies by @auth/core is scoped in import_map.json
import { Handler, Status } from "$fresh/server.ts";
// @deno-types="https://cdn.jsdelivr.net/npm/@auth/core@0.5.1/index.d.ts"
import {
Auth,
AuthConfig,
} from "https://cdn.jsdelivr.net/npm/@auth/core@0.5.1/index.js";
// @deno-types="https://cdn.jsdelivr.net/npm/@auth/core@0.5.1/types.d.ts"
import {
AuthAction,
Session,
} from "https://cdn.jsdelivr.net/npm/@auth/core@0.5.1/types.js";
// @deno-types="https://cdn.jsdelivr.net/npm/@auth/core@0.5.1/providers/github.d.ts"
export { default as GitHubProvider } from "https://cdn.jsdelivr.net/npm/@auth/core@0.5.1/providers/github.js";
export type { AuthAction };
// custom role
export type Role = "admin" | "user";
// a custom declaration
declare module "https://cdn.jsdelivr.net/npm/@auth/core@0.5.1/types.js" {
interface User {
role?: Role | null;
}
interface Session {
user: {
role?: Role | null;
} & DefaultUser;
}
}
export interface FreshAuthConfig extends AuthConfig {
/**
* Defines the base path for the auth routes.
* @default '/api/auth'
*/
prefix?: string;
}
const actions: AuthAction[] = [
"providers",
"session",
"csrf",
"signin",
"signout",
"callback",
"verify-request",
"error",
];
export function FreshAuth(config: FreshAuthConfig): Handler {
const { prefix = "/api/auth", ...authOptions } = config;
authOptions.secret ??= Deno.env.get("AUTH_SECRET");
authOptions.trustHost ??= !!(
Deno.env.get("AUTH_TRUST_HOST") ?? Deno.env.get("DENO_DEPLOYMENT_ID")
);
return async (request: Request, _ctx) => {
if (!["GET", "POST"].includes(request.method))
return new Response("Invalid method", { status: Status.NotImplemented });
const url = new URL(request.url);
const action = url.pathname
.slice(prefix.length + 1)
.split("/")[0] as AuthAction;
if (!actions.includes(action) || !url.pathname.startsWith(prefix + "/")) {
return new Response("Not Found", { status: Status.NotFound });
}
const response = await Auth(request, authOptions);
// const resp = response.clone();
// console.log(await resp.text());
return response;
};
}
export type GetSessionResult = Promise<Session | null>;
export async function getSession(
req: Request,
options: FreshAuthConfig
): GetSessionResult {
options.secret ??= Deno.env.get("AUTH_SECRET");
options.trustHost ??= true;
const { prefix = "/api/auth" } = options;
const url = new URL(`${prefix}/session`, req.url);
const response = await Auth(
new Request(url, { headers: req.headers }),
options
);
const { status = Status.OK } = response;
const data = await response.json();
if (!data || !Object.keys(data).length) return null;
if (status === Status.OK) return data;
throw new Error(data.message);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment