diff --git a/sdk/js/src/auth/adapter/adapter.ts b/sdk/js/src/auth/adapter/adapter.ts index 50ec317e1..f239abcd3 100644 --- a/sdk/js/src/auth/adapter/adapter.ts +++ b/sdk/js/src/auth/adapter/adapter.ts @@ -1,5 +1,7 @@ import type { Context, Hono } from "hono"; -export type Adapter = ( +import { KeyLike } from "jose"; + +export type Adapter = ( route: AdapterRoute, options: AdapterOptions, ) => void; @@ -7,8 +9,12 @@ export type Adapter = ( export type AdapterRoute = Hono; export interface AdapterOptions { name: string; + algorithm: string; + publicKey: Promise; + privateKey: Promise; success: (ctx: Context, properties: Properties) => Promise; forward: (ctx: Context, response: Response) => Response; + cookie: (ctx: Context, key: string, value: string, maxAge: number) => void; } export class AdapterError extends Error {} diff --git a/sdk/js/src/auth/adapter/apple.ts b/sdk/js/src/auth/adapter/apple.ts index a520c658f..c54f534ed 100644 --- a/sdk/js/src/auth/adapter/apple.ts +++ b/sdk/js/src/auth/adapter/apple.ts @@ -1,9 +1,6 @@ -import querystring from 'node:querystring'; -import { generators, Issuer } from 'openid-client'; +import { Issuer } from "openid-client"; -import { useBody, useCookie, useDomainName, usePathParam, useResponse } from '../../../api/index.js'; -import { Adapter } from './adapter.js'; -import { OauthConfig } from './oauth.js'; +import { OauthAdapter, OauthBasicConfig } from "./oauth.js"; // This adapter support the OAuth flow with the response_mode "form_post" for now. // More details about the flow: @@ -14,84 +11,18 @@ import { OauthConfig } from './oauth.js'; // await Issuer.discover("https://appleid.apple.com/.well-known/openid-configuration/"); const issuer = await Issuer.discover( - "https://appleid.apple.com/.well-known/openid-configuration" -) + "https://appleid.apple.com/.well-known/openid-configuration", +); export const AppleAdapter = /* @__PURE__ */ - (config: OauthConfig) => { - return async function () { - const step = usePathParam("step"); - const callback = "https://" + useDomainName() + "/callback"; - console.log("callback", callback); - - const client = new issuer.Client({ - client_id: config.clientID, - client_secret: config.clientSecret, - redirect_uris: [callback], - response_types: ["code"], - }); - - if (step === "authorize" || step === "connect") { - const code_verifier = generators.codeVerifier(); - const state = generators.state(); - const code_challenge = generators.codeChallenge(code_verifier); - - const url = client.authorizationUrl({ - scope: config.scope, - code_challenge: code_challenge, - code_challenge_method: "S256", - state, - prompt: config.prompt, - ...config.params, - }); - - useResponse().cookies( - { - auth_code_verifier: code_verifier, - auth_state: state, - }, - { - httpOnly: true, - secure: true, - maxAge: 60 * 10, - sameSite: "None", - } - ); - return { - type: "step", - properties: { - statusCode: 302, - headers: { - location: url, - }, - }, - }; - } - - if (step === "callback") { - let params = {} - if (config && config.params && config.params.response_mode === "form_post") { - const body = useBody() - if (typeof body === "string") { - params = querystring.parse(body) - } - } - - const code_verifier = useCookie("auth_code_verifier"); - const state = useCookie("auth_state"); - const tokenset = await client["callback"](callback, params, { - code_verifier, - state, - }); - const x = { - type: "success" as const, - properties: { - tokenset, - client, - }, - }; - return x; - } - } satisfies Adapter; + (config: OauthBasicConfig) => { + return OauthAdapter({ + issuer, + ...config, + params: { + ...config.params, + response_mode: "form_post", + }, + }); }; diff --git a/sdk/js/src/auth/adapter/code.ts b/sdk/js/src/auth/adapter/code.ts index eface5db7..2cb0d4c99 100644 --- a/sdk/js/src/auth/adapter/code.ts +++ b/sdk/js/src/auth/adapter/code.ts @@ -1,101 +1,69 @@ -import { APIGatewayProxyStructuredResultV2 } from "aws-lambda"; - -import { - useCookie, - useDomainName, - usePathParam, - useQueryParam, - useQueryParams, - useResponse, -} from "../../../api/index.js"; import { Adapter } from "./adapter.js"; -import { randomBytes } from "crypto"; -import { decrypt, encrypt } from "../encryption.js"; +import * as jose from "jose"; +import { deleteCookie, getCookie } from "hono/cookie"; +import { UnknownStateError } from "../index.js"; export function CodeAdapter(config: { length?: number; onCodeRequest: ( code: string, - claims: Record - ) => Promise; + claims: Record, + ) => Promise; onCodeInvalid: ( code: string, - claims: Record - ) => Promise; + claims: Record, + ) => Promise; }) { const length = config.length || 6; - function generate() { - const buffer = randomBytes(length); + const buffer = crypto.getRandomValues(new Uint8Array(length)); const otp = Array.from(buffer) .map((byte) => byte % 10) .join(""); return otp; } - return async function () { - const step = usePathParam("step"); - - if (step === "authorize" || step === "connect") { + return function (routes, ctx) { + routes.get("/authorize", async (c) => { const code = generate(); - const claims = useQueryParams(); + const claims = c.req.query(); delete claims["client_id"]; delete claims["redirect_uri"]; delete claims["response_type"]; delete claims["provider"]; - useResponse().cookies( - { - authorization: encrypt( - JSON.stringify({ - claims, - code, - }) - ), - }, - { - maxAge: 3600, - secure: true, - sameSite: "None", - httpOnly: true, - } - ); - return { - type: "step", - properties: await config.onCodeRequest(code, claims as any), - }; - } + const authorization = await new jose.CompactEncrypt( + new TextEncoder().encode( + JSON.stringify({ + claims, + code, + }), + ), + ) + .setProtectedHeader({ alg: "RSA-OAEP-512", enc: "A256GCM" }) + .encrypt(await ctx.publicKey); + ctx.cookie(c, "authorization", authorization, 60 * 10); + return ctx.forward(c, await config.onCodeRequest(code, claims as any)); + }); - if (step === "callback") { + routes.get("/callback", async (c) => { + const authorization = getCookie(c, "authorization"); + if (!authorization) throw new UnknownStateError(); const { code, claims } = JSON.parse( - decrypt(useCookie("authorization")!)! + new TextDecoder().decode( + await jose + .compactDecrypt(authorization!, await ctx.privateKey) + .then((value) => value.plaintext), + ), ); if (!code || !claims) { - return { - type: "step", - properties: await config.onCodeInvalid(code, claims), - }; + return ctx.forward(c, await config.onCodeInvalid(code, claims as any)); } - const compare = useQueryParam("code"); + const compare = c.req.query("code"); if (code !== compare) { - return { - type: "step", - properties: await config.onCodeInvalid(code, claims), - }; + return ctx.forward(c, await config.onCodeInvalid(code, claims as any)); } - useResponse().cookies( - { - authorization: "", - }, - { - expires: new Date(1), - } - ); - return { - type: "success", - properties: { - claims: claims, - }, - }; - } - } satisfies Adapter; + deleteCookie(c, "authorization"); + return ctx.forward(c, await ctx.success(c, { claims })); + }); + } satisfies Adapter<{ claims: Record }>; } diff --git a/sdk/js/src/auth/adapter/link.ts b/sdk/js/src/auth/adapter/link.ts index e09d3ea4b..3d2f8e52e 100644 --- a/sdk/js/src/auth/adapter/link.ts +++ b/sdk/js/src/auth/adapter/link.ts @@ -1,18 +1,15 @@ import { Adapter } from "./adapter.js"; -import { Resource } from "../../resource.js"; import * as jose from "jose"; -export function LinkAdapter< - T extends Record = Record, ->(config: { onLink: (link: string, claims: T) => Promise }) { +export function LinkAdapter(config: { + onLink: (link: string, claims: Record) => Promise; +}) { return function (routes, ctx) { - const { privateKey, publicKey } = Resource[process.env.AUTH_ID!]; - routes.get("/authorize", async (c) => { const token = await new jose.SignJWT(c.req.query()) - .setProtectedHeader({ alg: "RS512" }) + .setProtectedHeader({ alg: ctx.algorithm }) .setExpirationTime("10m") - .sign(await jose.importPKCS8(privateKey, "RS512")); + .sign(await ctx.privateKey); const url = new URL(new URL(c.req.url).origin); url.pathname = `/${ctx.name}/callback`; @@ -22,7 +19,7 @@ export function LinkAdapter< url.searchParams.set("token", token); const resp = ctx.forward( c, - await config.onLink(url.toString(), c.req.query() as T), + await config.onLink(url.toString(), c.req.query()), ); return resp; }); @@ -30,12 +27,9 @@ export function LinkAdapter< routes.get("/callback", async (c) => { const token = c.req.query("token"); if (!token) throw new Error("Missing token parameter"); - const verified = await jose.jwtVerify( - token, - await jose.importSPKI(publicKey, "RS512"), - ); - const resp = await ctx.success(c, verified.payload as any); + const verified = await jose.jwtVerify(token, await ctx.publicKey); + const resp = await ctx.success(c, { claims: verified.payload as any }); return resp; }); - } as Adapter; + } satisfies Adapter<{ claims: Record }>; } diff --git a/sdk/js/src/auth/adapter/oauth.ts b/sdk/js/src/auth/adapter/oauth.ts index 400d89b9a..2adb9bb0c 100644 --- a/sdk/js/src/auth/adapter/oauth.ts +++ b/sdk/js/src/auth/adapter/oauth.ts @@ -1,13 +1,7 @@ -import { APIGatewayProxyStructuredResultV2 } from "aws-lambda"; import { BaseClient, generators, Issuer, TokenSet } from "openid-client"; -import { - useCookie, - useDomainName, - usePathParam, - useQueryParams, - useResponse, -} from "../../../api/index.js"; import { Adapter, AdapterError } from "./adapter.js"; +import { Context } from "hono"; +import { getCookie } from "hono/cookie"; export interface OauthBasicConfig { /** @@ -41,23 +35,25 @@ export class OauthError extends AdapterError {} export const OauthAdapter = /* @__PURE__ */ (config: OauthConfig) => { - return async function () { - const step = usePathParam("step"); - const callback = "https://" + useDomainName() + "/callback"; - console.log("callback", callback); - - const client = new config.issuer.Client({ - client_id: config.clientID, - client_secret: config.clientSecret, - redirect_uris: [callback], - response_types: ["code"], - }); + return async function (routes, ctx) { + function getClient(c: Context) { + const callback = c.req.url.replace(/authorize$/, "callback"); + return [ + callback, + new config.issuer.Client({ + client_id: config.clientID, + client_secret: config.clientSecret, + redirect_uris: [callback], + response_types: ["code"], + }), + ] as const; + } - if (step === "authorize" || step === "connect") { + routes.get("/authorize", async (c) => { + const [_, client] = getClient(c); const code_verifier = generators.codeVerifier(); const state = generators.state(); const code_challenge = generators.codeChallenge(code_verifier); - const url = client.authorizationUrl({ scope: config.scope, code_challenge: code_challenge, @@ -66,56 +62,57 @@ export const OauthAdapter = prompt: config.prompt, ...config.params, }); + ctx.cookie(c, "auth_code_verifier", code_verifier, 60 * 10); + ctx.cookie(c, "auth_state", state, 60 * 10); + return c.redirect(url); + }); - useResponse().cookies( - { - auth_code_verifier: code_verifier, - auth_state: state, - }, - { - httpOnly: true, - secure: true, - maxAge: 60 * 10, - sameSite: "None", - } - ); - return { - type: "step", - properties: { - statusCode: 302, - headers: { - location: url, - }, - }, - }; - } + routes.get("/callback", async (c) => { + const [callback, client] = getClient(c); + const query = c.req.query(); + if (query.error) { + throw new OauthError(query.error); + } + const code_verifier = getCookie(c, "auth_code_verifier"); + const state = getCookie(c, "auth_state"); + const tokenset = await client[ + config.issuer.metadata.userinfo_endpoint + ? "callback" + : "oauthCallback" + ](callback, query, { + code_verifier, + state, + }); + return ctx.success(c, { + client, + tokenset, + }); + }); - if (step === "callback") { - const params = useQueryParams(); - if (params.error) { - return { - type: "error", - error: new OauthError(params.error), - }; + // response_mode=form_post + routes.get("/callback", async (c) => { + const [callback, client] = getClient(c); + const form = await c.req.formData(); + if (form.get("error")) { + throw new OauthError(form.get("error")!.toString()); } - const code_verifier = useCookie("auth_code_verifier"); - const state = useCookie("auth_state"); + const code_verifier = getCookie(c, "auth_code_verifier"); + const state = getCookie(c, "auth_state"); const tokenset = await client[ config.issuer.metadata.userinfo_endpoint ? "callback" : "oauthCallback" - ](callback, params, { + ](callback, Object.fromEntries(form), { code_verifier, state, }); - const x = { - type: "success" as const, - properties: { - tokenset, - client, - }, - }; - return x; - } - } satisfies Adapter; + return ctx.success(c, { + client, + tokenset, + }); + }); + } satisfies Adapter<{ + tokenset: TokenSet; + client: BaseClient; + }>; }; diff --git a/sdk/js/src/auth/adapter/oidc.ts b/sdk/js/src/auth/adapter/oidc.ts index 1639eacb3..c2f792c6d 100644 --- a/sdk/js/src/auth/adapter/oidc.ts +++ b/sdk/js/src/auth/adapter/oidc.ts @@ -1,12 +1,6 @@ -import { generators, Issuer } from "openid-client"; -import { - useCookie, - useDomainName, - useFormData, - usePathParam, - useResponse, -} from "../../../api/index.js"; +import { BaseClient, generators, Issuer, TokenSet } from "openid-client"; import { Adapter } from "./adapter.js"; +import { getCookie } from "hono/cookie"; export interface OidcBasicConfig { /** @@ -25,17 +19,14 @@ export interface OidcConfig extends OidcBasicConfig { } export const OidcAdapter = /* @__PURE__ */ (config: OidcConfig) => { - return async function () { - const step = usePathParam("step"); - const callback = "https://" + useDomainName() + "/callback"; - - const client = new config.issuer.Client({ - client_id: config.clientID, - redirect_uris: [callback], - response_types: ["id_token"], - }); - - if (step === "authorize" || step === "connect") { + return async function (routes, ctx) { + routes.get("/authorize", async (c) => { + const callback = c.req.url.replace(/authorize$/, "callback"); + const client = new config.issuer.Client({ + client_id: config.clientID, + redirect_uris: [callback], + response_types: ["id_token"], + }); const nonce = generators.nonce(); const state = generators.state(); const url = client.authorizationUrl({ @@ -45,50 +36,40 @@ export const OidcAdapter = /* @__PURE__ */ (config: OidcConfig) => { state, prompt: config.prompt, }); + ctx.cookie(c, "auth_nonce", nonce, 60 * 10); + ctx.cookie(c, "auth_state", state, 60 * 10); + return c.redirect(url); + }); - useResponse().cookies( - { - auth_nonce: nonce, - auth_state: state, - }, + routes.post("/callback", async (c) => { + const callback = c.req.url.replace(/authorize$/, "callback"); + const client = new config.issuer.Client({ + client_id: config.clientID, + redirect_uris: [callback], + response_types: ["id_token"], + }); + + const form = await c.req.formData(); + const nonce = getCookie(c, "auth_nonce"); + const state = getCookie(c, "auth_state"); + const tokenset = await client.callback( + callback, + Object.fromEntries(form), { - httpOnly: true, - secure: true, - maxAge: 60 * 10, - sameSite: "None", + nonce, + state, }, ); - return { - type: "step", - properties: { - statusCode: 302, - headers: { - location: url, - }, - }, - }; - } - if (step === "callback") { - const form = useFormData(); - if (!form) throw new Error("Missing body"); - const params = Object.fromEntries(form.entries()); - const nonce = useCookie("auth_nonce"); - const state = useCookie("auth_state"); - const tokenset = await client.callback(callback, params, { - nonce, - state, + return ctx.success(c, { + tokenset, + client, }); - const x = { - type: "success" as const, - properties: { - tokenset, - client, - }, - }; - return x; - } + }); throw new Error("Invalid auth request"); - } satisfies Adapter; + } satisfies Adapter<{ + tokenset: TokenSet; + client: BaseClient; + }>; }; diff --git a/sdk/js/src/auth/encryption.ts b/sdk/js/src/auth/encryption.ts deleted file mode 100644 index e39922096..000000000 --- a/sdk/js/src/auth/encryption.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { - createCipheriv, - createDecipheriv, - createHash, - randomBytes, -} from "crypto"; -import { Config } from "../../config/index.js"; - -export function encrypt(data: string) { - // @ts-expect-error - const key = Config[process.env.AUTH_ID + "PrivateKey"] as string; - const hashed = createHash("sha256").update(key).digest(); - - const iv = randomBytes(16); // Generate a random IV (Initialization Vector) - const cipher = createCipheriv("aes-256-cbc", hashed, iv); - let encrypted = cipher.update(data, "utf8", "hex"); - encrypted += cipher.final("hex"); - return JSON.stringify({ - i: iv.toString("hex"), - d: encrypted, - }); -} - -export function decrypt(data: string) { - // @ts-expect-error - const key = Config[process.env.AUTH_ID + "PrivateKey"] as string; - const hashed = createHash("sha256").update(key).digest(); - - try { - const parsed = JSON.parse(data); - const decipher = createDecipheriv( - "aes-256-cbc", - hashed, - Buffer.from(parsed.i, "hex") - ); - let decrypted = decipher.update(parsed.d, "hex", "utf8"); - decrypted += decipher.final("utf8"); - return decrypted; - } catch { - return; - } -} diff --git a/sdk/js/src/auth/example/bun.ts b/sdk/js/src/auth/example/bun.ts index 5ddd486ac..9a6901698 100644 --- a/sdk/js/src/auth/example/bun.ts +++ b/sdk/js/src/auth/example/bun.ts @@ -1,6 +1,7 @@ import { AuthHandler } from "../handler.js"; import { LinkAdapter } from "../adapter/link.js"; import { createSessionBuilder } from "../session.js"; +import { CodeAdapter } from "../index.js"; const sessions = createSessionBuilder<{ user: { @@ -8,19 +9,32 @@ const sessions = createSessionBuilder<{ }; }>(); -export default AuthHandler( - sessions, - { +export default AuthHandler({ + providers: { link: LinkAdapter({ - async onLink(link, claims: { email: string }) { + async onLink(link, claims) { return new Response(link, { status: 200, headers: { "Content-Type": "text/plain" }, }); }, }), + code: CodeAdapter({ + onCodeRequest: async (code, claims) => { + return new Response("Your code is " + code, { + status: 200, + headers: { "Content-Type": "text/plain" }, + }); + }, + onCodeInvalid: async (code, claims) => { + return new Response("Code is invalid " + code, { + status: 200, + headers: { "Content-Type": "text/plain" }, + }); + }, + }), }, - { + callbacks: { auth: { async allowClient(input) { return true; @@ -29,10 +43,10 @@ export default AuthHandler( return ctx.session({ type: "user", properties: { - email: input.email, + email: input.claims.email, }, }); }, }, }, -); +}); diff --git a/sdk/js/src/auth/handler.ts b/sdk/js/src/auth/handler.ts index 7d84a7d47..9a8d40873 100644 --- a/sdk/js/src/auth/handler.ts +++ b/sdk/js/src/auth/handler.ts @@ -5,14 +5,6 @@ import { Hono } from "hono/tiny"; import { Context } from "hono"; import { Resource } from "../resource.js"; import { deleteCookie, getCookie, setCookie } from "hono/cookie"; -import { CookieOptions } from "hono/utils/cookie"; - -const COOKIES = { - maxAge: 60 * 15, - // secure: true, - // sameSite: "None", - httpOnly: true, -} satisfies CookieOptions; interface OnSuccessResponder { session(input: T & jose.JWTPayload): Promise; @@ -53,12 +45,23 @@ export class InvalidSessionError extends Error { } } +export type Prettify = { + [K in keyof T]: T[K]; +} & {}; + export function AuthHandler< - Providers extends { [key: string]: Adapter }, - Sessions extends SessionBuilder, ->( - _sessions: Sessions, - providers: Providers, + Providers extends Record>, + Sessions extends SessionBuilder = SessionBuilder, + Result = { + [key in keyof Providers]: Prettify< + { + provider: key; + } & (Providers[key] extends Adapter ? T : {}) + >; + }[keyof Providers], +>(input: { + session?: Sessions; + providers: Providers; callbacks: { index?(event: Request): Promise; error?(error: UnknownStateError): Promise; @@ -73,13 +76,7 @@ export function AuthHandler< allowClient(clientID: string, redirect: string): Promise; success( response: OnSuccessResponder, - input: { - [key in keyof Providers]: Providers[key] extends Adapter< - infer Success - > - ? Success - : never; - }[keyof Providers], + input: Result, ): Promise; }; connect?: { @@ -89,15 +86,17 @@ export function AuthHandler< start?(session: Sessions["$typeValues"], event: Request): Promise; success?(session: Sessions["$typeValues"], input: {}): Promise; }; - }, -) { + }; +}) { const auth = Resource[process.env.AUTH_ID!]; - const privateKey = jose.importPKCS8(auth.privateKey, "RS512"); - // const publicKey = jose.importSPKI(auth.publicKey, "RS512"); + const privateKey = jose.importPKCS8(auth.privateKey, "RSA-OAEP-512"); + const publicKey = jose.importSPKI(auth.publicKey, "RSA-OAEP-512", { + extractable: true, + }); const app = new Hono(); - if (!callbacks.auth.error) { - callbacks.auth.error = async (err) => { + if (!input.callbacks.auth.error) { + input.callbacks.auth.error = async (err) => { return new Response(err.message, { status: 400, headers: { @@ -119,11 +118,7 @@ export function AuthHandler< return c.text("Missing code"); } - const pub = Resource[process.env.AUTH_ID!].publicKey; - const { payload } = await jose.jwtVerify( - code as string, - await jose.importPKCS8(pub, "RS512"), - ); + const { payload } = await jose.jwtVerify(code as string, await privateKey); if (payload.redirect_uri !== form.get("redirect_uri")) { c.status(400); return c.text("redirect_uri mismatch"); @@ -160,34 +155,34 @@ export function AuthHandler< c.status(400); return c.text("Missing response_type"); } - const cookies = { - ...COOKIES, - ...(c.req.url.startsWith("https://") - ? { secure: true, sameSite: "None" } - : {}), - } as CookieOptions; - setCookie(c, "provider", provider, cookies); - setCookie(c, "response_type", response_type, cookies); - setCookie(c, "redirect_uri", redirect_uri, cookies); - setCookie(c, "state", state || "", cookies); + options.cookie(c, "provider", provider, 60 * 10); + options.cookie(c, "response_type", response_type, 60 * 10); + options.cookie(c, "redirect_uri", redirect_uri, 60 * 10); + options.cookie(c, "state", state || "", 60 * 10); - if (callbacks.auth.start) { - await callbacks.auth.start(c.req.raw); + if (input.callbacks.auth.start) { + await input.callbacks.auth.start(c.req.raw); } await next(); }); - const options: Omit, "name"> = { + const options: { + algorithm: AdapterOptions["algorithm"]; + success: AdapterOptions["success"]; + forward: AdapterOptions["forward"]; + cookie: AdapterOptions["cookie"]; + } = { + algorithm: "RS512", async success(ctx: Context, properties: any) { const redirect_uri = getCookie(ctx, "redirect_uri"); const response_type = getCookie(ctx, "response_type"); if (!redirect_uri) { return options.forward( ctx, - await callbacks.auth.error!(new UnknownStateError()), + await input.callbacks.auth.error!(new UnknownStateError()), ); } - return await callbacks.auth.success( + return await input.callbacks.auth.success( { async session(session) { const token = await new jose.SignJWT(session) @@ -241,12 +236,23 @@ export function AuthHandler< Object.fromEntries(response.headers.entries()), ); }, + cookie(c, key, value, maxAge) { + setCookie(c, key, value, { + maxAge, + httpOnly: true, + ...(c.req.url.startsWith("https://") + ? { secure: true, sameSite: "None" } + : {}), + }); + }, }; - for (const [name, value] of Object.entries(providers)) { + for (const [name, value] of Object.entries(input.providers)) { const route = new Hono(); value(route, { name, + publicKey, + privateKey, ...options, }); app.route(`/${name}`, route); diff --git a/sdk/js/src/auth/index.ts b/sdk/js/src/auth/index.ts index c8def8ffb..9ef3f5e18 100644 --- a/sdk/js/src/auth/index.ts +++ b/sdk/js/src/auth/index.ts @@ -13,6 +13,5 @@ export type { Adapter } from "./adapter/adapter.js"; export * from "./session.js"; export * from "./handler.js"; -export * from "./encryption.js"; export { Issuer } from "openid-client";