@better-auth/oauth-provider 1.4.17 → 1.4.18

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.
@@ -78,4 +78,5 @@ type ProtectedResourceMetadataOutput<T> = T extends Auth ? (overrides?: Partial<
78
78
  externalScopes?: string[];
79
79
  }) => Promise<ResourceServerMetadata>;
80
80
  //#endregion
81
- export { VerifyAccessTokenRemote, oauthProviderResourceClient };
81
+ export { VerifyAccessTokenRemote, oauthProviderResourceClient };
82
+ //# sourceMappingURL=client-resource.d.mts.map
@@ -1,4 +1,4 @@
1
- import { a as getJwtPlugin, f as handleMcpErrors, o as getOAuthProviderPlugin } from "./utils-LksXOM6z.mjs";
1
+ import { a as getJwtPlugin, o as getOAuthProviderPlugin, p as handleMcpErrors } from "./utils-DnfreTWo.mjs";
2
2
  import { verifyAccessToken } from "better-auth/oauth2";
3
3
  import { APIError } from "better-call";
4
4
  import { BetterAuthError } from "@better-auth/core/error";
@@ -80,4 +80,5 @@ const oauthProviderResourceClient = (auth) => {
80
80
  };
81
81
 
82
82
  //#endregion
83
- export { oauthProviderResourceClient };
83
+ export { oauthProviderResourceClient };
84
+ //# sourceMappingURL=client-resource.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-resource.mjs","names":["jwtPlugin: ReturnType<typeof getJwtPlugin> | undefined"],"sources":["../src/client-resource.ts"],"sourcesContent":["import { logger } from \"@better-auth/core/env\";\nimport { BetterAuthError } from \"@better-auth/core/error\";\nimport { verifyAccessToken } from \"better-auth/oauth2\";\nimport type { Auth, BetterAuthClientPlugin } from \"better-auth/types\";\nimport { APIError } from \"better-call\";\nimport type { JWTPayload, JWTVerifyOptions } from \"jose\";\nimport { handleMcpErrors } from \"./mcp\";\nimport type { ResourceServerMetadata } from \"./types/oauth\";\nimport { getJwtPlugin, getOAuthProviderPlugin } from \"./utils\";\n\nexport const oauthProviderResourceClient = <T extends Auth | undefined>(\n\tauth?: T,\n) => {\n\tconst oauthProviderPlugin = auth ? getOAuthProviderPlugin(auth) : undefined;\n\tconst oauthProviderOptions = oauthProviderPlugin?.options;\n\tlet jwtPlugin: ReturnType<typeof getJwtPlugin> | undefined;\n\tconst getJwtPluginOptions = async () => {\n\t\tif (!jwtPlugin) {\n\t\t\tjwtPlugin =\n\t\t\t\tauth && !oauthProviderOptions?.disableJwtPlugin\n\t\t\t\t\t? getJwtPlugin(await auth.$context)\n\t\t\t\t\t: undefined;\n\t\t}\n\t\treturn jwtPlugin?.options;\n\t};\n\tconst getAuthorizationServer = async () => {\n\t\tconst jwtPluginOptions = await getJwtPluginOptions();\n\t\treturn jwtPluginOptions?.jwt?.issuer ?? authServerBaseUrl;\n\t};\n\tconst authServerBaseUrl = auth?.options.baseURL;\n\tconst authServerBasePath = auth?.options.basePath;\n\n\treturn {\n\t\tid: \"oauth-provider-resource-client\",\n\t\tgetActions() {\n\t\t\treturn {\n\t\t\t\t/**\n\t\t\t\t * Performs verification of an access token for your APIs. Can perform\n\t\t\t\t * local verification using `jwksUrl` by default. Can also be configured\n\t\t\t\t * for remote introspection using `remoteVerify` if a confidential client\n\t\t\t\t * is set up for this API.\n\t\t\t\t *\n\t\t\t\t * The optional auth parameter can fill known values automatically.\n\t\t\t\t */\n\t\t\t\tverifyAccessToken: (async (\n\t\t\t\t\ttoken: string | undefined,\n\t\t\t\t\topts?: {\n\t\t\t\t\t\tverifyOptions?: JWTVerifyOptions &\n\t\t\t\t\t\t\tRequired<Pick<JWTVerifyOptions, \"audience\" | \"issuer\">>;\n\t\t\t\t\t\tscopes?: string[];\n\t\t\t\t\t\tjwksUrl?: string;\n\t\t\t\t\t\tremoteVerify?: VerifyAccessTokenRemote;\n\t\t\t\t\t\t/** Maps non-url (ie urn, client) resources to resource_metadata */\n\t\t\t\t\t\tresourceMetadataMappings?: Record<string, string>;\n\t\t\t\t\t},\n\t\t\t\t): Promise<JWTPayload> => {\n\t\t\t\t\tconst jwtPluginOptions = await getJwtPluginOptions();\n\t\t\t\t\tconst audience = opts?.verifyOptions?.audience ?? authServerBaseUrl;\n\t\t\t\t\tconst issuer =\n\t\t\t\t\t\topts?.verifyOptions?.issuer ??\n\t\t\t\t\t\tjwtPluginOptions?.jwt?.issuer ??\n\t\t\t\t\t\tauthServerBaseUrl;\n\t\t\t\t\tif (!audience) {\n\t\t\t\t\t\tthrow Error(\"please define opts.verifyOptions.audience\");\n\t\t\t\t\t}\n\t\t\t\t\tif (!issuer) {\n\t\t\t\t\t\tthrow Error(\"please define opts.verifyOptions.issuer\");\n\t\t\t\t\t}\n\t\t\t\t\tconst jwksUrl =\n\t\t\t\t\t\topts?.jwksUrl ??\n\t\t\t\t\t\tjwtPluginOptions?.jwks?.remoteUrl ??\n\t\t\t\t\t\t(authServerBaseUrl\n\t\t\t\t\t\t\t? `${authServerBaseUrl + (authServerBasePath ?? \"\")}${jwtPluginOptions?.jwks?.jwksPath ?? \"/jwks\"}`\n\t\t\t\t\t\t\t: undefined);\n\t\t\t\t\tconst introspectUrl =\n\t\t\t\t\t\topts?.remoteVerify?.introspectUrl ??\n\t\t\t\t\t\t(authServerBaseUrl\n\t\t\t\t\t\t\t? `${authServerBaseUrl}${authServerBasePath ?? \"\"}/oauth2/introspect`\n\t\t\t\t\t\t\t: undefined);\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!token?.length) {\n\t\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\t\t\tmessage: \"missing authorization header\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn await verifyAccessToken(token, {\n\t\t\t\t\t\t\t...opts,\n\t\t\t\t\t\t\tjwksUrl,\n\t\t\t\t\t\t\tverifyOptions: {\n\t\t\t\t\t\t\t\t...opts?.verifyOptions,\n\t\t\t\t\t\t\t\taudience,\n\t\t\t\t\t\t\t\tissuer,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tremoteVerify:\n\t\t\t\t\t\t\t\topts?.remoteVerify && introspectUrl\n\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\t...opts.remoteVerify,\n\t\t\t\t\t\t\t\t\t\t\tintrospectUrl,\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthrow handleMcpErrors(error, audience, {\n\t\t\t\t\t\t\tresourceMetadataMappings: opts?.resourceMetadataMappings,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}) as VerifyAccessTokenOutput<T>,\n\t\t\t\t/**\n\t\t\t\t * An authorization server does not typically publish\n\t\t\t\t * the `/.well-known/oauth-protected-resource` themselves.\n\t\t\t\t * Thus, we provide a client-only endpoint to help set up\n\t\t\t\t * your protected resource metadata.\n\t\t\t\t *\n\t\t\t\t * The optional auth parameter can fill known values automatically.\n\t\t\t\t *\n\t\t\t\t * @see https://datatracker.ietf.org/doc/html/rfc8414#section-2\n\t\t\t\t */\n\t\t\t\tgetProtectedResourceMetadata: (async (\n\t\t\t\t\toverrides: Partial<ResourceServerMetadata> | undefined,\n\t\t\t\t\topts:\n\t\t\t\t\t\t| {\n\t\t\t\t\t\t\t\tsilenceWarnings?: {\n\t\t\t\t\t\t\t\t\toidcScopes?: boolean;\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\texternalScopes?: string[];\n\t\t\t\t\t\t }\n\t\t\t\t\t\t| undefined,\n\t\t\t\t): Promise<ResourceServerMetadata> => {\n\t\t\t\t\tconst resource = overrides?.resource ?? authServerBaseUrl;\n\t\t\t\t\tif (!resource) {\n\t\t\t\t\t\tthrow Error(\"missing required resource\");\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\toauthProviderOptions?.scopes &&\n\t\t\t\t\t\topts?.externalScopes &&\n\t\t\t\t\t\t(overrides?.authorization_servers?.length ?? 0) <= 1\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t\"external scopes should not be provided with one authorization server\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\t// Resource server should not mention specific scopes\n\t\t\t\t\tif (overrides?.scopes_supported) {\n\t\t\t\t\t\tconst allValidScopes = new Set([\n\t\t\t\t\t\t\t...(oauthProviderOptions?.scopes ?? []),\n\t\t\t\t\t\t\t...(opts?.externalScopes ?? []),\n\t\t\t\t\t\t]);\n\t\t\t\t\t\tfor (const sc of overrides.scopes_supported) {\n\t\t\t\t\t\t\tif (sc === \"openid\") {\n\t\t\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t\t\t\"Only the Auth Server should utilize the openid scope\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ([\"profile\", \"email\", \"phone\", \"address\"].includes(sc)) {\n\t\t\t\t\t\t\t\tif (!opts?.silenceWarnings?.oidcScopes) {\n\t\t\t\t\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t\t\t\t\t`\"${sc}\" is typically restricted for the authorization server, a resource server typically shouldn't handle this scope`,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!allValidScopes.has(sc)) {\n\t\t\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t\t\t`Unsupported scope ${sc}. If external, please add to \"externalScopes\"`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst authorizationServer = await getAuthorizationServer();\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tresource,\n\t\t\t\t\t\tauthorization_servers: authorizationServer\n\t\t\t\t\t\t\t? [authorizationServer]\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t...overrides,\n\t\t\t\t\t};\n\t\t\t\t}) as ProtectedResourceMetadataOutput<T>,\n\t\t\t};\n\t\t},\n\t} satisfies BetterAuthClientPlugin;\n};\n\nexport interface VerifyAccessTokenRemote {\n\t/** Full url of the introspect endpoint. Should end with `/oauth2/introspect` */\n\tintrospectUrl: string;\n\t/** Client Secret */\n\tclientId: string;\n\t/** Client Secret */\n\tclientSecret: string;\n\t/**\n\t * Forces remote verification of a token.\n\t * This ensures attached session (if applicable)\n\t * is also still active.\n\t */\n\tforce?: boolean;\n}\n\ntype VerifyAccessTokenOutput<T> = T extends Auth\n\t? (\n\t\t\ttoken: string | undefined,\n\t\t\topts?: VerifyAccessTokenAuthOpts,\n\t\t) => Promise<JWTPayload>\n\t: (\n\t\t\ttoken: string | undefined,\n\t\t\topts: VerifyAccessTokenNoAuthOpts,\n\t\t) => Promise<JWTPayload>;\ntype VerifyAccessTokenAuthOpts = {\n\tverifyOptions?: JWTVerifyOptions &\n\t\tRequired<Pick<JWTVerifyOptions, \"audience\">>;\n\tscopes?: string[];\n\tjwksUrl?: string;\n\tremoteVerify?: VerifyAccessTokenRemote;\n\t/** Maps non-url (ie urn, client) resources to resource_metadata */\n\tresourceMetadataMappings?: Record<string, string>;\n};\ntype VerifyAccessTokenNoAuthOpts =\n\t| {\n\t\t\tverifyOptions: JWTVerifyOptions &\n\t\t\t\tRequired<Pick<JWTVerifyOptions, \"audience\" | \"issuer\">>;\n\t\t\tscopes?: string[];\n\t\t\tjwksUrl: string;\n\t\t\tremoteVerify?: VerifyAccessTokenRemote;\n\t\t\t/** Maps non-url (ie urn, client) resources to resource_metadata */\n\t\t\tresourceMetadataMappings?: Record<string, string>;\n\t }\n\t| {\n\t\t\tverifyOptions: JWTVerifyOptions &\n\t\t\t\tRequired<Pick<JWTVerifyOptions, \"audience\" | \"issuer\">>;\n\t\t\tscopes?: string[];\n\t\t\tjwksUrl?: string;\n\t\t\tremoteVerify: VerifyAccessTokenRemote;\n\t\t\t/** Maps non-url (ie urn, client) resources to resource_metadata */\n\t\t\tresourceMetadataMappings?: Record<string, string>;\n\t };\n\ntype ProtectedResourceMetadataOutput<T> = T extends Auth\n\t? (\n\t\t\toverrides?: Partial<ResourceServerMetadata>,\n\t\t\topts?: {\n\t\t\t\tsilenceWarnings?: {\n\t\t\t\t\toidcScopes?: boolean;\n\t\t\t\t};\n\t\t\t\texternalScopes?: string[];\n\t\t\t},\n\t\t) => Promise<ResourceServerMetadata>\n\t: (\n\t\t\toverrides: ResourceServerMetadata,\n\t\t\topts?: {\n\t\t\t\tsilenceWarnings?: {\n\t\t\t\t\toidcScopes?: boolean;\n\t\t\t\t};\n\t\t\t\texternalScopes?: string[];\n\t\t\t},\n\t\t) => Promise<ResourceServerMetadata>;\n"],"mappings":";;;;;;;AAUA,MAAa,+BACZ,SACI;CAEJ,MAAM,wBADsB,OAAO,uBAAuB,KAAK,GAAG,SAChB;CAClD,IAAIA;CACJ,MAAM,sBAAsB,YAAY;AACvC,MAAI,CAAC,UACJ,aACC,QAAQ,CAAC,sBAAsB,mBAC5B,aAAa,MAAM,KAAK,SAAS,GACjC;AAEL,SAAO,WAAW;;CAEnB,MAAM,yBAAyB,YAAY;AAE1C,UADyB,MAAM,qBAAqB,GAC3B,KAAK,UAAU;;CAEzC,MAAM,oBAAoB,MAAM,QAAQ;CACxC,MAAM,qBAAqB,MAAM,QAAQ;AAEzC,QAAO;EACN,IAAI;EACJ,aAAa;AACZ,UAAO;IASN,oBAAoB,OACnB,OACA,SASyB;KACzB,MAAM,mBAAmB,MAAM,qBAAqB;KACpD,MAAM,WAAW,MAAM,eAAe,YAAY;KAClD,MAAM,SACL,MAAM,eAAe,UACrB,kBAAkB,KAAK,UACvB;AACD,SAAI,CAAC,SACJ,OAAM,MAAM,4CAA4C;AAEzD,SAAI,CAAC,OACJ,OAAM,MAAM,0CAA0C;KAEvD,MAAM,UACL,MAAM,WACN,kBAAkB,MAAM,cACvB,oBACE,GAAG,qBAAqB,sBAAsB,MAAM,kBAAkB,MAAM,YAAY,YACxF;KACJ,MAAM,gBACL,MAAM,cAAc,kBACnB,oBACE,GAAG,oBAAoB,sBAAsB,GAAG,sBAChD;AAEJ,SAAI;AACH,UAAI,CAAC,OAAO,OACX,OAAM,IAAI,SAAS,gBAAgB,EAClC,SAAS,gCACT,CAAC;AAEH,aAAO,MAAM,kBAAkB,OAAO;OACrC,GAAG;OACH;OACA,eAAe;QACd,GAAG,MAAM;QACT;QACA;QACA;OACD,cACC,MAAM,gBAAgB,gBACnB;QACA,GAAG,KAAK;QACR;QACA,GACA;OACJ,CAAC;cACM,OAAO;AACf,YAAM,gBAAgB,OAAO,UAAU,EACtC,0BAA0B,MAAM,0BAChC,CAAC;;;IAaJ,+BAA+B,OAC9B,WACA,SAQqC;KACrC,MAAM,WAAW,WAAW,YAAY;AACxC,SAAI,CAAC,SACJ,OAAM,MAAM,4BAA4B;AAEzC,SACC,sBAAsB,UACtB,MAAM,mBACL,WAAW,uBAAuB,UAAU,MAAM,EAEnD,OAAM,IAAI,gBACT,uEACA;AAGF,SAAI,WAAW,kBAAkB;MAChC,MAAM,iBAAiB,IAAI,IAAI,CAC9B,GAAI,sBAAsB,UAAU,EAAE,EACtC,GAAI,MAAM,kBAAkB,EAAE,CAC9B,CAAC;AACF,WAAK,MAAM,MAAM,UAAU,kBAAkB;AAC5C,WAAI,OAAO,SACV,OAAM,IAAI,gBACT,uDACA;AAEF,WAAI;QAAC;QAAW;QAAS;QAAS;QAAU,CAAC,SAAS,GAAG,EACxD;YAAI,CAAC,MAAM,iBAAiB,WAC3B,QAAO,KACN,IAAI,GAAG,iHACP;;AAGH,WAAI,CAAC,eAAe,IAAI,GAAG,CAC1B,OAAM,IAAI,gBACT,qBAAqB,GAAG,+CACxB;;;KAKJ,MAAM,sBAAsB,MAAM,wBAAwB;AAE1D,YAAO;MACN;MACA,uBAAuB,sBACpB,CAAC,oBAAoB,GACrB;MACH,GAAG;MACH;;IAEF;;EAEF"}
package/dist/client.d.mts CHANGED
@@ -16,4 +16,5 @@ declare const oauthProviderClient: () => {
16
16
  $InferServerPlugin: ReturnType<typeof oauthProvider>;
17
17
  };
18
18
  //#endregion
19
- export { oauthProviderClient };
19
+ export { oauthProviderClient };
20
+ //# sourceMappingURL=client.d.mts.map
package/dist/client.mjs CHANGED
@@ -35,4 +35,5 @@ const oauthProviderClient = () => {
35
35
  };
36
36
 
37
37
  //#endregion
38
- export { oauthProviderClient };
38
+ export { oauthProviderClient };
39
+ //# sourceMappingURL=client.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.mjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import { safeJSONParse } from \"@better-auth/core/utils\";\nimport type { BetterAuthClientPlugin } from \"better-auth/types\";\nimport type { oauthProvider } from \"./oauth\";\n\nfunction parseSignedQuery(search: string) {\n\tconst params = new URLSearchParams(search);\n\tif (params.has(\"sig\")) {\n\t\tconst signedParams = new URLSearchParams();\n\t\tfor (const [key, value] of params.entries()) {\n\t\t\tsignedParams.append(key, value);\n\t\t\tif (key === \"sig\") break;\n\t\t}\n\t\treturn signedParams.toString();\n\t}\n}\n\nexport const oauthProviderClient = () => {\n\treturn {\n\t\tid: \"oauth-provider-client\",\n\t\tfetchPlugins: [\n\t\t\t{\n\t\t\t\tid: \"oauth-provider-signin\",\n\t\t\t\tname: \"oauth-provider-signin\",\n\t\t\t\tdescription: \"Adds the current page query to oauth requests\",\n\t\t\t\thooks: {\n\t\t\t\t\tasync onRequest(ctx) {\n\t\t\t\t\t\tconst headers = ctx.headers;\n\t\t\t\t\t\tconst body =\n\t\t\t\t\t\t\ttypeof ctx.body === \"string\"\n\t\t\t\t\t\t\t\t? headers.get(\"content-type\") ===\n\t\t\t\t\t\t\t\t\t\"application/x-www-form-urlencoded\"\n\t\t\t\t\t\t\t\t\t? Object.fromEntries(new URLSearchParams(ctx.body))\n\t\t\t\t\t\t\t\t\t: safeJSONParse<Record<string, unknown>>(ctx.body ?? \"{}\")\n\t\t\t\t\t\t\t\t: ctx.body;\n\t\t\t\t\t\tif (body?.oauth_query) return;\n\t\t\t\t\t\tconst pathname =\n\t\t\t\t\t\t\ttypeof ctx.url === \"string\"\n\t\t\t\t\t\t\t\t? new URL(ctx.url).pathname\n\t\t\t\t\t\t\t\t: ctx.url.pathname;\n\t\t\t\t\t\t// Should only need to run for /sign-in/email, /sign-in/social, /sign-in/oauth2, /oauth2/consent, /oauth2/continue\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tpathname.endsWith(\"/sign-in/email\") ||\n\t\t\t\t\t\t\tpathname.endsWith(\"/sign-in/social\") ||\n\t\t\t\t\t\t\tpathname.endsWith(\"/sign-in/oauth2\") ||\n\t\t\t\t\t\t\tpathname.endsWith(\"/oauth2/consent\") ||\n\t\t\t\t\t\t\tpathname.endsWith(\"/oauth2/continue\")\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tctx.body = JSON.stringify({\n\t\t\t\t\t\t\t\t...body,\n\t\t\t\t\t\t\t\toauth_query:\n\t\t\t\t\t\t\t\t\ttypeof window !== \"undefined\"\n\t\t\t\t\t\t\t\t\t\t? parseSignedQuery(window?.location?.search)\n\t\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\t$InferServerPlugin: {} as ReturnType<typeof oauthProvider>,\n\t} satisfies BetterAuthClientPlugin;\n};\n"],"mappings":";;;AAIA,SAAS,iBAAiB,QAAgB;CACzC,MAAM,SAAS,IAAI,gBAAgB,OAAO;AAC1C,KAAI,OAAO,IAAI,MAAM,EAAE;EACtB,MAAM,eAAe,IAAI,iBAAiB;AAC1C,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,SAAS,EAAE;AAC5C,gBAAa,OAAO,KAAK,MAAM;AAC/B,OAAI,QAAQ,MAAO;;AAEpB,SAAO,aAAa,UAAU;;;AAIhC,MAAa,4BAA4B;AACxC,QAAO;EACN,IAAI;EACJ,cAAc,CACb;GACC,IAAI;GACJ,MAAM;GACN,aAAa;GACb,OAAO,EACN,MAAM,UAAU,KAAK;IACpB,MAAM,UAAU,IAAI;IACpB,MAAM,OACL,OAAO,IAAI,SAAS,WACjB,QAAQ,IAAI,eAAe,KAC5B,sCACE,OAAO,YAAY,IAAI,gBAAgB,IAAI,KAAK,CAAC,GACjD,cAAuC,IAAI,QAAQ,KAAK,GACzD,IAAI;AACR,QAAI,MAAM,YAAa;IACvB,MAAM,WACL,OAAO,IAAI,QAAQ,WAChB,IAAI,IAAI,IAAI,IAAI,CAAC,WACjB,IAAI,IAAI;AAEZ,QACC,SAAS,SAAS,iBAAiB,IACnC,SAAS,SAAS,kBAAkB,IACpC,SAAS,SAAS,kBAAkB,IACpC,SAAS,SAAS,kBAAkB,IACpC,SAAS,SAAS,mBAAmB,CAErC,KAAI,OAAO,KAAK,UAAU;KACzB,GAAG;KACH,aACC,OAAO,WAAW,cACf,iBAAiB,QAAQ,UAAU,OAAO,GAC1C;KACJ,CAAC;MAGJ;GACD,CACD;EACD,oBAAoB,EAAE;EACtB"}
package/dist/index.d.mts CHANGED
@@ -62,4 +62,5 @@ declare const oauthProviderOpenIdConfigMetadata: <Auth extends {
62
62
  headers?: HeadersInit;
63
63
  }) => (_request: Request) => Promise<Response>;
64
64
  //#endregion
65
- export { AuthServerMetadata, AuthorizePrompt, OAuthAuthorizationQuery, OAuthClient, OAuthConsent, OAuthOpaqueAccessToken, OAuthOptions, OAuthRefreshToken, OIDCMetadata, Prompt, ResourceServerMetadata, SchemaClient, Scope, StoreTokenType, VerificationValue, authServerMetadata, mcpHandler, oauthProvider, oauthProviderAuthServerMetadata, oauthProviderOpenIdConfigMetadata, oidcServerMetadata };
65
+ export { AuthServerMetadata, AuthorizePrompt, OAuthAuthorizationQuery, OAuthClient, OAuthConsent, OAuthOpaqueAccessToken, OAuthOptions, OAuthRefreshToken, OIDCMetadata, Prompt, ResourceServerMetadata, SchemaClient, Scope, StoreTokenType, VerificationValue, authServerMetadata, mcpHandler, oauthProvider, oauthProviderAuthServerMetadata, oauthProviderOpenIdConfigMetadata, oidcServerMetadata };
66
+ //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as getJwtPlugin, c as parsePrompt, d as validateClientCredentials, i as getClient, l as storeClientSecret, n as decryptStoredClientSecret, p as mcpHandler, r as deleteFromPrompt, s as getStoredToken, t as basicToClientCredentials, u as storeToken } from "./utils-LksXOM6z.mjs";
1
+ import { a as getJwtPlugin, c as parseClientMetadata, d as storeToken, f as validateClientCredentials, i as getClient, l as parsePrompt, m as mcpHandler, n as decryptStoredClientSecret, r as deleteFromPrompt, s as getStoredToken, t as basicToClientCredentials, u as storeClientSecret } from "./utils-DnfreTWo.mjs";
2
2
  import { generateCodeChallenge, getJwks, verifyJwsAccessToken } from "better-auth/oauth2";
3
3
  import { APIError } from "better-call";
4
4
  import { BetterAuthError } from "@better-auth/core/error";
@@ -516,7 +516,7 @@ async function createJwtAccessToken(ctx, opts, user, client, audience, scopes, r
516
516
  scopes,
517
517
  resource: ctx.body.resource,
518
518
  referenceId,
519
- metadata: client.metadata ? JSON.parse(client.metadata) : void 0
519
+ metadata: parseClientMetadata(client.metadata)
520
520
  }) : {};
521
521
  const jwtPluginOptions = getJwtPlugin(ctx.context).options;
522
522
  return signJWT(ctx, {
@@ -547,7 +547,7 @@ async function createIdToken(ctx, opts, user, client, scopes, nonce, sessionId)
547
547
  const customClaims = opts.customIdTokenClaims ? await opts.customIdTokenClaims({
548
548
  user,
549
549
  scopes,
550
- metadata: client.metadata ? JSON.parse(client.metadata) : void 0
550
+ metadata: parseClientMetadata(client.metadata)
551
551
  }) : {};
552
552
  const jwtPluginOptions = opts.disableJwtPlugin ? void 0 : getJwtPlugin(ctx.context).options;
553
553
  const payload = {
@@ -857,7 +857,7 @@ async function handleClientCredentialsGrant(ctx, opts) {
857
857
  const customClaims = opts.customAccessTokenClaims ? await opts.customAccessTokenClaims({
858
858
  scopes: requestedScopes,
859
859
  resource: ctx.body.resource,
860
- metadata: client.metadata ? JSON.parse(client.metadata) : void 0
860
+ metadata: parseClientMetadata(client.metadata)
861
861
  }) : {};
862
862
  const accessToken = audience && !opts.disableJwtPlugin ? await signJWT(ctx, {
863
863
  options: jwtPluginOptions,
@@ -1069,7 +1069,7 @@ async function validateOpaqueAccessToken(ctx, opts, token, clientId) {
1069
1069
  user,
1070
1070
  scopes: accessToken.scopes,
1071
1071
  referenceId: accessToken?.referenceId,
1072
- metadata: client?.metadata ? JSON.parse(client.metadata) : void 0
1072
+ metadata: parseClientMetadata(client?.metadata)
1073
1073
  }) : {};
1074
1074
  const jwtPluginOptions = (opts.disableJwtPlugin ? void 0 : getJwtPlugin(ctx.context))?.options;
1075
1075
  return {
@@ -1420,14 +1420,19 @@ async function createOAuthClientEndpoint(ctx, opts, settings) {
1420
1420
  * @returns
1421
1421
  */
1422
1422
  function oauthToSchema(input) {
1423
- const { client_id: clientId, client_secret: clientSecret, client_secret_expires_at: _expiresAt, scope: _scope, user_id: userId, client_id_issued_at: _createdAt, client_name: name, client_uri: uri, logo_uri: icon, contacts, tos_uri: tos, policy_uri: policy, jwks: _jwks, jwks_uri: _jwksUri, software_id: softwareId, software_version: softwareVersion, software_statement: softwareStatement, redirect_uris: redirectUris, post_logout_redirect_uris: postLogoutRedirectUris, token_endpoint_auth_method: tokenEndpointAuthMethod, grant_types: grantTypes, response_types: responseTypes, public: _public, type, disabled, skip_consent: skipConsent, enable_end_session: enableEndSession, reference_id: referenceId, ...rest } = input;
1423
+ const { client_id: clientId, client_secret: clientSecret, client_secret_expires_at: _expiresAt, scope: _scope, user_id: userId, client_id_issued_at: _createdAt, client_name: name, client_uri: uri, logo_uri: icon, contacts, tos_uri: tos, policy_uri: policy, jwks: _jwks, jwks_uri: _jwksUri, software_id: softwareId, software_version: softwareVersion, software_statement: softwareStatement, redirect_uris: redirectUris, post_logout_redirect_uris: postLogoutRedirectUris, token_endpoint_auth_method: tokenEndpointAuthMethod, grant_types: grantTypes, response_types: responseTypes, public: _public, type, disabled, skip_consent: skipConsent, enable_end_session: enableEndSession, reference_id: referenceId, metadata: inputMetadata, ...rest } = input;
1424
1424
  const expiresAt = _expiresAt ? /* @__PURE__ */ new Date(_expiresAt * 1e3) : void 0;
1425
1425
  const createdAt = _createdAt ? /* @__PURE__ */ new Date(_createdAt * 1e3) : void 0;
1426
+ const scopes = _scope?.split(" ");
1427
+ const metadataObj = {
1428
+ ...rest && Object.keys(rest).length ? rest : {},
1429
+ ...inputMetadata && typeof inputMetadata === "object" ? inputMetadata : {}
1430
+ };
1426
1431
  return {
1427
1432
  clientId,
1428
1433
  clientSecret,
1429
1434
  disabled,
1430
- scopes: _scope?.split(" "),
1435
+ scopes,
1431
1436
  userId,
1432
1437
  createdAt,
1433
1438
  expiresAt,
@@ -1450,7 +1455,7 @@ function oauthToSchema(input) {
1450
1455
  skipConsent,
1451
1456
  enableEndSession,
1452
1457
  referenceId,
1453
- metadata: rest && Object.keys(rest).length ? JSON.stringify(rest) : void 0
1458
+ metadata: Object.keys(metadataObj).length ? JSON.stringify(metadataObj) : void 0
1454
1459
  };
1455
1460
  }
1456
1461
  /**
@@ -1465,7 +1470,7 @@ function schemaToOAuth(input) {
1465
1470
  const _createdAt = createdAt ? Math.round(createdAt.getTime() / 1e3) : void 0;
1466
1471
  const _scopes = scopes?.join(" ");
1467
1472
  return {
1468
- ...metadata ? JSON.parse(metadata) : void 0,
1473
+ ...parseClientMetadata(metadata),
1469
1474
  client_id: clientId,
1470
1475
  client_secret: clientSecret ?? void 0,
1471
1476
  client_secret_expires_at: clientSecret ? _expiresAt ?? 0 : void 0,
@@ -1519,9 +1524,9 @@ const SafeUrlSchema = z.url().superRefine((val, ctx) => {
1519
1524
  async function getClientEndpoint(ctx, opts) {
1520
1525
  const session = await getSessionFromCtx(ctx);
1521
1526
  if (!session) throw new APIError$1("UNAUTHORIZED");
1522
- if (!ctx.request) throw new APIError$1("BAD_REQUEST");
1527
+ if (!ctx.headers) throw new APIError$1("BAD_REQUEST");
1523
1528
  if (opts.clientPrivileges && !await opts.clientPrivileges({
1524
- headers: ctx.request.headers,
1529
+ headers: ctx.headers,
1525
1530
  action: "read",
1526
1531
  session: session.session,
1527
1532
  user: session.user
@@ -1567,9 +1572,9 @@ async function getClientPublicEndpoint(ctx, opts) {
1567
1572
  async function getClientsEndpoint(ctx, opts) {
1568
1573
  const session = await getSessionFromCtx(ctx);
1569
1574
  if (!session) throw new APIError$1("UNAUTHORIZED");
1570
- if (!ctx.request) throw new APIError$1("BAD_REQUEST");
1575
+ if (!ctx.headers) throw new APIError$1("BAD_REQUEST");
1571
1576
  if (opts.clientPrivileges && !await opts.clientPrivileges({
1572
- headers: ctx.request.headers,
1577
+ headers: ctx.headers,
1573
1578
  action: "list",
1574
1579
  session: session.session,
1575
1580
  user: session.user
@@ -1608,9 +1613,9 @@ async function getClientsEndpoint(ctx, opts) {
1608
1613
  async function deleteClientEndpoint(ctx, opts) {
1609
1614
  const session = await getSessionFromCtx(ctx);
1610
1615
  if (!session) throw new APIError$1("UNAUTHORIZED");
1611
- if (!ctx.request) throw new APIError$1("BAD_REQUEST");
1616
+ if (!ctx.headers) throw new APIError$1("BAD_REQUEST");
1612
1617
  if (opts.clientPrivileges && !await opts.clientPrivileges({
1613
- headers: ctx.request.headers,
1618
+ headers: ctx.headers,
1614
1619
  action: "delete",
1615
1620
  session: session.session,
1616
1621
  user: session.user
@@ -1641,9 +1646,9 @@ async function deleteClientEndpoint(ctx, opts) {
1641
1646
  async function updateClientEndpoint(ctx, opts) {
1642
1647
  const session = await getSessionFromCtx(ctx);
1643
1648
  if (!session) throw new APIError$1("UNAUTHORIZED");
1644
- if (!ctx.request) throw new APIError$1("BAD_REQUEST");
1649
+ if (!ctx.headers) throw new APIError$1("BAD_REQUEST");
1645
1650
  if (opts.clientPrivileges && !await opts.clientPrivileges({
1646
- headers: ctx.request.headers,
1651
+ headers: ctx.headers,
1647
1652
  action: "update",
1648
1653
  session: session.session,
1649
1654
  user: session.user
@@ -1692,9 +1697,9 @@ async function updateClientEndpoint(ctx, opts) {
1692
1697
  async function rotateClientSecretEndpoint(ctx, opts) {
1693
1698
  const session = await getSessionFromCtx(ctx);
1694
1699
  if (!session) throw new APIError$1("UNAUTHORIZED");
1695
- if (!ctx.request) throw new APIError$1("BAD_REQUEST");
1700
+ if (!ctx.headers) throw new APIError$1("BAD_REQUEST");
1696
1701
  if (opts.clientPrivileges && !await opts.clientPrivileges({
1697
- headers: ctx.request.headers,
1702
+ headers: ctx.headers,
1698
1703
  action: "rotate",
1699
1704
  session: session.session,
1700
1705
  user: session.user
@@ -3715,4 +3720,5 @@ const oauthProvider = (options) => {
3715
3720
  };
3716
3721
 
3717
3722
  //#endregion
3718
- export { authServerMetadata, mcpHandler, oauthProvider, oauthProviderAuthServerMetadata, oauthProviderOpenIdConfigMetadata, oidcServerMetadata };
3723
+ export { authServerMetadata, mcpHandler, oauthProvider, oauthProviderAuthServerMetadata, oauthProviderOpenIdConfigMetadata, oidcServerMetadata };
3724
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["query: OAuthAuthorizationQuery","data: Omit<Verification, \"id\" | \"createdAt\">","APIError","consent: Omit<OAuthConsent<Scope[]>, \"id\">","APIError","APIError","grantType: GrantType | undefined","APIError","payload: JWTPayload","resource: string | string[] | undefined","verificationValue: VerificationValue","scope","jwtPayload: JWTPayload & {\n\t\tsid?: string;\n\t\tazp?: string;\n\t}","client: SchemaClient<Scope[]> | null | undefined","user: User | null | undefined","sessionId: string | undefined","user: User | undefined","decoded: JWTPayload","idTokenPayload: JWTPayload | undefined","APIError","schema","APIError","res","APIError","accessToken:\n\t\t| (OAuthOpaqueAccessToken<Scope[]> & { id?: string })\n\t\t| null","opts: O & { claims?: string[] }","APIError","oauthClientEndpoints.adminCreateOAuthClient","oauthClientEndpoints.createOAuthClient","oauthClientEndpoints.getOAuthClient","oauthClientEndpoints.getOAuthClientPublic","oauthClientEndpoints.getOAuthClients","oauthClientEndpoints.adminUpdateOAuthClient","oauthClientEndpoints.updateOAuthClient","oauthClientEndpoints.rotateClientSecret","oauthClientEndpoints.deleteOAuthClient","oauthConsentEndpoints.getOAuthConsent","oauthConsentEndpoints.getOAuthConsents","oauthConsentEndpoints.updateOAuthConsent","oauthConsentEndpoints.deleteOAuthConsent"],"sources":["../src/metadata.ts","../src/authorize.ts","../src/consent.ts","../src/continue.ts","../src/userinfo.ts","../src/token.ts","../src/introspect.ts","../src/logout.ts","../src/register.ts","../src/types/zod.ts","../src/oauthClient/endpoints.ts","../src/oauthClient/index.ts","../src/oauthConsent/endpoints.ts","../src/oauthConsent/index.ts","../src/revoke.ts","../src/schema.ts","../src/oauth.ts"],"sourcesContent":["import type { GenericEndpointContext } from \"@better-auth/core\";\nimport type { JWSAlgorithms, JwtOptions } from \"better-auth/plugins\";\nimport type { OAuthOptions, Scope } from \"./types\";\nimport type {\n\tAuthServerMetadata,\n\tGrantType,\n\tOIDCMetadata,\n\tTokenEndpointAuthMethod,\n} from \"./types/oauth\";\nimport { getJwtPlugin } from \"./utils\";\n\nexport function authServerMetadata(\n\tctx: GenericEndpointContext,\n\topts?: JwtOptions,\n\toverrides?: {\n\t\tscopes_supported?: AuthServerMetadata[\"scopes_supported\"];\n\t\tpublic_client_supported?: boolean;\n\t\tgrant_types_supported?: GrantType[];\n\t\tjwt_disabled?: boolean;\n\t},\n) {\n\tconst baseURL = ctx.context.baseURL;\n\tconst metadata: AuthServerMetadata = {\n\t\tscopes_supported: overrides?.scopes_supported,\n\t\tissuer: opts?.jwt?.issuer ?? baseURL,\n\t\tauthorization_endpoint: `${baseURL}/oauth2/authorize`,\n\t\ttoken_endpoint: `${baseURL}/oauth2/token`,\n\t\tjwks_uri: overrides?.jwt_disabled\n\t\t\t? undefined\n\t\t\t: (opts?.jwks?.remoteUrl ??\n\t\t\t\t`${baseURL}${opts?.jwks?.jwksPath ?? \"/jwks\"}`),\n\t\tregistration_endpoint: `${baseURL}/oauth2/register`,\n\t\tintrospection_endpoint: `${baseURL}/oauth2/introspect`,\n\t\trevocation_endpoint: `${baseURL}/oauth2/revoke`,\n\t\tresponse_types_supported:\n\t\t\toverrides?.grant_types_supported &&\n\t\t\t!overrides.grant_types_supported.includes(\"authorization_code\")\n\t\t\t\t? []\n\t\t\t\t: [\"code\"],\n\t\tresponse_modes_supported: [\"query\"],\n\t\tgrant_types_supported: overrides?.grant_types_supported ?? [\n\t\t\t\"authorization_code\",\n\t\t\t\"client_credentials\",\n\t\t\t\"refresh_token\",\n\t\t],\n\t\ttoken_endpoint_auth_methods_supported: [\n\t\t\t...(overrides?.public_client_supported\n\t\t\t\t? ([\"none\"] satisfies TokenEndpointAuthMethod[])\n\t\t\t\t: []),\n\t\t\t\"client_secret_basic\",\n\t\t\t\"client_secret_post\",\n\t\t],\n\t\tintrospection_endpoint_auth_methods_supported: [\n\t\t\t\"client_secret_basic\",\n\t\t\t\"client_secret_post\",\n\t\t],\n\t\trevocation_endpoint_auth_methods_supported: [\n\t\t\t\"client_secret_basic\",\n\t\t\t\"client_secret_post\",\n\t\t],\n\t\tcode_challenge_methods_supported: [\"S256\"],\n\t};\n\treturn metadata;\n}\n\nexport function oidcServerMetadata(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]> & { claims?: string[] },\n) {\n\tconst baseURL = ctx.context.baseURL;\n\tconst jwtPluginOptions = opts.disableJwtPlugin\n\t\t? undefined\n\t\t: getJwtPlugin(ctx.context).options;\n\tconst authMetadata = authServerMetadata(ctx, jwtPluginOptions, {\n\t\tscopes_supported: opts.advertisedMetadata?.scopes_supported ?? opts.scopes,\n\t\tpublic_client_supported: opts.allowUnauthenticatedClientRegistration,\n\t\tgrant_types_supported: opts.grantTypes,\n\t\tjwt_disabled: opts.disableJwtPlugin,\n\t});\n\tconst metadata: Omit<\n\t\tOIDCMetadata,\n\t\t\"id_token_signing_alg_values_supported\"\n\t> & {\n\t\tid_token_signing_alg_values_supported: JWSAlgorithms[] | [\"HS256\"];\n\t} = {\n\t\t...authMetadata,\n\t\tclaims_supported:\n\t\t\topts?.advertisedMetadata?.claims_supported ?? opts?.claims ?? [],\n\t\tuserinfo_endpoint: `${baseURL}/oauth2/userinfo`,\n\t\tsubject_types_supported: [\"public\"],\n\t\tid_token_signing_alg_values_supported: jwtPluginOptions?.jwks?.keyPairConfig\n\t\t\t?.alg\n\t\t\t? [jwtPluginOptions?.jwks?.keyPairConfig?.alg]\n\t\t\t: opts.disableJwtPlugin\n\t\t\t\t? [\"HS256\"]\n\t\t\t\t: [\"EdDSA\"],\n\t\tend_session_endpoint: `${baseURL}/oauth2/end-session`,\n\t\tacr_values_supported: [\"urn:mace:incommon:iap:bronze\"],\n\t\tprompt_values_supported: [\"login\", \"consent\", \"create\", \"select_account\"],\n\t};\n\treturn metadata;\n}\n\n/**\n * Provides an exportable `/.well-known/oauth-authorization-server`.\n *\n * Useful when basePath prevents the endpoint from being located at the root\n * and must be provided manually.\n *\n * @external\n */\nexport const oauthProviderAuthServerMetadata = <\n\tAuth extends {\n\t\tapi: {\n\t\t\tgetOAuthServerConfig: (...args: any) => any;\n\t\t};\n\t},\n>(\n\tauth: Auth,\n\topts?: {\n\t\theaders?: HeadersInit;\n\t},\n) => {\n\treturn async (_request: Request) => {\n\t\tconst res = await auth.api.getOAuthServerConfig();\n\t\treturn new Response(JSON.stringify(res), {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t// We should cache here because it is unlikely this will\n\t\t\t\t// change frequently and if it does shouldn't be more than\n\t\t\t\t// for 15 seconds in a change period\n\t\t\t\t\"Cache-Control\":\n\t\t\t\t\t\"public, max-age=15, stale-while-revalidate=15, stale-if-error=86400\", // 15 sec\n\t\t\t\t...opts?.headers,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t});\n\t};\n};\n\n/**\n * Provides an exportable `/.well-known/openid-configuration`.\n *\n * Useful when basePath prevents the endpoint from being located at the root\n * and must be provided manually.\n *\n * @external\n */\nexport const oauthProviderOpenIdConfigMetadata = <\n\tAuth extends {\n\t\tapi: {\n\t\t\tgetOpenIdConfig: (...args: any) => any;\n\t\t};\n\t},\n>(\n\tauth: Auth,\n\topts?: {\n\t\theaders?: HeadersInit;\n\t},\n) => {\n\treturn async (_request: Request) => {\n\t\tconst res = await auth.api.getOpenIdConfig();\n\t\treturn new Response(JSON.stringify(res), {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t// We should cache here because it is unlikely this will\n\t\t\t\t// change frequently and if it does shouldn't be more than\n\t\t\t\t// for 15 seconds in a change period\n\t\t\t\t\"Cache-Control\":\n\t\t\t\t\t\"public, max-age=15, stale-while-revalidate=15, stale-if-error=86400\", // 15 sec\n\t\t\t\t...opts?.headers,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t});\n\t};\n};\n","import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { getSessionFromCtx } from \"better-auth/api\";\nimport { generateRandomString, makeSignature } from \"better-auth/crypto\";\nimport type { Verification } from \"better-auth/db\";\nimport { APIError } from \"better-call\";\nimport type {\n\tOAuthAuthorizationQuery,\n\tOAuthConsent,\n\tOAuthOptions,\n\tScope,\n\tVerificationValue,\n} from \"./types\";\nimport { getClient, parsePrompt, storeToken } from \"./utils\";\n\n/**\n * Formats an error url\n */\nexport function formatErrorURL(\n\turl: string,\n\terror: string,\n\tdescription: string,\n\tstate?: string,\n) {\n\tconst searchParams = new URLSearchParams({\n\t\terror,\n\t\terror_description: description,\n\t});\n\tstate && searchParams.append(\"state\", state);\n\treturn `${url}${url.includes(\"?\") ? \"&\" : \"?\"}${searchParams.toString()}`;\n}\n\nexport const handleRedirect = (ctx: GenericEndpointContext, uri: string) => {\n\tconst acceptJson = ctx.headers?.get(\"accept\")?.includes(\"application/json\");\n\tif (acceptJson) {\n\t\treturn {\n\t\t\tredirect: true,\n\t\t\turl: uri.toString(),\n\t\t};\n\t} else {\n\t\tthrow ctx.redirect(uri);\n\t}\n};\n\n/**\n * Error page url if redirect_uri has not been verified yet\n * Generates Url for custom error page\n */\nfunction getErrorURL(\n\tctx: GenericEndpointContext,\n\terror: string,\n\tdescription: string,\n) {\n\tconst baseURL =\n\t\tctx.context.options.onAPIError?.errorURL || `${ctx.context.baseURL}/error`;\n\tconst formattedURL = formatErrorURL(baseURL, error, description);\n\treturn formattedURL;\n}\n\nexport async function authorizeEndpoint(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\tsettings?: {\n\t\tisAuthorize?: boolean;\n\t\tpostLogin?: boolean;\n\t},\n) {\n\t// Grant type must include authorization_code to use this endpoint\n\tif (opts.grantTypes && !opts.grantTypes.includes(\"authorization_code\")) {\n\t\tthrow new APIError(\"NOT_FOUND\");\n\t}\n\n\tif (!ctx.request) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"request not found\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\t// Check request\n\tconst query: OAuthAuthorizationQuery = ctx.query;\n\tif (!query.client_id) {\n\t\tthrow ctx.redirect(\n\t\t\tgetErrorURL(ctx, \"invalid_client\", \"client_id is required\"),\n\t\t);\n\t}\n\n\tif (!query.response_type) {\n\t\tthrow ctx.redirect(\n\t\t\tgetErrorURL(ctx, \"invalid_request\", \"response_type is required\"),\n\t\t);\n\t}\n\n\tconst promptSet = ctx.query?.prompt\n\t\t? parsePrompt(ctx.query?.prompt)\n\t\t: undefined;\n\tif (promptSet?.has(\"select_account\") && !opts.selectAccount?.page) {\n\t\tthrow ctx.redirect(\n\t\t\tgetErrorURL(\n\t\t\t\tctx,\n\t\t\t\t`unsupported_prompt_select_account`,\n\t\t\t\t\"unsupported prompt type\",\n\t\t\t),\n\t\t);\n\t}\n\n\tif (!(query.response_type === \"code\")) {\n\t\tthrow ctx.redirect(\n\t\t\tgetErrorURL(\n\t\t\t\tctx,\n\t\t\t\t\"unsupported_response_type\",\n\t\t\t\t\"unsupported response type\",\n\t\t\t),\n\t\t);\n\t}\n\n\t// Check client\n\tconst client = await getClient(ctx, opts, query.client_id);\n\tif (!client) {\n\t\tthrow ctx.redirect(\n\t\t\tgetErrorURL(ctx, \"invalid_client\", \"client_id is required\"),\n\t\t);\n\t}\n\tif (client.disabled) {\n\t\tthrow ctx.redirect(\n\t\t\tgetErrorURL(ctx, \"client_disabled\", \"client is disabled\"),\n\t\t);\n\t}\n\n\tconst redirectUri = client.redirectUris?.find(\n\t\t(url) => url === query.redirect_uri,\n\t);\n\tif (!redirectUri || !query.redirect_uri) {\n\t\tthrow ctx.redirect(\n\t\t\tgetErrorURL(ctx, \"invalid_redirect\", \"invalid redirect uri\"),\n\t\t);\n\t}\n\n\t// Check for invalid scopes if requested from query\n\tlet requestedScopes = query.scope?.split(\" \").filter((s) => s);\n\tif (requestedScopes) {\n\t\tconst validScopes = new Set(client.scopes ?? opts.scopes);\n\t\tconst invalidScopes = requestedScopes.filter((scope) => {\n\t\t\treturn (\n\t\t\t\t!validScopes?.has(scope) ||\n\t\t\t\t// offline access must be requested through PKCE\n\t\t\t\t(scope === \"offline_access\" &&\n\t\t\t\t\t(query.code_challenge_method !== \"S256\" || !query.code_challenge))\n\t\t\t);\n\t\t});\n\t\tif (invalidScopes.length) {\n\t\t\tthrow ctx.redirect(\n\t\t\t\tformatErrorURL(\n\t\t\t\t\tquery.redirect_uri,\n\t\t\t\t\t\"invalid_scope\",\n\t\t\t\t\t`The following scopes are invalid: ${invalidScopes.join(\", \")}`,\n\t\t\t\t\tquery.state,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\t// Always set default scopes if not originally sent\n\tif (!requestedScopes) {\n\t\trequestedScopes = client.scopes ?? opts.scopes ?? [];\n\t\tquery.scope = requestedScopes.join(\" \");\n\t}\n\n\tif (!query.code_challenge || !query.code_challenge_method) {\n\t\tthrow ctx.redirect(\n\t\t\tformatErrorURL(\n\t\t\t\tquery.redirect_uri,\n\t\t\t\t\"invalid_request\",\n\t\t\t\t\"pkce is required\",\n\t\t\t\tquery.state,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Check code challenges\n\tconst codeChallengesSupported = [\"S256\"];\n\tif (!codeChallengesSupported.includes(query.code_challenge_method)) {\n\t\tthrow ctx.redirect(\n\t\t\tformatErrorURL(\n\t\t\t\tquery.redirect_uri,\n\t\t\t\t\"invalid_request\",\n\t\t\t\t\"invalid code_challenge method\",\n\t\t\t\tquery.state,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Check for session\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session || promptSet?.has(\"login\") || promptSet?.has(\"create\")) {\n\t\treturn redirectWithPromptCode(\n\t\t\tctx,\n\t\t\topts,\n\t\t\tpromptSet?.has(\"create\") ? \"create\" : \"login\",\n\t\t);\n\t}\n\n\t// Force account selection (eg. multi-session)\n\tif (settings?.isAuthorize && promptSet?.has(\"select_account\")) {\n\t\treturn redirectWithPromptCode(ctx, opts, \"select_account\");\n\t}\n\n\tif (\n\t\t// Check if account needs selection (only for authorize endpoint)\n\t\tsettings?.isAuthorize &&\n\t\topts.selectAccount\n\t) {\n\t\tconst selectedAccountRedirect = await opts.selectAccount.shouldRedirect({\n\t\t\theaders: ctx.request.headers,\n\t\t\tuser: session.user,\n\t\t\tsession: session.session,\n\t\t\tscopes: requestedScopes,\n\t\t});\n\t\tif (selectedAccountRedirect) {\n\t\t\treturn redirectWithPromptCode(ctx, opts, \"select_account\");\n\t\t}\n\t}\n\n\t// Redirect to complete registration steps\n\tif (opts.signup?.shouldRedirect) {\n\t\tconst signupRedirect = await opts.signup.shouldRedirect({\n\t\t\theaders: ctx.request.headers,\n\t\t\tuser: session.user,\n\t\t\tsession: session.session,\n\t\t\tscopes: requestedScopes,\n\t\t});\n\t\tif (signupRedirect) {\n\t\t\treturn redirectWithPromptCode(\n\t\t\t\tctx,\n\t\t\t\topts,\n\t\t\t\t\"create\",\n\t\t\t\ttypeof signupRedirect === \"string\" ? signupRedirect : undefined,\n\t\t\t);\n\t\t}\n\t}\n\n\tif (!settings?.postLogin && opts.postLogin) {\n\t\tconst postLoginRedirect = await opts.postLogin.shouldRedirect({\n\t\t\theaders: ctx.request.headers,\n\t\t\tuser: session.user,\n\t\t\tsession: session.session,\n\t\t\tscopes: requestedScopes,\n\t\t});\n\t\tif (postLoginRedirect) {\n\t\t\treturn redirectWithPromptCode(ctx, opts, \"post_login\");\n\t\t}\n\t}\n\n\t// Force consent screen\n\tif (promptSet?.has(\"consent\")) {\n\t\treturn redirectWithPromptCode(ctx, opts, \"consent\");\n\t}\n\n\tconst referenceId = await opts.postLogin?.consentReferenceId?.({\n\t\tuser: session.user,\n\t\tsession: session.session,\n\t\tscopes: requestedScopes,\n\t});\n\n\t// Can skip consent (unless forced by prompt above)\n\tif (client.skipConsent) {\n\t\treturn redirectWithAuthorizationCode(ctx, opts, {\n\t\t\tquery,\n\t\t\tclientId: client.clientId,\n\t\t\tuserId: session.user.id,\n\t\t\tsessionId: session.session.id,\n\t\t\treferenceId,\n\t\t});\n\t}\n\tconst consent = await ctx.context.adapter.findOne<OAuthConsent<Scope[]>>({\n\t\tmodel: \"oauthConsent\",\n\t\twhere: [\n\t\t\t{\n\t\t\t\tfield: \"clientId\",\n\t\t\t\tvalue: client.clientId,\n\t\t\t},\n\t\t\t{\n\t\t\t\tfield: \"userId\",\n\t\t\t\tvalue: session.user.id,\n\t\t\t},\n\t\t\t...(referenceId\n\t\t\t\t? [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfield: \"referenceId\",\n\t\t\t\t\t\t\tvalue: referenceId,\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t: []),\n\t\t],\n\t});\n\n\tif (\n\t\t!consent ||\n\t\t!requestedScopes.every((val) => consent.scopes.includes(val))\n\t) {\n\t\treturn redirectWithPromptCode(ctx, opts, \"consent\");\n\t}\n\n\treturn redirectWithAuthorizationCode(ctx, opts, {\n\t\tquery,\n\t\tclientId: client.clientId,\n\t\tuserId: session.user.id,\n\t\tsessionId: session.session.id,\n\t\treferenceId,\n\t});\n}\n\nasync function redirectWithAuthorizationCode(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\tverificationValue: {\n\t\tquery: OAuthAuthorizationQuery;\n\t\tclientId: string;\n\t\tuserId: string;\n\t\tsessionId: string;\n\t\treferenceId?: string;\n\t},\n) {\n\tconst code = generateRandomString(32, \"a-z\", \"A-Z\", \"0-9\");\n\tconst iat = Math.floor(Date.now() / 1000);\n\tconst exp = iat + (opts.codeExpiresIn ?? 600);\n\n\tconst data: Omit<Verification, \"id\" | \"createdAt\"> = {\n\t\tidentifier: await storeToken(opts.storeTokens, code, \"authorization_code\"),\n\t\tupdatedAt: new Date(iat * 1000),\n\t\texpiresAt: new Date(exp * 1000),\n\t\tvalue: JSON.stringify({\n\t\t\ttype: \"authorization_code\",\n\t\t\tquery: ctx.query,\n\t\t\tuserId: verificationValue.userId,\n\t\t\tsessionId: verificationValue?.sessionId,\n\t\t\treferenceId: verificationValue.referenceId,\n\t\t} satisfies VerificationValue),\n\t};\n\tctx.context.verification_id\n\t\t? await ctx.context.internalAdapter.updateVerificationValue(\n\t\t\t\tctx.context.verification_id,\n\t\t\t\tdata,\n\t\t\t)\n\t\t: await ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\t...data,\n\t\t\t\tcreatedAt: new Date(iat * 1000),\n\t\t\t});\n\n\tconst redirectUriWithCode = new URL(verificationValue.query.redirect_uri);\n\tredirectUriWithCode.searchParams.set(\"code\", code);\n\tif (verificationValue.query.state) {\n\t\tredirectUriWithCode.searchParams.set(\n\t\t\t\"state\",\n\t\t\tverificationValue.query.state,\n\t\t);\n\t}\n\n\treturn handleRedirect(ctx, redirectUriWithCode.toString());\n}\n\nasync function redirectWithPromptCode(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\ttype: \"login\" | \"create\" | \"consent\" | \"select_account\" | \"post_login\",\n\tpage?: string,\n) {\n\tconst queryParams = await signParams(ctx, opts);\n\tlet path = opts.loginPage;\n\tif (type === \"select_account\") {\n\t\tpath = opts.selectAccount?.page ?? opts.loginPage;\n\t} else if (type === \"post_login\") {\n\t\tif (!opts.postLogin?.page)\n\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\terror_description: \"postLogin should have been defined\",\n\t\t\t});\n\t\tpath = opts.postLogin?.page;\n\t} else if (type === \"consent\") {\n\t\tpath = opts.consentPage;\n\t} else if (type === \"create\") {\n\t\tpath = opts.signup?.page ?? opts.loginPage;\n\t}\n\treturn handleRedirect(ctx, `${page ?? path}?${queryParams}`);\n}\n\nasync function signParams(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\t// Add expiration to query parameters\n\tconst iat = Math.floor(Date.now() / 1000);\n\tconst exp = iat + (opts.codeExpiresIn ?? 600);\n\tconst params = new URLSearchParams(ctx.query);\n\tparams.set(\"exp\", String(exp));\n\n\tconst signature = await makeSignature(params.toString(), ctx.context.secret);\n\tparams.append(\"sig\", signature);\n\treturn params.toString();\n}\n","import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { APIError, getSessionFromCtx } from \"better-auth/api\";\nimport { authorizeEndpoint, formatErrorURL } from \"./authorize\";\nimport { oAuthState } from \"./oauth\";\nimport type { OAuthConsent, OAuthOptions, Scope } from \"./types\";\nimport { deleteFromPrompt } from \"./utils\";\n\nexport async function consentEndpoint(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\t// Obtain oauth query\n\tconst _query = (await oAuthState.get())?.query as string | undefined;\n\tif (!_query) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"missing oauth query\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tconst query = new URLSearchParams(_query);\n\tconst originalRequestedScopes = query.get(\"scope\")?.split(\" \") ?? [];\n\tconst clientId = query.get(\"client_id\");\n\tif (!clientId) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"client_id is required\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\n\t// Check scopes if received (can only be equal or lesser than originally requested scopes)\n\tconst requestedScopes = (ctx.body.scope as string | undefined)?.split(\" \");\n\tif (requestedScopes) {\n\t\tif (!requestedScopes.every((sc) => originalRequestedScopes?.includes(sc))) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\terror_description: \"Scope not originally requested\",\n\t\t\t\terror: \"invalid_request\",\n\t\t\t});\n\t\t}\n\t}\n\n\t// Consent not accepted (ensure it's strictly boolean true)\n\tconst accepted = ctx.body.accept === true;\n\tif (!accepted) {\n\t\treturn {\n\t\t\tredirect: true,\n\t\t\turi: formatErrorURL(\n\t\t\t\tquery.get(\"redirect_uri\") ?? \"\",\n\t\t\t\t\"access_denied\",\n\t\t\t\t\"User denied access\",\n\t\t\t\tquery.get(\"state\") ?? undefined,\n\t\t\t),\n\t\t};\n\t}\n\n\t// Consent accepted\n\tconst session = await getSessionFromCtx(ctx);\n\tconst referenceId = await opts.postLogin?.consentReferenceId?.({\n\t\tuser: session?.user!,\n\t\tsession: session?.session!,\n\t\tscopes: requestedScopes ?? originalRequestedScopes,\n\t});\n\tconst foundConsent = await ctx.context.adapter.findOne<OAuthConsent<Scope[]>>(\n\t\t{\n\t\t\tmodel: \"oauthConsent\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"clientId\",\n\t\t\t\t\tvalue: clientId,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tfield: \"userId\",\n\t\t\t\t\tvalue: session?.user.id!,\n\t\t\t\t},\n\t\t\t\t...(referenceId\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfield: \"referenceId\",\n\t\t\t\t\t\t\t\tvalue: referenceId,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]\n\t\t\t\t\t: []),\n\t\t\t],\n\t\t},\n\t);\n\tconst iat = Math.floor(Date.now() / 1000);\n\tconst consent: Omit<OAuthConsent<Scope[]>, \"id\"> = {\n\t\tclientId: clientId,\n\t\tuserId: session?.user.id!,\n\t\tscopes: requestedScopes ?? originalRequestedScopes,\n\t\tcreatedAt: new Date(iat * 1000),\n\t\tupdatedAt: new Date(iat * 1000),\n\t\treferenceId,\n\t};\n\tfoundConsent?.id\n\t\t? await ctx.context.adapter.update({\n\t\t\t\tmodel: \"oauthConsent\",\n\t\t\t\twhere: [\n\t\t\t\t\t{\n\t\t\t\t\t\tfield: \"id\",\n\t\t\t\t\t\tvalue: foundConsent.id,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tupdate: {\n\t\t\t\t\tscopes: consent.scopes,\n\t\t\t\t\tupdatedAt: new Date(iat * 1000),\n\t\t\t\t},\n\t\t\t})\n\t\t: await ctx.context.adapter.create({\n\t\t\t\tmodel: \"oauthConsent\",\n\t\t\t\tdata: {\n\t\t\t\t\t...consent,\n\t\t\t\t\tscopes: consent.scopes,\n\t\t\t\t},\n\t\t\t});\n\n\t// Return authorization code\n\tctx?.headers?.set(\"accept\", \"application/json\");\n\tctx.query = deleteFromPrompt(query, \"consent\");\n\tctx.context.postLogin = true;\n\tconst { url } = await authorizeEndpoint(ctx, opts);\n\treturn {\n\t\tredirect: true,\n\t\turi: url,\n\t};\n}\n","import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { APIError } from \"better-auth/api\";\nimport { authorizeEndpoint } from \"./authorize\";\nimport { oAuthState } from \"./oauth\";\nimport type { OAuthOptions, Scope } from \"./types\";\nimport { deleteFromPrompt } from \"./utils\";\n\nexport async function continueEndpoint(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\t// Continue login flow (ensure it's strictly boolean true)\n\tif (ctx.body.selected === true) {\n\t\treturn await selected(ctx, opts);\n\t} else if (ctx.body.created === true) {\n\t\treturn await created(ctx, opts);\n\t} else if (ctx.body.postLogin === true) {\n\t\treturn await postLogin(ctx, opts);\n\t} else {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"Missing parameters\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n}\n\nasync function selected(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\tconst _query = (await oAuthState.get())?.query as string | undefined;\n\tif (!_query) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"missing oauth query\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tctx.headers?.set(\"accept\", \"application/json\");\n\tconst query = new URLSearchParams(_query);\n\tctx.query = deleteFromPrompt(query, \"select_account\");\n\tconst { url } = await authorizeEndpoint(ctx, opts);\n\treturn {\n\t\tredirect: true,\n\t\turi: url,\n\t};\n}\n\nasync function created(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\tconst _query = (await oAuthState.get())?.query as string | undefined;\n\tif (!_query) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"missing oauth query\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tconst query = new URLSearchParams(_query);\n\tctx.query = deleteFromPrompt(query, \"create\");\n\tconst { url } = await authorizeEndpoint(ctx, opts);\n\treturn {\n\t\tredirect: true,\n\t\turi: url,\n\t};\n}\n\nasync function postLogin(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\tconst _query = (await oAuthState.get())?.query as string | undefined;\n\tif (!_query) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"missing oauth query\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tconst query = new URLSearchParams(_query);\n\tctx.headers?.set(\"accept\", \"application/json\");\n\tctx.query = Object.fromEntries(query);\n\tconst { url } = await authorizeEndpoint(ctx, opts, {\n\t\tpostLogin: true,\n\t});\n\treturn {\n\t\tredirect: true,\n\t\turi: url,\n\t};\n}\n","import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { APIError } from \"better-auth/api\";\nimport type { User } from \"better-auth/types\";\nimport { validateAccessToken } from \"./introspect\";\nimport type { OAuthOptions, Scope } from \"./types\";\n\n/**\n * Provides shared /userinfo and id_token claims functionality\n *\n * @see https://openid.net/specs/openid-connect-core-1_0.html#NormalClaims\n */\nexport function userNormalClaims(user: User, scopes: string[]) {\n\tconst name = user.name.split(\" \").filter((v) => v !== \"\");\n\tconst profile = {\n\t\tname: user.name ?? undefined,\n\t\tpicture: user.image ?? undefined,\n\t\tgiven_name: name.length > 1 ? name.slice(0, -1).join(\" \") : undefined,\n\t\tfamily_name: name.length > 1 ? name.at(-1) : undefined,\n\t};\n\tconst email = {\n\t\temail: user.email ?? undefined,\n\t\temail_verified: user.emailVerified ?? false,\n\t};\n\n\treturn {\n\t\tsub: user.id ?? undefined,\n\t\t...(scopes.includes(\"profile\") ? profile : {}),\n\t\t...(scopes.includes(\"email\") ? email : {}),\n\t};\n}\n\n/**\n * Handles the /oauth2/userinfo endpoint\n */\nexport async function userInfoEndpoint(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\tif (!ctx.request) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"request not found\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\tconst authorization = ctx.request.headers.get(\"authorization\");\n\tconst token =\n\t\ttypeof authorization === \"string\" && authorization?.startsWith(\"Bearer \")\n\t\t\t? authorization?.replace(\"Bearer \", \"\")\n\t\t\t: authorization;\n\tif (!token?.length) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"authorization header not found\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tconst jwt = await validateAccessToken(ctx, opts, token);\n\n\tconst scopes = (jwt.scope as string | undefined)?.split(\" \");\n\tif (!scopes?.includes(\"openid\")) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"Missing required scope\",\n\t\t\terror: \"invalid_scope\",\n\t\t});\n\t}\n\n\tif (!jwt.sub) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"user not found\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\tconst user = await ctx.context.internalAdapter.findUserById(jwt.sub);\n\tif (!user) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"user not found\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\tconst baseUserClaims = userNormalClaims(user, scopes ?? []);\n\tconst additionalInfoUserClaims =\n\t\topts.customUserInfoClaims && scopes?.length\n\t\t\t? await opts.customUserInfoClaims({ user, scopes, jwt })\n\t\t\t: {};\n\treturn {\n\t\t...baseUserClaims,\n\t\t...additionalInfoUserClaims,\n\t};\n}\n","import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { APIError } from \"better-auth/api\";\nimport { generateRandomString } from \"better-auth/crypto\";\nimport { generateCodeChallenge } from \"better-auth/oauth2\";\nimport { signJWT, toExpJWT } from \"better-auth/plugins\";\nimport type { Session, User } from \"better-auth/types\";\nimport type { JWTPayload } from \"jose\";\nimport { SignJWT } from \"jose\";\nimport type {\n\tOAuthOptions,\n\tOAuthRefreshToken,\n\tSchemaClient,\n\tScope,\n\tVerificationValue,\n} from \"./types\";\nimport type { GrantType } from \"./types/oauth\";\nimport { userNormalClaims } from \"./userinfo\";\nimport {\n\tbasicToClientCredentials,\n\tdecryptStoredClientSecret,\n\tgetJwtPlugin,\n\tgetStoredToken,\n\tparseClientMetadata,\n\tstoreToken,\n\tvalidateClientCredentials,\n} from \"./utils\";\n\n/**\n * Handles the /oauth2/token endpoint by delegating\n * the grant types\n */\nexport async function tokenEndpoint(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\tconst grantType: GrantType | undefined = ctx.body?.grant_type;\n\n\tif (opts.grantTypes && grantType && !opts.grantTypes.includes(grantType)) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: `unsupported grant_type ${grantType}`,\n\t\t\terror: \"unsupported_grant_type\",\n\t\t});\n\t}\n\n\tswitch (grantType) {\n\t\tcase \"authorization_code\":\n\t\t\treturn handleAuthorizationCodeGrant(ctx, opts);\n\t\tcase \"client_credentials\":\n\t\t\treturn handleClientCredentialsGrant(ctx, opts);\n\t\tcase \"refresh_token\":\n\t\t\treturn handleRefreshTokenGrant(ctx, opts);\n\t\tcase undefined:\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\terror_description: \"missing required grant_type\",\n\t\t\t\terror: \"unsupported_grant_type\",\n\t\t\t});\n\t\tdefault:\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\terror_description: `unsupported grant_type ${grantType}`,\n\t\t\t\terror: \"unsupported_grant_type\",\n\t\t\t});\n\t}\n}\n\n// User Jwt SHALL follow oAuth 2\n// NOTE: Requires jwt plugin (assert !opts.disableJwtPlugin)\nasync function createJwtAccessToken(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\tuser: User,\n\tclient: SchemaClient<Scope[]>,\n\taudience: string | string[],\n\tscopes: string[],\n\treferenceId?: string,\n\toverrides?: {\n\t\tiat?: number;\n\t\texp?: number;\n\t\tsid?: string;\n\t},\n) {\n\tconst iat = overrides?.iat ?? Math.floor(Date.now() / 1000);\n\tconst exp = overrides?.exp ?? iat + (opts.accessTokenExpiresIn ?? 3600);\n\tconst customClaims = opts.customAccessTokenClaims\n\t\t? await opts.customAccessTokenClaims({\n\t\t\t\tuser,\n\t\t\t\tscopes,\n\t\t\t\tresource: ctx.body.resource,\n\t\t\t\treferenceId,\n\t\t\t\tmetadata: parseClientMetadata(client.metadata),\n\t\t\t})\n\t\t: {};\n\n\tconst jwtPluginOptions = getJwtPlugin(ctx.context).options;\n\n\t// Sign token\n\treturn signJWT(ctx, {\n\t\toptions: jwtPluginOptions,\n\t\tpayload: {\n\t\t\t...customClaims,\n\t\t\tsub: user.id,\n\t\t\taud:\n\t\t\t\ttypeof audience === \"string\"\n\t\t\t\t\t? audience\n\t\t\t\t\t: audience?.length === 1\n\t\t\t\t\t\t? audience.at(0)\n\t\t\t\t\t\t: audience,\n\t\t\tazp: client.clientId,\n\t\t\tscope: scopes.join(\" \"),\n\t\t\tsid: overrides?.sid,\n\t\t\tiss: jwtPluginOptions?.jwt?.issuer ?? ctx.context.baseURL,\n\t\t\tiat,\n\t\t\texp,\n\t\t},\n\t});\n}\n\n/**\n * Creates a user id token in code_authorization with scope of 'openid'\n * and hybrid/implicit (not yet implemented) flows\n */\nasync function createIdToken(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\tuser: User,\n\tclient: SchemaClient<Scope[]>,\n\tscopes: string[],\n\tnonce?: string,\n\tsessionId?: string,\n) {\n\tconst iat = Math.floor(Date.now() / 1000);\n\tconst exp = iat + (opts.idTokenExpiresIn ?? 36000);\n\tconst userClaims = userNormalClaims(user, scopes);\n\tconst authTime = Math.floor(\n\t\t(ctx.context.session?.session.createdAt ?? new Date(iat * 1000)).getTime() /\n\t\t\t1000,\n\t);\n\t// TODO: this should be validated against the login process\n\t// - bronze : password only\n\t// - silver : mfa\n\tconst acr = \"urn:mace:incommon:iap:bronze\";\n\n\tconst customClaims = opts.customIdTokenClaims\n\t\t? await opts.customIdTokenClaims({\n\t\t\t\tuser,\n\t\t\t\tscopes,\n\t\t\t\tmetadata: parseClientMetadata(client.metadata),\n\t\t\t})\n\t\t: {};\n\n\tconst jwtPluginOptions = opts.disableJwtPlugin\n\t\t? undefined\n\t\t: getJwtPlugin(ctx.context).options;\n\n\tconst payload: JWTPayload = {\n\t\t...customClaims,\n\t\t...userClaims,\n\t\tauth_time: authTime,\n\t\tacr,\n\t\tiss: jwtPluginOptions?.jwt?.issuer ?? ctx.context.baseURL,\n\t\tsub: user.id,\n\t\taud: client.clientId,\n\t\tnonce,\n\t\tiat,\n\t\texp,\n\t\tsid: client.enableEndSession ? sessionId : undefined,\n\t};\n\n\t// Public clients without a client secret cannot receive an idToken as it can't be verified\n\t// Confidential clients would still receive an idToken signed by the clientSecret\n\tif (opts.disableJwtPlugin && !client.clientSecret) {\n\t\treturn undefined;\n\t}\n\n\treturn opts.disableJwtPlugin\n\t\t? new SignJWT(payload)\n\t\t\t\t.setProtectedHeader({ alg: \"HS256\" })\n\t\t\t\t.sign(\n\t\t\t\t\tnew TextEncoder().encode(\n\t\t\t\t\t\tawait decryptStoredClientSecret(\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\topts.storeClientSecret,\n\t\t\t\t\t\t\tclient.clientSecret!,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t: signJWT(ctx, {\n\t\t\t\toptions: jwtPluginOptions,\n\t\t\t\tpayload,\n\t\t\t});\n}\n\n/**\n * Encodes a refresh token for a client\n */\nasync function encodeRefreshToken(\n\topts: OAuthOptions<Scope[]>,\n\ttoken: string,\n\tsessionId?: string,\n) {\n\treturn (\n\t\t(opts.prefix?.refreshToken ?? \"\") +\n\t\t(opts.formatRefreshToken?.encrypt\n\t\t\t? opts.formatRefreshToken.encrypt(token, sessionId)\n\t\t\t: token)\n\t);\n}\n\n/**\n * Decodes a refresh token for a client\n *\n * @internal\n */\nexport async function decodeRefreshToken(\n\topts: OAuthOptions<Scope[]>,\n\ttoken: string,\n) {\n\tif (opts.prefix?.refreshToken) {\n\t\tif (token.startsWith(opts.prefix.refreshToken)) {\n\t\t\ttoken = token.replace(opts.prefix.refreshToken, \"\");\n\t\t} else {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\terror_description: \"refresh token not found\",\n\t\t\t\terror: \"invalid_token\",\n\t\t\t});\n\t\t}\n\t}\n\n\treturn opts.formatRefreshToken?.decrypt\n\t\t? opts.formatRefreshToken?.decrypt(token)\n\t\t: { token };\n}\n\nasync function createOpaqueAccessToken(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\tuser: User | undefined,\n\tclient: SchemaClient<Scope[]>,\n\tscopes: string[],\n\tpayload: JWTPayload,\n\treferenceId?: string,\n\trefreshId?: string,\n) {\n\tconst iat = payload.iat ?? Math.floor(Date.now() / 1000);\n\tconst exp = payload?.exp ?? iat + (opts.accessTokenExpiresIn ?? 3600);\n\tconst token = opts.generateOpaqueAccessToken\n\t\t? await opts.generateOpaqueAccessToken()\n\t\t: generateRandomString(32, \"A-Z\", \"a-z\");\n\tawait ctx.context.adapter.create({\n\t\tmodel: \"oauthAccessToken\",\n\t\tdata: {\n\t\t\ttoken: await storeToken(opts.storeTokens, token, \"access_token\"),\n\t\t\tclientId: client.clientId,\n\t\t\tsessionId: payload?.sid,\n\t\t\tuserId: user?.id,\n\t\t\treferenceId,\n\t\t\trefreshId,\n\t\t\tscopes,\n\t\t\tcreatedAt: new Date(iat * 1000),\n\t\t\texpiresAt: new Date(exp * 1000),\n\t\t},\n\t});\n\treturn (opts.prefix?.opaqueAccessToken ?? \"\") + token;\n}\n\nasync function createRefreshToken(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\tuser: User,\n\treferenceId: string | undefined,\n\tclient: SchemaClient<Scope[]>,\n\tscopes: string[],\n\tpayload: JWTPayload,\n\toriginalRefresh?: OAuthRefreshToken<Scope[]> & { id: string },\n) {\n\tconst iat = payload.iat ?? Math.floor(Date.now() / 1000);\n\tconst exp = payload?.exp ?? iat + (opts.refreshTokenExpiresIn ?? 2592000);\n\tconst token = opts.generateRefreshToken\n\t\t? await opts.generateRefreshToken()\n\t\t: generateRandomString(32, \"A-Z\", \"a-z\");\n\tconst sessionId = payload?.sid as string | undefined;\n\t// Mark old refresh as stale\n\tif (originalRefresh?.id) {\n\t\tawait ctx.context.adapter.update({\n\t\t\tmodel: \"oauthRefreshToken\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t\tvalue: originalRefresh.id,\n\t\t\t\t},\n\t\t\t],\n\t\t\tupdate: {\n\t\t\t\trevoked: new Date(iat * 1000),\n\t\t\t},\n\t\t});\n\t}\n\n\t// Issue new refresh token\n\tconst refreshToken = await ctx.context.adapter.create({\n\t\tmodel: \"oauthRefreshToken\",\n\t\tdata: {\n\t\t\ttoken: await storeToken(opts.storeTokens, token, \"refresh_token\"),\n\t\t\tclientId: client.clientId,\n\t\t\tsessionId,\n\t\t\tuserId: user.id,\n\t\t\treferenceId,\n\t\t\tscopes,\n\t\t\tcreatedAt: new Date(iat * 1000),\n\t\t\texpiresAt: new Date(exp * 1000),\n\t\t},\n\t});\n\treturn {\n\t\tid: refreshToken.id,\n\t\ttoken: await encodeRefreshToken(opts, token, sessionId),\n\t};\n}\n\n/**\n * Checks the resource parameter, if provided,\n * and returns a valid audience based on the request\n */\nasync function checkResource(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\tscopes: string[],\n) {\n\tconst resource: string | string[] | undefined = ctx.body.resource;\n\tconst audience =\n\t\ttypeof resource === \"string\"\n\t\t\t? [resource]\n\t\t\t: resource\n\t\t\t\t? [...resource]\n\t\t\t\t: undefined;\n\tif (audience) {\n\t\t// Adds /userinfo to audience\n\t\tif (scopes.includes(\"openid\")) {\n\t\t\taudience.push(`${ctx.context.baseURL}/oauth2/userinfo`);\n\t\t}\n\t\t// Check valid audiences\n\t\tconst validAudiences = new Set(\n\t\t\t[\n\t\t\t\t...(opts.validAudiences ?? [ctx.context.baseURL]),\n\t\t\t\tscopes?.includes(\"openid\")\n\t\t\t\t\t? `${ctx.context.baseURL}/oauth2/userinfo`\n\t\t\t\t\t: undefined,\n\t\t\t]\n\t\t\t\t.flat()\n\t\t\t\t.filter((v) => v?.length),\n\t\t);\n\t\tfor (const aud of audience) {\n\t\t\tif (!validAudiences.has(aud)) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\terror_description: \"requested resource invalid\",\n\t\t\t\t\terror: \"invalid_request\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\treturn audience?.length === 1 ? audience.at(0) : audience;\n}\n\nasync function createUserTokens(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\tclient: SchemaClient<Scope[]>,\n\tscopes: string[],\n\tuser: User,\n\treferenceId?: string,\n\tsessionId?: string,\n\tnonce?: string,\n\tadditional?: {\n\t\trefreshToken?: OAuthRefreshToken<Scope[]> & { id: string };\n\t},\n) {\n\tconst iat = Math.floor(Date.now() / 1000);\n\tconst defaultExp = iat + (opts.accessTokenExpiresIn ?? 3600);\n\tconst exp = opts.scopeExpirations\n\t\t? scopes\n\t\t\t\t.map((sc) =>\n\t\t\t\t\topts.scopeExpirations?.[sc]\n\t\t\t\t\t\t? toExpJWT(opts.scopeExpirations[sc], iat)\n\t\t\t\t\t\t: defaultExp,\n\t\t\t\t)\n\t\t\t\t.reduce((prev, curr) => {\n\t\t\t\t\treturn prev < curr ? prev : curr;\n\t\t\t\t}, defaultExp)\n\t\t: defaultExp;\n\n\t// Check requested audience if sent as the resource parameter\n\tconst audience = await checkResource(ctx, opts, scopes);\n\tconst isRefreshToken =\n\t\tadditional?.refreshToken?.scopes?.includes(\"offline_access\") ||\n\t\tscopes.includes(\"offline_access\");\n\tconst isJwtAccessToken = audience && !opts.disableJwtPlugin;\n\tconst isIdToken = scopes.includes(\"openid\");\n\n\t// Refresh token may need to be created beforehand for id field\n\tconst earlyRefreshToken =\n\t\tisRefreshToken && !isJwtAccessToken\n\t\t\t? await createRefreshToken(\n\t\t\t\t\tctx,\n\t\t\t\t\topts,\n\t\t\t\t\tuser,\n\t\t\t\t\treferenceId,\n\t\t\t\t\tclient,\n\t\t\t\t\tscopes,\n\t\t\t\t\t{\n\t\t\t\t\t\tiat,\n\t\t\t\t\t\texp: iat + (opts.refreshTokenExpiresIn ?? 2592000),\n\t\t\t\t\t\tsid: sessionId,\n\t\t\t\t\t},\n\t\t\t\t\tadditional?.refreshToken,\n\t\t\t\t)\n\t\t\t: undefined;\n\n\t// Sign jwt and refresh tokens in parallel\n\tconst [accessToken, refreshToken, idToken] = await Promise.all([\n\t\tisJwtAccessToken\n\t\t\t? createJwtAccessToken(\n\t\t\t\t\tctx,\n\t\t\t\t\topts,\n\t\t\t\t\tuser,\n\t\t\t\t\tclient,\n\t\t\t\t\taudience,\n\t\t\t\t\tscopes,\n\t\t\t\t\treferenceId,\n\t\t\t\t\t{\n\t\t\t\t\t\tiat,\n\t\t\t\t\t\texp,\n\t\t\t\t\t\tsid: sessionId,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t: createOpaqueAccessToken(\n\t\t\t\t\tctx,\n\t\t\t\t\topts,\n\t\t\t\t\tuser,\n\t\t\t\t\tclient,\n\t\t\t\t\tscopes,\n\t\t\t\t\t{\n\t\t\t\t\t\tiat,\n\t\t\t\t\t\texp,\n\t\t\t\t\t\tsid: sessionId,\n\t\t\t\t\t},\n\t\t\t\t\treferenceId,\n\t\t\t\t\tearlyRefreshToken?.id,\n\t\t\t\t),\n\t\tearlyRefreshToken\n\t\t\t? earlyRefreshToken\n\t\t\t: isRefreshToken\n\t\t\t\t? createRefreshToken(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\topts,\n\t\t\t\t\t\tuser,\n\t\t\t\t\t\treferenceId,\n\t\t\t\t\t\tclient,\n\t\t\t\t\t\tscopes,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tiat,\n\t\t\t\t\t\t\texp: iat + (opts.refreshTokenExpiresIn ?? 2592000),\n\t\t\t\t\t\t\tsid: sessionId,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tadditional?.refreshToken,\n\t\t\t\t\t)\n\t\t\t\t: undefined,\n\t\tisIdToken\n\t\t\t? createIdToken(ctx, opts, user, client, scopes, nonce, sessionId)\n\t\t\t: undefined,\n\t]);\n\n\treturn ctx.json(\n\t\t{\n\t\t\taccess_token: accessToken,\n\t\t\texpires_in: exp - iat,\n\t\t\texpires_at: exp,\n\t\t\ttoken_type: \"Bearer\",\n\t\t\trefresh_token: refreshToken?.token,\n\t\t\tscope: scopes.join(\" \"),\n\t\t\tid_token: idToken,\n\t\t},\n\t\t{\n\t\t\theaders: {\n\t\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t\tPragma: \"no-cache\",\n\t\t\t},\n\t\t},\n\t);\n}\n\n/** Checks verification value */\nasync function checkVerificationValue(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\tcode: string,\n\tclient_id: string,\n\tredirect_uri?: string,\n) {\n\tconst verification = await ctx.context.internalAdapter.findVerificationValue(\n\t\tawait storeToken(opts.storeTokens, code, \"authorization_code\"),\n\t);\n\tconst verificationValue: VerificationValue = verification\n\t\t? JSON.parse(verification?.value)\n\t\t: undefined;\n\n\tif (!verification) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"Invalid code\",\n\t\t\terror: \"invalid_verification\",\n\t\t});\n\t}\n\n\t// Delete used code\n\tif (verification?.id) {\n\t\tawait ctx.context.internalAdapter.deleteVerificationValue(verification.id);\n\t}\n\n\t// Check verification\n\tif (!verification.expiresAt || verification.expiresAt < new Date()) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"code expired\",\n\t\t\terror: \"invalid_verification\",\n\t\t});\n\t}\n\n\t// Check verification value\n\tif (!verificationValue) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"missing verification value content\",\n\t\t\terror: \"invalid_verification\",\n\t\t});\n\t}\n\tif (verificationValue.type !== \"authorization_code\") {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"incorrect verification type\",\n\t\t\terror: \"invalid_verification\",\n\t\t});\n\t}\n\tif (verificationValue.query.client_id !== client_id) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"invalid client_id\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\tif (!verificationValue.userId) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"missing user_id on challenge\",\n\t\t\terror: \"invalid_user\",\n\t\t});\n\t}\n\tif (\n\t\tverificationValue.query?.redirect_uri &&\n\t\tverificationValue.query?.redirect_uri !== redirect_uri\n\t) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"missing verification redirect_uri\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\treturn verificationValue;\n}\n\n/**\n * Obtains new Session Jwt and Refresh Tokens using a code\n */\nasync function handleAuthorizationCodeGrant(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\tlet {\n\t\tclient_id,\n\t\tclient_secret,\n\t\tcode,\n\t\tcode_verifier,\n\t\tredirect_uri,\n\t}: {\n\t\tclient_id?: string;\n\t\tclient_secret?: string;\n\t\tcode?: string;\n\t\tcode_verifier?: string;\n\t\tredirect_uri?: string;\n\t} = ctx.body;\n\tconst authorization = ctx.request?.headers.get(\"authorization\") || null;\n\n\t// Convert basic authorization\n\tif (authorization?.startsWith(\"Basic \")) {\n\t\tconst res = basicToClientCredentials(authorization);\n\t\tclient_id = res?.client_id;\n\t\tclient_secret = res?.client_secret;\n\t}\n\n\tif (!client_id) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"client_id is required\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tif (!code) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"code is required\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tif (!redirect_uri) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"redirect_uri is required\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\tconst isAuthCodeWithSecret = client_id && client_secret;\n\tconst isAuthCodeWithPkce = client_id && code && code_verifier;\n\n\tif (!(isAuthCodeWithPkce || isAuthCodeWithSecret)) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description:\n\t\t\t\t\"Missing a required credential value for authorization_code grant\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\t/** Get and check Verification Value */\n\tconst verificationValue = await checkVerificationValue(\n\t\tctx,\n\t\topts,\n\t\tcode,\n\t\tclient_id,\n\t\tredirect_uri,\n\t);\n\tconst scopes = verificationValue.query.scope?.split(\" \");\n\tif (!scopes) {\n\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\terror_description: \"verification scope unset\",\n\t\t\terror: \"invalid_scope\",\n\t\t});\n\t}\n\n\t/** Verify Client */\n\tconst client = await validateClientCredentials(\n\t\tctx,\n\t\topts,\n\t\tclient_id,\n\t\tclient_secret,\n\t\tscopes,\n\t);\n\n\t/** Check challenge */\n\tconst challenge =\n\t\tcode_verifier && verificationValue.query?.code_challenge_method === \"S256\"\n\t\t\t? await generateCodeChallenge(code_verifier)\n\t\t\t: undefined;\n\tif (\n\t\t// AuthCodeWithSecret - Required if sent\n\t\tisAuthCodeWithSecret &&\n\t\t(challenge || verificationValue?.query?.code_challenge) &&\n\t\tchallenge !== verificationValue.query?.code_challenge\n\t) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"code verification failed\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tif (\n\t\t// AuthCodeWithPkce - Always required\n\t\tisAuthCodeWithPkce &&\n\t\tchallenge !== verificationValue.query?.code_challenge\n\t) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"code verification failed\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\t/** Get user */\n\tif (!verificationValue.userId) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"missing user, user may have been deleted\",\n\t\t\terror: \"invalid_user\",\n\t\t});\n\t}\n\tconst user = await ctx.context.internalAdapter.findUserById(\n\t\tverificationValue.userId,\n\t);\n\tif (!user) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"missing user, user may have been deleted\",\n\t\t\terror: \"invalid_user\",\n\t\t});\n\t}\n\n\t// Check if session used is still active\n\tconst session = await ctx.context.adapter.findOne<Session>({\n\t\tmodel: \"session\",\n\t\twhere: [\n\t\t\t{\n\t\t\t\tfield: \"id\",\n\t\t\t\tvalue: verificationValue.sessionId,\n\t\t\t},\n\t\t],\n\t});\n\tif (!session || session.expiresAt < new Date()) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"session no longer exists\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\treturn createUserTokens(\n\t\tctx,\n\t\topts,\n\t\tclient,\n\t\tverificationValue.query.scope?.split(\" \") ?? [],\n\t\tuser,\n\t\tverificationValue.referenceId,\n\t\tsession.id,\n\t\tverificationValue.query?.nonce,\n\t);\n}\n\n/**\n * Grant that allows direct access to an API using the application's credentials\n * This grant is for M2M so the concept of a user id does not exist on the token.\n *\n * MUST follow https://datatracker.ietf.org/doc/html/rfc6749#section-4.4\n */\nasync function handleClientCredentialsGrant(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\tlet {\n\t\tclient_id,\n\t\tclient_secret,\n\t\tscope,\n\t}: {\n\t\tclient_id?: string;\n\t\tclient_secret?: string;\n\t\tscope?: string;\n\t} = ctx.body;\n\tconst authorization = ctx.request?.headers.get(\"authorization\") || null;\n\n\t// Convert basic authorization\n\tif (authorization?.startsWith(\"Basic \")) {\n\t\tconst res = basicToClientCredentials(authorization);\n\t\tclient_id = res?.client_id;\n\t\tclient_secret = res?.client_secret;\n\t}\n\n\tif (!client_id) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"Missing required client_id\",\n\t\t\terror: \"invalid_grant\",\n\t\t});\n\t}\n\tif (!client_secret) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"Missing a required client_secret\",\n\t\t\terror: \"invalid_grant\",\n\t\t});\n\t}\n\n\t// Note: Scope check is done below instead of through the function since different requirements\n\tconst client = await validateClientCredentials(\n\t\tctx,\n\t\topts,\n\t\tclient_id,\n\t\tclient_secret,\n\t);\n\n\t// OIDC scopes should not be requestable (code authorization grant should be used)\n\tlet requestedScopes = scope?.split(\" \");\n\tif (requestedScopes) {\n\t\tconst validScopes = new Set(client.scopes ?? opts.scopes);\n\t\tconst oidcScopes = new Set([\n\t\t\t\"openid\",\n\t\t\t\"profile\",\n\t\t\t\"email\",\n\t\t\t\"offline_access\",\n\t\t]);\n\t\tconst invalidScopes = requestedScopes.filter((scope) => {\n\t\t\treturn !validScopes?.has(scope) || oidcScopes.has(scope);\n\t\t});\n\t\tif (invalidScopes.length) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\terror_description: `The following scopes are invalid: ${invalidScopes.join(\", \")}`,\n\t\t\t\terror: \"invalid_scope\",\n\t\t\t});\n\t\t}\n\t}\n\t// Set default scopes to all those available for that client or all provided scopes.\n\tif (!requestedScopes) {\n\t\trequestedScopes =\n\t\t\tclient.scopes ??\n\t\t\topts.clientCredentialGrantDefaultScopes ??\n\t\t\topts.scopes ??\n\t\t\t[];\n\t}\n\n\t// Check requested audience if sent as the resource parameter\n\tconst jwtPluginOptions = opts.disableJwtPlugin\n\t\t? undefined\n\t\t: getJwtPlugin(ctx.context).options;\n\tconst audience = await checkResource(ctx, opts, requestedScopes);\n\n\tconst iat = Math.floor(Date.now() / 1000);\n\tconst defaultExp = iat + (opts.m2mAccessTokenExpiresIn ?? 3600);\n\tconst exp =\n\t\topts.scopeExpirations && requestedScopes\n\t\t\t? requestedScopes\n\t\t\t\t\t.map((sc) =>\n\t\t\t\t\t\topts.scopeExpirations?.[sc]\n\t\t\t\t\t\t\t? toExpJWT(opts.scopeExpirations[sc], iat)\n\t\t\t\t\t\t\t: defaultExp,\n\t\t\t\t\t)\n\t\t\t\t\t.reduce((prev, curr) => {\n\t\t\t\t\t\treturn prev < curr ? prev : curr;\n\t\t\t\t\t}, defaultExp)\n\t\t\t: defaultExp;\n\n\tconst customClaims = opts.customAccessTokenClaims\n\t\t? await opts.customAccessTokenClaims({\n\t\t\t\tscopes: requestedScopes,\n\t\t\t\tresource: ctx.body.resource,\n\t\t\t\tmetadata: parseClientMetadata(client.metadata),\n\t\t\t})\n\t\t: {};\n\n\tconst accessToken =\n\t\taudience && !opts.disableJwtPlugin\n\t\t\t? await signJWT(ctx, {\n\t\t\t\t\toptions: jwtPluginOptions,\n\t\t\t\t\tpayload: {\n\t\t\t\t\t\t...customClaims,\n\t\t\t\t\t\taud: audience,\n\t\t\t\t\t\tazp: client.clientId,\n\t\t\t\t\t\tscope: requestedScopes.join(\" \"),\n\t\t\t\t\t\tiss: jwtPluginOptions?.jwt?.issuer ?? ctx.context.baseURL,\n\t\t\t\t\t\tiat,\n\t\t\t\t\t\texp,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t: await createOpaqueAccessToken(\n\t\t\t\t\tctx,\n\t\t\t\t\topts,\n\t\t\t\t\tundefined,\n\t\t\t\t\tclient,\n\t\t\t\t\trequestedScopes,\n\t\t\t\t\t{\n\t\t\t\t\t\tiat,\n\t\t\t\t\t\texp,\n\t\t\t\t\t},\n\t\t\t\t);\n\n\treturn ctx.json(\n\t\t{\n\t\t\taccess_token: accessToken,\n\t\t\texpires_in: exp - iat,\n\t\t\texpires_at: exp,\n\t\t\ttoken_type: \"Bearer\",\n\t\t\tscope: requestedScopes.join(\" \"),\n\t\t},\n\t\t{\n\t\t\theaders: {\n\t\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t\tPragma: \"no-cache\",\n\t\t\t},\n\t\t},\n\t);\n}\n\n/**\n * Obtains new Session Jwt and Refresh Tokens using a refresh token\n *\n * Refresh tokens will only allow the same or lesser scopes as the initial authorize request.\n * To add scopes, you must restart the authorize process again.\n */\nasync function handleRefreshTokenGrant(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\tlet {\n\t\tclient_id,\n\t\tclient_secret,\n\t\trefresh_token,\n\t\tscope,\n\t}: {\n\t\tclient_id?: string;\n\t\tclient_secret?: string;\n\t\trefresh_token?: string;\n\t\tscope?: string;\n\t} = ctx.body;\n\n\tconst authorization = ctx.request?.headers.get(\"authorization\") || null;\n\n\t// Convert basic authorization\n\tif (authorization?.startsWith(\"Basic \")) {\n\t\tconst res = basicToClientCredentials(authorization);\n\t\tclient_id = res?.client_id;\n\t\tclient_secret = res?.client_secret;\n\t}\n\n\tif (!client_id) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"Missing required client_id\",\n\t\t\terror: \"invalid_grant\",\n\t\t});\n\t}\n\n\tif (!refresh_token) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description:\n\t\t\t\t\"Missing a required refresh_token for refresh_token grant\",\n\t\t\terror: \"invalid_grant\",\n\t\t});\n\t}\n\tconst decodedRefresh = await decodeRefreshToken(opts, refresh_token);\n\n\tconst refreshToken = await ctx.context.adapter.findOne<\n\t\tOAuthRefreshToken<Scope[]> & { id: string }\n\t>({\n\t\tmodel: \"oauthRefreshToken\",\n\t\twhere: [\n\t\t\t{\n\t\t\t\tfield: \"token\",\n\t\t\t\tvalue: await getStoredToken(\n\t\t\t\t\topts.storeTokens,\n\t\t\t\t\tdecodedRefresh.token,\n\t\t\t\t\t\"refresh_token\",\n\t\t\t\t),\n\t\t\t},\n\t\t],\n\t});\n\n\t// Check refresh\n\tif (!refreshToken) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"session not found\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tif (refreshToken.clientId !== client_id) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"invalid client_id\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\tif (refreshToken.expiresAt < new Date()) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"invalid refresh token\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\t// Replay revoke (delete all tokens for that user-client)\n\tif (refreshToken.revoked) {\n\t\tawait ctx.context.adapter.deleteMany({\n\t\t\tmodel: \"oauthRefreshToken\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"clientId\",\n\t\t\t\t\tvalue: client_id,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tfield: \"userId\",\n\t\t\t\t\tvalue: refreshToken.userId,\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"invalid refresh token\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\t// Check session scopes\n\tconst scopes = refreshToken?.scopes;\n\tconst requestedScopes = scope?.split(\" \");\n\tif (requestedScopes) {\n\t\tconst validScopes = new Set(scopes);\n\t\tfor (const requestedScope of requestedScopes) {\n\t\t\tif (!validScopes.has(requestedScope)) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\terror_description: `unable to issue scope ${requestedScope}`,\n\t\t\t\t\terror: \"invalid_scope\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tconst client = await validateClientCredentials(\n\t\tctx,\n\t\topts,\n\t\tclient_id,\n\t\tclient_secret, // Optional for refresh_grant but required on confidential clients\n\t\trequestedScopes ?? scopes,\n\t);\n\n\tconst user = await ctx.context.internalAdapter.findUserById(\n\t\trefreshToken.userId,\n\t);\n\tif (!user) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"user not found\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\t// Generate new tokens\n\treturn createUserTokens(\n\t\tctx,\n\t\topts,\n\t\tclient,\n\t\trequestedScopes ?? scopes,\n\t\tuser,\n\t\trefreshToken.referenceId,\n\t\trefreshToken.sessionId,\n\t\tundefined,\n\t\t{\n\t\t\trefreshToken,\n\t\t},\n\t);\n}\n","import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { logger } from \"@better-auth/core/env\";\nimport { verifyJwsAccessToken } from \"better-auth/oauth2\";\nimport type { Session, User } from \"better-auth/types\";\nimport { APIError } from \"better-call\";\nimport type { JSONWebKeySet, JWTPayload } from \"jose\";\nimport { decodeRefreshToken } from \"./token\";\nimport type {\n\tOAuthOpaqueAccessToken,\n\tOAuthOptions,\n\tOAuthRefreshToken,\n\tSchemaClient,\n\tScope,\n} from \"./types\";\nimport {\n\tbasicToClientCredentials,\n\tgetClient,\n\tgetJwtPlugin,\n\tgetStoredToken,\n\tparseClientMetadata,\n\tvalidateClientCredentials,\n} from \"./utils\";\n\n/**\n * IMPORTANT NOTES:\n * Introspection follows RFC7662\n * https://datatracker.ietf.org/doc/html/rfc7662\n * - APIError: Continue catches (returnable to client)\n * - Error: Should immediately stop catches (internal error)\n */\n\n/**\n * Validates a JWT access token against the configured JWKs.\n *\n * @returns RFC7662 introspection format\n */\nasync function validateJwtAccessToken(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\ttoken: string,\n\tclientId?: string,\n) {\n\tconst jwtPlugin = opts.disableJwtPlugin\n\t\t? undefined\n\t\t: getJwtPlugin(ctx.context);\n\tconst jwtPluginOptions = jwtPlugin?.options;\n\tlet jwtPayload: JWTPayload & {\n\t\tsid?: string;\n\t\tazp?: string;\n\t};\n\n\ttry {\n\t\tjwtPayload = await verifyJwsAccessToken(token, {\n\t\t\tjwksFetch: jwtPluginOptions?.jwks?.remoteUrl\n\t\t\t\t? jwtPluginOptions.jwks.remoteUrl\n\t\t\t\t: async () => {\n\t\t\t\t\t\tconst jwksRes = await jwtPlugin?.endpoints.getJwks(ctx);\n\t\t\t\t\t\t// @ts-expect-error response is a JSONWebKeySet but within the response field\n\t\t\t\t\t\treturn jwksRes?.response as JSONWebKeySet | undefined;\n\t\t\t\t\t},\n\t\t\tverifyOptions: {\n\t\t\t\taudience: opts.validAudiences ?? ctx.context.baseURL,\n\t\t\t\tissuer: jwtPluginOptions?.jwt?.issuer ?? ctx.context.baseURL,\n\t\t\t},\n\t\t});\n\t} catch (error) {\n\t\tif (error instanceof Error) {\n\t\t\tif (error.name === \"TypeError\" || error.name === \"JWSInvalid\") {\n\t\t\t\t// likely an opaque token\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\terror_description: \"invalid JWT signature\",\n\t\t\t\t\terror: \"invalid_request\",\n\t\t\t\t});\n\t\t\t} else if (error.name === \"JWTExpired\") {\n\t\t\t\treturn {\n\t\t\t\t\tactive: false,\n\t\t\t\t};\n\t\t\t} else if (error.name === \"JWTInvalid\") {\n\t\t\t\t// audience or issuer mismatch\n\t\t\t\treturn {\n\t\t\t\t\tactive: false,\n\t\t\t\t};\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tthrow new Error(error as unknown as string);\n\t}\n\n\tlet client: SchemaClient<Scope[]> | null | undefined;\n\tif (jwtPayload.azp) {\n\t\tclient = await getClient(ctx, opts, jwtPayload.azp);\n\t\tif (!client || client?.disabled) {\n\t\t\treturn {\n\t\t\t\tactive: false,\n\t\t\t};\n\t\t}\n\t\tif (clientId && jwtPayload.azp !== clientId) {\n\t\t\treturn {\n\t\t\t\tactive: false,\n\t\t\t};\n\t\t}\n\t}\n\n\t// Validate JWT against its session if it exists\n\tconst sessionId = jwtPayload.sid;\n\tif (sessionId) {\n\t\tconst session = await ctx.context.adapter.findOne<Session>({\n\t\t\tmodel: \"session\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t\tvalue: sessionId,\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\t\tif (!session || session.expiresAt < new Date()) {\n\t\t\tjwtPayload.sid = undefined;\n\t\t}\n\t}\n\n\t// Return the JWT payload in introspection format\n\t// https://datatracker.ietf.org/doc/html/rfc7662#section-2.2\n\tif (jwtPayload.azp) {\n\t\tjwtPayload.client_id = jwtPayload.azp;\n\t}\n\tjwtPayload.active = true;\n\treturn jwtPayload;\n}\n\n/**\n * Searches for an opaque access token in the database and validates it\n *\n * @returns RFC7662 introspection format\n */\nasync function validateOpaqueAccessToken(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\ttoken: string,\n\tclientId?: string,\n) {\n\tlet tokenValue = token;\n\tif (opts.prefix?.opaqueAccessToken) {\n\t\tif (tokenValue.startsWith(opts.prefix.opaqueAccessToken)) {\n\t\t\ttokenValue = tokenValue.replace(opts.prefix.opaqueAccessToken, \"\");\n\t\t} else {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\terror_description: \"opaque access token not found\",\n\t\t\t\terror: \"invalid_request\",\n\t\t\t});\n\t\t}\n\t}\n\tconst accessToken = await ctx.context.adapter.findOne<\n\t\tOAuthOpaqueAccessToken<Scope[]>\n\t>({\n\t\tmodel: \"oauthAccessToken\",\n\t\twhere: [\n\t\t\t{\n\t\t\t\tfield: \"token\",\n\t\t\t\tvalue: await getStoredToken(\n\t\t\t\t\topts.storeTokens,\n\t\t\t\t\ttokenValue,\n\t\t\t\t\t\"access_token\",\n\t\t\t\t),\n\t\t\t},\n\t\t],\n\t});\n\tif (!accessToken) {\n\t\t// Pass through, may be other token type\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"opaque access token not found\",\n\t\t\terror: \"invalid_token\",\n\t\t});\n\t}\n\tif (!accessToken.expiresAt || accessToken.expiresAt < new Date()) {\n\t\treturn {\n\t\t\tactive: false,\n\t\t};\n\t}\n\n\tlet client: SchemaClient<Scope[]> | null | undefined;\n\tif (accessToken.clientId) {\n\t\tclient = await getClient(ctx, opts, accessToken.clientId);\n\t\tif (!client || client?.disabled) {\n\t\t\treturn {\n\t\t\t\tactive: false,\n\t\t\t};\n\t\t}\n\t\tif (clientId && accessToken.clientId !== clientId) {\n\t\t\treturn {\n\t\t\t\tactive: false,\n\t\t\t};\n\t\t}\n\t}\n\n\tlet sessionId = accessToken.sessionId ?? undefined;\n\tif (sessionId) {\n\t\tconst session = await ctx.context.adapter.findOne<Session>({\n\t\t\tmodel: \"session\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t\tvalue: sessionId,\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\t\tif (!session || session.expiresAt < new Date()) {\n\t\t\tsessionId = undefined;\n\t\t}\n\t}\n\n\tlet user: User | null | undefined;\n\tif (accessToken.userId) {\n\t\tuser = await ctx.context.internalAdapter.findUserById(accessToken?.userId);\n\t}\n\n\t// Add Custom Claims\n\tconst customClaims = opts.customAccessTokenClaims\n\t\t? await opts.customAccessTokenClaims({\n\t\t\t\tuser,\n\t\t\t\tscopes: accessToken.scopes,\n\t\t\t\treferenceId: accessToken?.referenceId,\n\t\t\t\tmetadata: parseClientMetadata(client?.metadata),\n\t\t\t})\n\t\t: {};\n\n\t// Return the access token in introspection format\n\t// https://datatracker.ietf.org/doc/html/rfc7662#section-2.2\n\tconst jwtPlugin = opts.disableJwtPlugin\n\t\t? undefined\n\t\t: getJwtPlugin(ctx.context);\n\tconst jwtPluginOptions = jwtPlugin?.options;\n\treturn {\n\t\t...customClaims,\n\t\tactive: true,\n\t\tiss: jwtPluginOptions?.jwt?.issuer ?? ctx.context.baseURL,\n\t\tclient_id: accessToken.clientId,\n\t\tsub: user?.id,\n\t\tsid: sessionId,\n\t\texp: Math.floor(accessToken.expiresAt.getTime() / 1000),\n\t\tiat: Math.floor(accessToken.createdAt.getTime() / 1000),\n\t\tscope: accessToken.scopes?.join(\" \"),\n\t} as JWTPayload;\n}\n\n/**\n * Validates a refresh token in the session store.\n *\n * @returns payload in RFC7662 introspection format\n */\nasync function validateRefreshToken(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\ttoken: string,\n\tclientId: string,\n) {\n\tconst refreshToken = await ctx.context.adapter.findOne<OAuthRefreshToken<\n\t\tScope[]\n\t> | null>({\n\t\tmodel: \"oauthRefreshToken\",\n\t\twhere: [\n\t\t\t{\n\t\t\t\tfield: \"token\",\n\t\t\t\tvalue: await getStoredToken(opts.storeTokens, token, \"refresh_token\"),\n\t\t\t},\n\t\t],\n\t});\n\tif (!refreshToken) {\n\t\t// Pass through may be other token type\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"token not found\",\n\t\t\terror: \"invalid_token\",\n\t\t});\n\t}\n\tif (!refreshToken.clientId || refreshToken.clientId !== clientId) {\n\t\treturn {\n\t\t\tactive: false,\n\t\t};\n\t}\n\tif (!refreshToken.expiresAt || refreshToken.expiresAt < new Date()) {\n\t\treturn {\n\t\t\tactive: false,\n\t\t};\n\t}\n\tif (refreshToken.revoked) {\n\t\treturn {\n\t\t\tactive: false,\n\t\t};\n\t}\n\n\tlet sessionId: string | undefined = refreshToken.sessionId ?? undefined;\n\tif (sessionId) {\n\t\tconst session = await ctx.context.adapter.findOne<Session>({\n\t\t\tmodel: \"session\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t\tvalue: refreshToken.sessionId,\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\t\tif (!session || session.expiresAt < new Date()) {\n\t\t\tsessionId = undefined;\n\t\t}\n\t}\n\n\tlet user: User | undefined = undefined;\n\tif (refreshToken.userId) {\n\t\tuser =\n\t\t\t(await ctx.context.internalAdapter.findUserById(refreshToken?.userId)) ??\n\t\t\tundefined;\n\t}\n\n\t// Return the access token in introspection format\n\t// https://datatracker.ietf.org/doc/html/rfc7662#section-2.2\n\tconst jwtPlugin = opts.disableJwtPlugin\n\t\t? undefined\n\t\t: getJwtPlugin(ctx.context);\n\tconst jwtPluginOptions = jwtPlugin?.options;\n\n\treturn {\n\t\tactive: true,\n\t\tclient_id: clientId,\n\t\tiss: jwtPluginOptions?.jwt?.issuer ?? ctx.context.baseURL,\n\t\tsub: user?.id,\n\t\tsid: sessionId,\n\t\texp: Math.floor(refreshToken.expiresAt.getTime() / 1000),\n\t\tiat: Math.floor(refreshToken.createdAt.getTime() / 1000),\n\t\tscope: refreshToken.scopes?.join(\" \"),\n\t} as JWTPayload;\n}\n\n/**\n * We don't know the access token format so we try to validate it\n * as a JWT first, then as an opaque token.\n *\n * @returns RFC7662 introspection format\n *\n * @internal\n */\nexport async function validateAccessToken(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\ttoken: string,\n\tclientId?: string,\n) {\n\ttry {\n\t\treturn await validateJwtAccessToken(ctx, opts, token, clientId);\n\t} catch (err) {\n\t\tif (err instanceof APIError) {\n\t\t\t// continue\n\t\t} else if (err instanceof Error) {\n\t\t\tthrow err;\n\t\t} else {\n\t\t\tthrow new Error(err as unknown as string);\n\t\t}\n\t}\n\ttry {\n\t\treturn await validateOpaqueAccessToken(ctx, opts, token, clientId);\n\t} catch (err) {\n\t\tif (err instanceof APIError) {\n\t\t\t// nothing\n\t\t} else if (err instanceof Error) {\n\t\t\tthrow err;\n\t\t} else {\n\t\t\tthrow new Error(\"Unknown error validating access token\");\n\t\t}\n\t}\n\tthrow new APIError(\"BAD_REQUEST\", {\n\t\terror_description: \"Invalid access token\",\n\t\terror: \"invalid_request\",\n\t});\n}\n\nexport async function introspectEndpoint(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\tlet {\n\t\tclient_id,\n\t\tclient_secret,\n\t\ttoken,\n\t\ttoken_type_hint,\n\t}: {\n\t\tclient_id?: string;\n\t\tclient_secret?: string;\n\t\ttoken: string;\n\t\ttoken_type_hint?: \"access_token\" | \"refresh_token\";\n\t} = ctx.body;\n\n\t// Convert basic authorization\n\tconst authorization = ctx.request?.headers.get(\"authorization\") || null;\n\tif (authorization?.startsWith(\"Basic \")) {\n\t\tconst res = basicToClientCredentials(authorization);\n\t\tclient_id = res?.client_id;\n\t\tclient_secret = res?.client_secret;\n\t}\n\tif (!client_id || !client_secret) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"missing required credentials\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\n\t// Check token\n\tif (token && typeof token === \"string\" && token.startsWith(\"Bearer \")) {\n\t\ttoken = token.replace(\"Bearer \", \"\");\n\t}\n\tif (!token?.length) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"missing a required token for introspection\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\t// Validate client credentials\n\tconst client = await validateClientCredentials(\n\t\tctx,\n\t\topts,\n\t\tclient_id,\n\t\tclient_secret,\n\t);\n\n\ttry {\n\t\tif (token_type_hint === undefined || token_type_hint === \"access_token\") {\n\t\t\ttry {\n\t\t\t\tconst payload = await validateAccessToken(\n\t\t\t\t\tctx,\n\t\t\t\t\topts,\n\t\t\t\t\ttoken,\n\t\t\t\t\tclient.clientId,\n\t\t\t\t);\n\t\t\t\treturn payload;\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof APIError) {\n\t\t\t\t\tif (token_type_hint === \"access_token\") {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t} // else continue\n\t\t\t\t} else if (error instanceof Error) {\n\t\t\t\t\tthrow error;\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(error as unknown as string);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (token_type_hint === undefined || token_type_hint === \"refresh_token\") {\n\t\t\ttry {\n\t\t\t\tconst refreshToken = await decodeRefreshToken(opts, token);\n\t\t\t\tconst payload = await validateRefreshToken(\n\t\t\t\t\tctx,\n\t\t\t\t\topts,\n\t\t\t\t\trefreshToken.token,\n\t\t\t\t\tclient.clientId,\n\t\t\t\t);\n\t\t\t\treturn payload;\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof APIError) {\n\t\t\t\t\tif (token_type_hint === \"refresh_token\") {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t} // else continue\n\t\t\t\t} else if (error instanceof Error) {\n\t\t\t\t\tthrow error;\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(error as unknown as string);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"token not found\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t} catch (error) {\n\t\tif (error instanceof APIError) {\n\t\t\tif (error.name === \"BAD_REQUEST\") {\n\t\t\t\treturn {\n\t\t\t\t\tactive: false,\n\t\t\t\t};\n\t\t\t}\n\t\t\tthrow error;\n\t\t} else if (error instanceof Error) {\n\t\t\tlogger.error(\"Introspection error:\", error.message, error.stack);\n\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\");\n\t\t} else {\n\t\t\tlogger.error(\"Introspection error:\", error);\n\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\");\n\t\t}\n\t}\n}\n","import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { getJwks } from \"better-auth/oauth2\";\nimport type { Session } from \"better-auth/types\";\nimport { APIError } from \"better-call\";\nimport type { JWTPayload } from \"jose\";\nimport { compactVerify, createLocalJWKSet, decodeJwt } from \"jose\";\nimport { handleRedirect } from \"./authorize\";\nimport type { OAuthOptions, Scope } from \"./types\";\nimport { decryptStoredClientSecret, getClient, getJwtPlugin } from \"./utils\";\n\n/**\n * IMPORTANT NOTES:\n * Follows OIDC RP-Initiated Logout\n *\n * @see https://openid.net/specs/openid-connect-rpinitiated-1_0.html\n */\nexport async function rpInitiatedLogoutEndpoint(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\tconst {\n\t\tid_token_hint,\n\t\tclient_id,\n\t\tpost_logout_redirect_uri,\n\t\tstate,\n\t}: {\n\t\t// Spec says `id_token_hint` recommended but we make it required for DOS\n\t\tid_token_hint: string;\n\t\tclient_id?: string;\n\t\tpost_logout_redirect_uri?: string;\n\t\tstate?: string;\n\t} = ctx.query;\n\n\tconst baseURL = ctx.context.baseURL;\n\tconst jwtPlugin = opts.disableJwtPlugin\n\t\t? undefined\n\t\t: getJwtPlugin(ctx.context);\n\tconst jwtPluginOptions = jwtPlugin?.options;\n\tconst jwksUrl =\n\t\tjwtPluginOptions?.jwks?.remoteUrl ??\n\t\t`${baseURL}${jwtPluginOptions?.jwks?.jwksPath ?? \"/jwks\"}`;\n\n\tlet clientId = client_id;\n\tif (!clientId) {\n\t\tlet decoded: JWTPayload;\n\t\ttry {\n\t\t\tdecoded = decodeJwt(id_token_hint);\n\t\t} catch (_e) {\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\terror_description: \"invalid id token\",\n\t\t\t\terror: \"invalid_token\",\n\t\t\t});\n\t\t}\n\t\tclientId = decoded?.aud as string | undefined;\n\t\tif (!clientId) {\n\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\terror_description: \"id token missing audience\",\n\t\t\t\terror: \"invalid_request\",\n\t\t\t});\n\t\t}\n\t}\n\n\t// Only specified trusted clients can logout via the rpInitiated logout\n\tconst client = await getClient(ctx, opts, clientId);\n\tif (!client) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"client doesn't exist\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\tif (client.disabled) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"client is disabled\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\tif (!client.enableEndSession) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"client unable to logout\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\n\t// Obtain idTokenPayload\n\tlet idTokenPayload: JWTPayload | undefined;\n\tif (opts.disableJwtPlugin) {\n\t\t// Get the client's secret to verify the token\n\t\tconst clientSecret = client.clientSecret;\n\t\tif (!clientSecret) {\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\terror_description: \"missing required credentials\",\n\t\t\t\terror: \"invalid_client\",\n\t\t\t});\n\t\t}\n\n\t\t// Convert the client secret to a key\n\t\tconst secret = await decryptStoredClientSecret(\n\t\t\tctx,\n\t\t\topts.storeClientSecret,\n\t\t\tclientSecret,\n\t\t);\n\t\tconst key = new TextEncoder().encode(secret);\n\n\t\t// compactVerify only verifies the token, not its claims (perform manually)\n\t\tconst { payload } = await compactVerify(id_token_hint, key);\n\t\tconst idToken = new TextDecoder().decode(payload);\n\t\tidTokenPayload = JSON.parse(idToken);\n\t} else {\n\t\tconst jwks = await getJwks(id_token_hint, {\n\t\t\tjwksFetch: jwksUrl,\n\t\t});\n\n\t\t// compactVerify only verifies the token, not its claims (perform manually)\n\t\tconst { payload } = await compactVerify(\n\t\t\tid_token_hint,\n\t\t\tcreateLocalJWKSet(jwks),\n\t\t);\n\t\tconst idToken = new TextDecoder().decode(payload);\n\t\tidTokenPayload = JSON.parse(idToken);\n\t}\n\n\tif (!idTokenPayload) {\n\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\terror_description: \"missing payload\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\tconst issuer = jwtPluginOptions?.jwt?.issuer ?? ctx.context.baseURL;\n\tif (issuer !== idTokenPayload.iss) {\n\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\terror_description: \"invalid issuer\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\tconst idTokenAudience =\n\t\ttypeof idTokenPayload.aud === \"string\"\n\t\t\t? [idTokenPayload.aud]\n\t\t\t: idTokenPayload.aud;\n\tif (!idTokenAudience) {\n\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\terror_description: \"id token missing audience\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tif (client_id && !idTokenAudience.includes(client_id)) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"audience mismatch\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tconst sessionId = idTokenPayload.sid as string | undefined;\n\n\t// Logout using the sid attached to the idToken\n\tif (!sessionId) {\n\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\terror_description: \"id token missing session\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\ttry {\n\t\tconst session = await ctx.context.adapter.findOne<Session>({\n\t\t\tmodel: \"session\",\n\t\t\twhere: [{ field: \"id\", value: sessionId }],\n\t\t});\n\t\tsession?.token\n\t\t\t? await ctx.context.internalAdapter.deleteSession(session?.token)\n\t\t\t: session?.id\n\t\t\t\t? await ctx.context.adapter.delete<Session>({\n\t\t\t\t\t\tmodel: \"session\",\n\t\t\t\t\t\twhere: [{ field: \"id\", value: session.id }],\n\t\t\t\t\t})\n\t\t\t\t: await ctx.context.adapter.delete<Session>({\n\t\t\t\t\t\tmodel: \"session\",\n\t\t\t\t\t\twhere: [{ field: \"id\", value: sessionId }],\n\t\t\t\t\t});\n\t} catch {\n\t\t// continue - session already deleted\n\t}\n\n\t// Redirect to post_logout_redirect_uri if provided and exact match (no need to fail)\n\tif (post_logout_redirect_uri) {\n\t\tconst registeredUris = client.postLogoutRedirectUris;\n\t\tif (registeredUris?.includes(post_logout_redirect_uri)) {\n\t\t\tconst redirectUri = new URL(post_logout_redirect_uri);\n\t\t\tif (state) {\n\t\t\t\tredirectUri.searchParams.set(\"state\", state);\n\t\t\t}\n\t\t\treturn handleRedirect(ctx, redirectUri.toString());\n\t\t}\n\t}\n}\n","import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { APIError, getSessionFromCtx } from \"better-auth/api\";\nimport { generateRandomString } from \"better-auth/crypto\";\nimport { toExpJWT } from \"better-auth/plugins\";\nimport type { OAuthOptions, SchemaClient, Scope } from \"./types\";\nimport type { OAuthClient } from \"./types/oauth\";\nimport { parseClientMetadata, storeClientSecret } from \"./utils\";\n\nexport async function registerEndpoint(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\t// Check if registration endpoint is enabled\n\tif (!opts.allowDynamicClientRegistration) {\n\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\terror: \"access_denied\",\n\t\t\terror_description: \"Client registration is disabled\",\n\t\t});\n\t}\n\n\tconst body = ctx.body as OAuthClient;\n\tconst session = await getSessionFromCtx(ctx);\n\n\t// Check authorization\n\tif (!(session || opts.allowUnauthenticatedClientRegistration)) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror: \"invalid_token\",\n\t\t\terror_description: \"Authentication required for client registration\",\n\t\t});\n\t}\n\n\t// Determine whether registration request for public client\n\t// https://datatracker.ietf.org/doc/html/rfc7591#section-2\n\tconst isPublic = body.token_endpoint_auth_method === \"none\";\n\n\t// Check unauthenticated user is requesting a confidential client\n\tif (!session && !isPublic) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror: \"invalid_request\",\n\t\t\terror_description:\n\t\t\t\t\"Authentication required for confidential client registration\",\n\t\t});\n\t}\n\n\t// Ensure dynamically registered clients shall have a scope\n\tif (!ctx.body.scope) {\n\t\tctx.body.scope = (\n\t\t\topts.clientRegistrationDefaultScopes ?? opts.scopes\n\t\t)?.join(\" \");\n\t}\n\n\treturn createOAuthClientEndpoint(ctx, opts, {\n\t\tisRegister: true,\n\t});\n}\n\nexport async function checkOAuthClient(\n\tclient: OAuthClient,\n\topts: OAuthOptions<Scope[]>,\n\tsettings?: {\n\t\tisRegister?: boolean;\n\t},\n) {\n\t// Determine whether registration request for public client\n\t// https://datatracker.ietf.org/doc/html/rfc7591#section-2\n\tconst isPublic = client.token_endpoint_auth_method === \"none\";\n\n\t// Check value of type, if sent, matches isPublic\n\tif (client.type) {\n\t\tif (\n\t\t\tisPublic &&\n\t\t\t!(client.type === \"native\" || client.type === \"user-agent-based\")\n\t\t) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\terror: \"invalid_client_metadata\",\n\t\t\t\terror_description: `Type must be 'native' or 'user-agent-based' for public applications`,\n\t\t\t});\n\t\t} else if (!isPublic && !(client.type === \"web\")) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\terror: \"invalid_client_metadata\",\n\t\t\t\terror_description: `Type must be 'web' for confidential applications`,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Validate redirect URIs for redirect-based flows\n\tif (\n\t\t(!client.grant_types ||\n\t\t\tclient.grant_types.includes(\"authorization_code\")) &&\n\t\t(!client.redirect_uris || client.redirect_uris.length === 0)\n\t) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror: \"invalid_redirect_uri\",\n\t\t\terror_description:\n\t\t\t\t\"Redirect URIs are required for authorization_code and implicit grant types\",\n\t\t});\n\t}\n\n\t// Validate correlation between grant_types and response_types\n\tconst grantTypes = client.grant_types ?? [\"authorization_code\"];\n\tconst responseTypes = client.response_types ?? [\"code\"];\n\tif (\n\t\tgrantTypes.includes(\"authorization_code\") &&\n\t\t!responseTypes.includes(\"code\")\n\t) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror: \"invalid_client_metadata\",\n\t\t\terror_description:\n\t\t\t\t\"When 'authorization_code' grant type is used, 'code' response type must be included\",\n\t\t});\n\t}\n\n\t// Check requested application scopes\n\tconst requestedScopes = (client?.scope as string | undefined)\n\t\t?.split(\" \")\n\t\t.filter((v) => v.length);\n\tconst allowedScopes = settings?.isRegister\n\t\t? (opts.clientRegistrationAllowedScopes ?? opts.scopes)\n\t\t: opts.scopes;\n\tif (allowedScopes) {\n\t\tconst validScopes = new Set(allowedScopes);\n\t\tfor (const requestedScope of requestedScopes ?? []) {\n\t\t\tif (!validScopes?.has(requestedScope)) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\terror: \"invalid_scope\",\n\t\t\t\t\terror_description: `cannot request scope ${requestedScope}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport async function createOAuthClientEndpoint(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\tsettings: {\n\t\tisRegister: boolean;\n\t},\n) {\n\tconst body = ctx.body as OAuthClient;\n\tconst session = await getSessionFromCtx(ctx);\n\n\t// Determine whether registration request for public client\n\t// https://datatracker.ietf.org/doc/html/rfc7591#section-2\n\tconst isPublic = body.token_endpoint_auth_method === \"none\";\n\n\t// Check if client parameters are valid combination\n\tawait checkOAuthClient(ctx.body, opts, settings);\n\n\t// Generate clientId and clientSecret based on its type\n\tconst clientId =\n\t\topts.generateClientId?.() || generateRandomString(32, \"a-z\", \"A-Z\");\n\tconst clientSecret = isPublic\n\t\t? undefined\n\t\t: opts.generateClientSecret?.() || generateRandomString(32, \"a-z\", \"A-Z\");\n\tconst storedClientSecret = clientSecret\n\t\t? await storeClientSecret(ctx, opts, clientSecret)\n\t\t: undefined;\n\n\t// Create the client with the existing schema\n\tconst iat = Math.floor(Date.now() / 1000);\n\tconst referenceId = opts.clientReference\n\t\t? await opts.clientReference({\n\t\t\t\tuser: session?.user,\n\t\t\t\tsession: session?.session,\n\t\t\t})\n\t\t: undefined;\n\tconst schema = oauthToSchema({\n\t\t...((body ?? {}) as OAuthClient),\n\t\t// Dynamic registration should not have disabled defined\n\t\tdisabled: undefined,\n\t\t// Jwks unsupported\n\t\tjwks: undefined,\n\t\tjwks_uri: undefined,\n\t\t// Required if client secret is issued\n\t\tclient_secret_expires_at: storedClientSecret\n\t\t\t? settings.isRegister && opts?.clientRegistrationClientSecretExpiration\n\t\t\t\t? toExpJWT(opts.clientRegistrationClientSecretExpiration, iat)\n\t\t\t\t: 0\n\t\t\t: undefined,\n\t\t// Override\n\t\tclient_id: clientId,\n\t\tclient_secret: storedClientSecret,\n\t\tclient_id_issued_at: iat,\n\t\tpublic: isPublic,\n\t\tuser_id: referenceId ? undefined : session?.session.userId,\n\t\treference_id: referenceId,\n\t});\n\tconst client = await ctx.context.adapter.create<SchemaClient<Scope[]>>({\n\t\tmodel: \"oauthClient\",\n\t\tdata: schema,\n\t});\n\t// Format the response according to RFC7591\n\treturn ctx.json(\n\t\tschemaToOAuth({\n\t\t\t...client,\n\t\t\tclientSecret: clientSecret\n\t\t\t\t? (opts.prefix?.clientSecret ?? \"\") + clientSecret\n\t\t\t\t: undefined,\n\t\t}),\n\t\t{\n\t\t\tstatus: 201,\n\t\t\theaders: {\n\t\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t\tPragma: \"no-cache\",\n\t\t\t},\n\t\t},\n\t);\n}\n\n/**\n * Converts an OAuth 2.0 Dynamic Client Schema to a Database Schema\n *\n * @param input\n * @returns\n */\nexport function oauthToSchema(input: OAuthClient): SchemaClient<Scope[]> {\n\tconst {\n\t\t// Important Fields\n\t\tclient_id: clientId,\n\t\tclient_secret: clientSecret,\n\t\tclient_secret_expires_at: _expiresAt,\n\t\tscope: _scope,\n\t\t// Recommended client data\n\t\tuser_id: userId,\n\t\tclient_id_issued_at: _createdAt,\n\t\t// UI Metadata\n\t\tclient_name: name,\n\t\tclient_uri: uri,\n\t\tlogo_uri: icon,\n\t\tcontacts,\n\t\ttos_uri: tos,\n\t\tpolicy_uri: policy,\n\t\t// Jwks (only one can be used)\n\t\tjwks: _jwks,\n\t\tjwks_uri: _jwksUri,\n\t\t// User Software Identifiers\n\t\tsoftware_id: softwareId,\n\t\tsoftware_version: softwareVersion,\n\t\tsoftware_statement: softwareStatement,\n\t\t// Authentication Metadata\n\t\tredirect_uris: redirectUris,\n\t\tpost_logout_redirect_uris: postLogoutRedirectUris,\n\t\ttoken_endpoint_auth_method: tokenEndpointAuthMethod,\n\t\tgrant_types: grantTypes,\n\t\tresponse_types: responseTypes,\n\t\t// RFC6749 Spec\n\t\tpublic: _public,\n\t\ttype,\n\t\t// Not Part of RFC7591 Spec\n\t\tdisabled,\n\t\tskip_consent: skipConsent,\n\t\tenable_end_session: enableEndSession,\n\t\treference_id: referenceId,\n\t\tmetadata: inputMetadata,\n\t\t// All other metadata\n\t\t...rest\n\t} = input;\n\n\t// Type conversions\n\tconst expiresAt = _expiresAt ? new Date(_expiresAt * 1000) : undefined;\n\tconst createdAt = _createdAt ? new Date(_createdAt * 1000) : undefined;\n\tconst scopes = _scope?.split(\" \");\n\tconst metadataObj = {\n\t\t...(rest && Object.keys(rest).length ? rest : {}),\n\t\t...(inputMetadata && typeof inputMetadata === \"object\"\n\t\t\t? inputMetadata\n\t\t\t: {}),\n\t};\n\tconst metadata = Object.keys(metadataObj).length\n\t\t? JSON.stringify(metadataObj)\n\t\t: undefined;\n\n\treturn {\n\t\t// Important Fields\n\t\tclientId,\n\t\tclientSecret,\n\t\tdisabled,\n\t\tscopes,\n\t\t// Recommended client data\n\t\tuserId,\n\t\tcreatedAt,\n\t\texpiresAt,\n\t\t// UI Metadata\n\t\tname,\n\t\turi,\n\t\ticon,\n\t\tcontacts,\n\t\ttos,\n\t\tpolicy,\n\t\t// User Software Identifiers\n\t\tsoftwareId,\n\t\tsoftwareVersion,\n\t\tsoftwareStatement,\n\t\t// Authentication Metadata\n\t\tredirectUris,\n\t\tpostLogoutRedirectUris,\n\t\ttokenEndpointAuthMethod,\n\t\tgrantTypes,\n\t\tresponseTypes,\n\t\t// RFC6749 Spec\n\t\tpublic: _public,\n\t\ttype,\n\t\t// All other metadata\n\t\tskipConsent,\n\t\tenableEndSession,\n\t\treferenceId,\n\t\tmetadata,\n\t};\n}\n\n/**\n * Converts a Database Schema to an OAuth 2.0 Dynamic Client Schema\n * @param input\n * @param cleaned - default true, determines if the output has only Oauth 2.0 compatible data\n * @returns\n */\nexport function schemaToOAuth(input: SchemaClient<Scope[]>): OAuthClient {\n\tconst {\n\t\t// Important Fields\n\t\tclientId,\n\t\tclientSecret,\n\t\tdisabled,\n\t\tscopes,\n\t\t// Recommended client data\n\t\tuserId,\n\t\tcreatedAt,\n\t\tupdatedAt: _updatedAt,\n\t\texpiresAt,\n\t\t// UI Metadata\n\t\tname,\n\t\turi,\n\t\ticon,\n\t\tcontacts,\n\t\ttos,\n\t\tpolicy,\n\t\t// User Software Identifiers\n\t\tsoftwareId,\n\t\tsoftwareVersion,\n\t\tsoftwareStatement,\n\t\t// Authentication Metadata\n\t\tredirectUris,\n\t\tpostLogoutRedirectUris,\n\t\ttokenEndpointAuthMethod,\n\t\tgrantTypes,\n\t\tresponseTypes,\n\t\t// RFC6749 Spec\n\t\tpublic: _public,\n\t\ttype,\n\t\t// All other metadata\n\t\tskipConsent,\n\t\tenableEndSession,\n\t\treferenceId,\n\t\tmetadata, // in JSON format\n\t} = input;\n\n\t// Type conversions\n\tconst _expiresAt = expiresAt\n\t\t? Math.round(expiresAt.getTime() / 1000)\n\t\t: undefined;\n\tconst _createdAt = createdAt\n\t\t? Math.round(createdAt.getTime() / 1000)\n\t\t: undefined;\n\tconst _scopes = scopes?.join(\" \");\n\tconst _metadata = parseClientMetadata(metadata);\n\n\treturn {\n\t\t// All other metadata\n\t\t..._metadata,\n\t\t// Important Fields\n\t\tclient_id: clientId,\n\t\tclient_secret: clientSecret ?? undefined,\n\t\tclient_secret_expires_at: clientSecret ? (_expiresAt ?? 0) : undefined,\n\t\tscope: _scopes ?? undefined,\n\t\t// Recommended client data\n\t\tuser_id: userId ?? undefined,\n\t\tclient_id_issued_at: _createdAt ?? undefined,\n\t\t// UI Metadata\n\t\tclient_name: name ?? undefined,\n\t\tclient_uri: uri ?? undefined,\n\t\tlogo_uri: icon ?? undefined,\n\t\tcontacts: contacts ?? undefined,\n\t\ttos_uri: tos ?? undefined,\n\t\tpolicy_uri: policy ?? undefined,\n\t\t// Jwks (only one can be used)\n\t\t// jwks, // Not Stored\n\t\t// jwks_uri: jwksUri, // Not Stored\n\t\t// User Software Identifiers\n\t\tsoftware_id: softwareId ?? undefined,\n\t\tsoftware_version: softwareVersion ?? undefined,\n\t\tsoftware_statement: softwareStatement ?? undefined,\n\t\t// Authentication Metadata\n\t\tredirect_uris: redirectUris ?? undefined,\n\t\tpost_logout_redirect_uris: postLogoutRedirectUris ?? undefined,\n\t\ttoken_endpoint_auth_method: tokenEndpointAuthMethod ?? undefined,\n\t\tgrant_types: grantTypes ?? undefined,\n\t\tresponse_types: responseTypes ?? undefined,\n\t\t// RFC6749 Spec\n\t\tpublic: _public ?? undefined,\n\t\ttype: type ?? undefined,\n\t\t// Not Part of RFC7591 Spec\n\t\tdisabled: disabled ?? undefined,\n\t\tskip_consent: skipConsent ?? undefined,\n\t\tenable_end_session: enableEndSession ?? undefined,\n\t\treference_id: referenceId ?? undefined,\n\t};\n}\n","import * as z from \"zod\";\n\n/**\n * Reusable URL validation that disallows javascript: scheme\n */\nexport const SafeUrlSchema = z\n\t.url()\n\t.superRefine((val, ctx) => {\n\t\tif (!URL.canParse(val)) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tmessage: \"URL must be parseable\",\n\t\t\t\tfatal: true,\n\t\t\t});\n\t\t\treturn z.NEVER;\n\t\t}\n\t})\n\t.refine(\n\t\t(url) => {\n\t\t\tconst u = new URL(url);\n\t\t\treturn (\n\t\t\t\tu.protocol !== \"javascript:\" &&\n\t\t\t\tu.protocol !== \"data:\" &&\n\t\t\t\tu.protocol !== \"vbscript:\"\n\t\t\t);\n\t\t},\n\t\t{ message: \"URL cannot use javascript:, data:, or vbscript: scheme\" },\n\t);\n","import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { APIError, getSessionFromCtx } from \"better-auth/api\";\nimport { generateRandomString } from \"better-auth/crypto\";\nimport { checkOAuthClient, oauthToSchema, schemaToOAuth } from \"../register\";\nimport type { OAuthOptions, SchemaClient, Scope } from \"../types\";\nimport type { OAuthClient } from \"../types/oauth\";\nimport { getClient, storeClientSecret } from \"../utils\";\n\nexport async function getClientEndpoint(\n\tctx: GenericEndpointContext & { query: { client_id: string } },\n\topts: OAuthOptions<Scope[]>,\n) {\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session) throw new APIError(\"UNAUTHORIZED\");\n\tif (!ctx.headers) throw new APIError(\"BAD_REQUEST\");\n\tif (\n\t\topts.clientPrivileges &&\n\t\t!(await opts.clientPrivileges({\n\t\t\theaders: ctx.headers,\n\t\t\taction: \"read\",\n\t\t\tsession: session.session,\n\t\t\tuser: session.user,\n\t\t}))\n\t) {\n\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t}\n\n\tconst client = await getClient(ctx, opts, ctx.query.client_id);\n\tif (!client) {\n\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\terror_description: \"client not found\",\n\t\t\terror: \"not_found\",\n\t\t});\n\t}\n\n\tif (client.userId) {\n\t\tif (client.userId !== session.user.id) throw new APIError(\"UNAUTHORIZED\");\n\t} else if (client.referenceId && opts.clientReference) {\n\t\tif (client.referenceId !== (await opts.clientReference(session)))\n\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t} else {\n\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t}\n\n\t// Never return @internal client_secret\n\tconst res = schemaToOAuth(client);\n\tres.client_secret = undefined;\n\treturn res;\n}\n\n/**\n * Provides public client fields for any logged-in user.\n * This is commonly used to display information on login flow pages.\n */\nexport async function getClientPublicEndpoint(\n\tctx: GenericEndpointContext & { query: { client_id: string } },\n\topts: OAuthOptions<Scope[]>,\n) {\n\tconst client = await getClient(ctx, opts, ctx.query.client_id);\n\tif (!client) {\n\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\terror_description: \"client not found\",\n\t\t\terror: \"not_found\",\n\t\t});\n\t}\n\tif (client.disabled) {\n\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\terror_description: \"client not found\",\n\t\t\terror: \"not_found\",\n\t\t});\n\t}\n\t// Manually provide common client fields for login flow pages\n\tconst res = schemaToOAuth({\n\t\tclientId: client.clientId,\n\t\tname: client.name,\n\t\turi: client.uri,\n\t\tcontacts: client.contacts,\n\t\ticon: client.icon,\n\t\ttos: client.tos,\n\t\tpolicy: client.policy,\n\t});\n\treturn res;\n}\n\nexport async function getClientsEndpoint(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session) throw new APIError(\"UNAUTHORIZED\");\n\tif (!ctx.headers) throw new APIError(\"BAD_REQUEST\");\n\tif (\n\t\topts.clientPrivileges &&\n\t\t!(await opts.clientPrivileges({\n\t\t\theaders: ctx.headers,\n\t\t\taction: \"list\",\n\t\t\tsession: session.session,\n\t\t\tuser: session.user,\n\t\t}))\n\t) {\n\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t}\n\n\tconst referenceId = await opts.clientReference?.(session);\n\tif (referenceId) {\n\t\tconst dbClients = await ctx.context.adapter\n\t\t\t.findMany<SchemaClient<Scope[]>>({\n\t\t\t\tmodel: \"oauthClient\",\n\t\t\t\twhere: [{ field: \"referenceId\", value: referenceId }],\n\t\t\t})\n\t\t\t.then((res) => {\n\t\t\t\tif (!res) return null;\n\t\t\t\treturn res.map((v) => {\n\t\t\t\t\tconst res = schemaToOAuth(v);\n\t\t\t\t\tres.client_secret = undefined;\n\t\t\t\t\treturn res;\n\t\t\t\t});\n\t\t\t});\n\t\treturn dbClients;\n\t} else if (session.user.id) {\n\t\tconst dbClients = await ctx.context.adapter\n\t\t\t.findMany<SchemaClient<Scope[]>>({\n\t\t\t\tmodel: \"oauthClient\",\n\t\t\t\twhere: [{ field: \"userId\", value: session.user.id }],\n\t\t\t})\n\t\t\t.then((res) => {\n\t\t\t\tif (!res) return null;\n\t\t\t\treturn res.map((v) => {\n\t\t\t\t\tconst res = schemaToOAuth(v);\n\t\t\t\t\tres.client_secret = undefined;\n\t\t\t\t\treturn res;\n\t\t\t\t});\n\t\t\t});\n\t\treturn dbClients;\n\t} else {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\tmessage: \"either user_id or reference_id must be provided\",\n\t\t});\n\t}\n}\n\nexport async function deleteClientEndpoint(\n\tctx: GenericEndpointContext & { body: { client_id: string } },\n\topts: OAuthOptions<Scope[]>,\n) {\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session) throw new APIError(\"UNAUTHORIZED\");\n\tif (!ctx.headers) throw new APIError(\"BAD_REQUEST\");\n\tif (\n\t\topts.clientPrivileges &&\n\t\t!(await opts.clientPrivileges({\n\t\t\theaders: ctx.headers,\n\t\t\taction: \"delete\",\n\t\t\tsession: session.session,\n\t\t\tuser: session.user,\n\t\t}))\n\t) {\n\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t}\n\n\tconst clientId = ctx.body.client_id;\n\tconst trustedClient = opts.cachedTrustedClients?.has(clientId);\n\tif (trustedClient) {\n\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\terror_description: \"trusted clients must be updated manually\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\n\tconst client = await getClient(ctx, opts, clientId);\n\tif (!client) {\n\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\terror_description: \"client not found\",\n\t\t\terror: \"not_found\",\n\t\t});\n\t}\n\n\tif (client.userId) {\n\t\tif (client.userId !== session.user.id) throw new APIError(\"UNAUTHORIZED\");\n\t} else if (client.referenceId && opts.clientReference) {\n\t\tif (client.referenceId !== (await opts.clientReference(session)))\n\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t} else {\n\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t}\n\n\tawait ctx.context.adapter.delete({\n\t\tmodel: \"oauthClient\",\n\t\twhere: [\n\t\t\t{\n\t\t\t\tfield: \"clientId\",\n\t\t\t\tvalue: clientId,\n\t\t\t},\n\t\t],\n\t});\n}\n\nexport async function updateClientEndpoint(\n\tctx: GenericEndpointContext & {\n\t\tbody: {\n\t\t\tclient_id: string;\n\t\t\tupdate: Omit<Partial<OAuthClient>, \"client_id\">;\n\t\t};\n\t},\n\topts: OAuthOptions<Scope[]>,\n) {\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session) throw new APIError(\"UNAUTHORIZED\");\n\tif (!ctx.headers) throw new APIError(\"BAD_REQUEST\");\n\tif (\n\t\topts.clientPrivileges &&\n\t\t!(await opts.clientPrivileges({\n\t\t\theaders: ctx.headers,\n\t\t\taction: \"update\",\n\t\t\tsession: session.session,\n\t\t\tuser: session.user,\n\t\t}))\n\t) {\n\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t}\n\n\tconst clientId = ctx.body.client_id;\n\tconst trustedClient = opts.cachedTrustedClients?.has(clientId);\n\tif (trustedClient) {\n\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\terror_description: \"trusted clients must be updated manually\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\n\tconst client = await getClient(ctx, opts, clientId);\n\tif (!client) {\n\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\terror_description: \"client not found\",\n\t\t\terror: \"not_found\",\n\t\t});\n\t}\n\n\tif (client.userId) {\n\t\tif (client.userId !== session.user.id) throw new APIError(\"UNAUTHORIZED\");\n\t} else if (client.referenceId && opts.clientReference) {\n\t\tif (client.referenceId !== (await opts.clientReference(session)))\n\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t} else {\n\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t}\n\n\tconst updates = ctx.body.update as OAuthClient;\n\tif (Object.keys(updates).length === 0) {\n\t\t// Never return @internal client_secret\n\t\tconst res = schemaToOAuth(client);\n\t\tres.client_secret = undefined;\n\t\treturn res;\n\t}\n\n\tawait checkOAuthClient(\n\t\t{\n\t\t\t...schemaToOAuth(client),\n\t\t\t...updates,\n\t\t},\n\t\topts,\n\t);\n\tconst updatedClient = await ctx.context.adapter.update<SchemaClient<Scope[]>>(\n\t\t{\n\t\t\tmodel: \"oauthClient\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"clientId\",\n\t\t\t\t\tvalue: clientId,\n\t\t\t\t},\n\t\t\t],\n\t\t\tupdate: oauthToSchema(updates),\n\t\t},\n\t);\n\tif (!updatedClient) {\n\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\terror_description: \"unable to update client\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\t// Never return @internal client_secret\n\tconst res = schemaToOAuth(updatedClient);\n\tres.client_secret = undefined;\n\treturn res;\n}\n\nexport async function rotateClientSecretEndpoint(\n\tctx: GenericEndpointContext & { body: { client_id: string } },\n\topts: OAuthOptions<Scope[]>,\n) {\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session) throw new APIError(\"UNAUTHORIZED\");\n\tif (!ctx.headers) throw new APIError(\"BAD_REQUEST\");\n\tif (\n\t\topts.clientPrivileges &&\n\t\t!(await opts.clientPrivileges({\n\t\t\theaders: ctx.headers,\n\t\t\taction: \"rotate\",\n\t\t\tsession: session.session,\n\t\t\tuser: session.user,\n\t\t}))\n\t) {\n\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t}\n\n\tconst clientId = ctx.body.client_id;\n\tconst trustedClient = opts.cachedTrustedClients?.has(clientId);\n\tif (trustedClient) {\n\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\terror_description: \"trusted clients must be updated manually\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\n\tconst client = await getClient(ctx, opts, clientId);\n\tif (!client) {\n\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\terror_description: \"client not found\",\n\t\t\terror: \"not_found\",\n\t\t});\n\t}\n\n\tif (client.userId) {\n\t\tif (client.userId !== session.user.id) throw new APIError(\"UNAUTHORIZED\");\n\t} else if (client.referenceId && opts.clientReference) {\n\t\tif (client.referenceId !== (await opts.clientReference(session)))\n\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t} else {\n\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t}\n\n\tif (client.public || !client.clientSecret) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"public clients cannot be updated\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\n\tconst clientSecret =\n\t\topts.generateClientSecret?.() || generateRandomString(32, \"a-z\", \"A-Z\");\n\tconst storedClientSecret = clientSecret\n\t\t? await storeClientSecret(ctx, opts, clientSecret)\n\t\t: undefined;\n\tconst updatedClient = await ctx.context.adapter.update<SchemaClient<Scope[]>>(\n\t\t{\n\t\t\tmodel: \"oauthClient\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"clientId\",\n\t\t\t\t\tvalue: clientId,\n\t\t\t\t},\n\t\t\t],\n\t\t\tupdate: {\n\t\t\t\t...schemaToOAuth(client),\n\t\t\t\tclientSecret: storedClientSecret,\n\t\t\t},\n\t\t},\n\t);\n\n\tif (!updatedClient) {\n\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\terror_description: \"unable to update client\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\n\treturn schemaToOAuth({\n\t\t...updatedClient,\n\t\tclientSecret: (opts.prefix?.clientSecret ?? \"\") + clientSecret,\n\t});\n}\n","import { createAuthEndpoint, sessionMiddleware } from \"better-auth/api\";\nimport * as z from \"zod\";\nimport { createOAuthClientEndpoint } from \"../register\";\nimport type { OAuthOptions, Scope } from \"../types\";\nimport { SafeUrlSchema } from \"../types/zod\";\nimport {\n\tdeleteClientEndpoint,\n\tgetClientEndpoint,\n\tgetClientPublicEndpoint,\n\tgetClientsEndpoint,\n\trotateClientSecretEndpoint,\n\tupdateClientEndpoint,\n} from \"./endpoints\";\n\nexport const adminCreateOAuthClient = (opts: OAuthOptions<Scope[]>) =>\n\tcreateAuthEndpoint(\n\t\t\"/admin/oauth2/create-client\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: z.object({\n\t\t\t\tredirect_uris: z.array(SafeUrlSchema).min(1),\n\t\t\t\tscope: z.string().optional(),\n\t\t\t\tclient_name: z.string().optional(),\n\t\t\t\tclient_uri: z.string().optional(),\n\t\t\t\tlogo_uri: z.string().optional(),\n\t\t\t\tcontacts: z.array(z.string().min(1)).min(1).optional(),\n\t\t\t\ttos_uri: z.string().optional(),\n\t\t\t\tpolicy_uri: z.string().optional(),\n\t\t\t\tsoftware_id: z.string().optional(),\n\t\t\t\tsoftware_version: z.string().optional(),\n\t\t\t\tsoftware_statement: z.string().optional(),\n\t\t\t\tpost_logout_redirect_uris: z.array(SafeUrlSchema).min(1).optional(),\n\t\t\t\ttoken_endpoint_auth_method: z\n\t\t\t\t\t.enum([\"none\", \"client_secret_basic\", \"client_secret_post\"])\n\t\t\t\t\t.default(\"client_secret_basic\")\n\t\t\t\t\t.optional(),\n\t\t\t\tgrant_types: z\n\t\t\t\t\t.array(\n\t\t\t\t\t\tz.enum([\n\t\t\t\t\t\t\t\"authorization_code\",\n\t\t\t\t\t\t\t\"client_credentials\",\n\t\t\t\t\t\t\t\"refresh_token\",\n\t\t\t\t\t\t]),\n\t\t\t\t\t)\n\t\t\t\t\t.default([\"authorization_code\"])\n\t\t\t\t\t.optional(),\n\t\t\t\tresponse_types: z\n\t\t\t\t\t.array(z.enum([\"code\"]))\n\t\t\t\t\t.default([\"code\"])\n\t\t\t\t\t.optional(),\n\t\t\t\ttype: z.enum([\"web\", \"native\", \"user-agent-based\"]).optional(),\n\t\t\t\t// SERVER_ONLY applicable fields\n\t\t\t\tclient_secret_expires_at: z\n\t\t\t\t\t.union([z.string(), z.number()])\n\t\t\t\t\t.optional()\n\t\t\t\t\t.default(0),\n\t\t\t\tskip_consent: z.boolean().optional(),\n\t\t\t\tenable_end_session: z.boolean().optional(),\n\t\t\t\tmetadata: z.record(z.string(), z.unknown()).optional(),\n\t\t\t}),\n\t\t\tmetadata: {\n\t\t\t\tSERVER_ONLY: true,\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Register an OAuth2 application\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"OAuth2 application registered successfully\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t/** @returns {OauthClient} */\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tclient_id: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Unique identifier for the client\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tclient_secret: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Secret key for the client\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tclient_secret_expires_at: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Time the client secret will expire. If 0, the client secret will never expire.\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tscope: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Space-separated scopes allowed by the client\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser_id: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"ID of the user who registered the client, null if registered anonymously\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tclient_id_issued_at: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Creation timestamp of this client\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tclient_name: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Name of the OAuth2 application\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tclient_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"URI of the OAuth2 application\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tlogo_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Icon URI for the application\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tcontacts: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"List representing ways to contact people responsible for this client, typically email addresses\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttos_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Client's terms of service uri\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tpolicy_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Client's policy uri\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tsoftware_id: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Unique identifier assigned by the developer to help in the dynamic registration process\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tsoftware_version: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Version identifier for the software_id\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tsoftware_statement: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"JWT containing metadata values about the client software as claims\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tredirect_uris: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"uri\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"List of allowed redirect uris\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttoken_endpoint_auth_method: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Requested authentication method for the token endpoint\",\n\t\t\t\t\t\t\t\t\t\t\t\tenum: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"client_secret_basic\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"client_secret_post\",\n\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tgrant_types: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tenum: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"authorization_code\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"client_credentials\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"refresh_token\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Requested authentication method for the token endpoint\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tresponse_types: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tenum: [\"code\"],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Requested authentication method for the token endpoint\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tpublic: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Whether the client is public as determined by the type\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttype: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Type of the client\",\n\t\t\t\t\t\t\t\t\t\t\t\tenum: [\"web\", \"native\", \"user-agent-based\"],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tdisabled: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Whether the client is disabled\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tadditionalProperties: true,\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Additional metadata for the application\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"client_id\"],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\treturn createOAuthClientEndpoint(ctx, opts, {\n\t\t\t\tisRegister: false,\n\t\t\t});\n\t\t},\n\t);\n\nexport const createOAuthClient = (opts: OAuthOptions<Scope[]>) =>\n\tcreateAuthEndpoint(\n\t\t\"/oauth2/create-client\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tbody: z.object({\n\t\t\t\tredirect_uris: z.array(SafeUrlSchema).min(1),\n\t\t\t\tscope: z.string().optional(),\n\t\t\t\tclient_name: z.string().optional(),\n\t\t\t\tclient_uri: z.string().optional(),\n\t\t\t\tlogo_uri: z.string().optional(),\n\t\t\t\tcontacts: z.array(z.string().min(1)).min(1).optional(),\n\t\t\t\ttos_uri: z.string().optional(),\n\t\t\t\tpolicy_uri: z.string().optional(),\n\t\t\t\tsoftware_id: z.string().optional(),\n\t\t\t\tsoftware_version: z.string().optional(),\n\t\t\t\tsoftware_statement: z.string().optional(),\n\t\t\t\tpost_logout_redirect_uris: z.array(SafeUrlSchema).min(1).optional(),\n\t\t\t\ttoken_endpoint_auth_method: z\n\t\t\t\t\t.enum([\"none\", \"client_secret_basic\", \"client_secret_post\"])\n\t\t\t\t\t.default(\"client_secret_basic\")\n\t\t\t\t\t.optional(),\n\t\t\t\tgrant_types: z\n\t\t\t\t\t.array(\n\t\t\t\t\t\tz.enum([\n\t\t\t\t\t\t\t\"authorization_code\",\n\t\t\t\t\t\t\t\"client_credentials\",\n\t\t\t\t\t\t\t\"refresh_token\",\n\t\t\t\t\t\t]),\n\t\t\t\t\t)\n\t\t\t\t\t.default([\"authorization_code\"])\n\t\t\t\t\t.optional(),\n\t\t\t\tresponse_types: z\n\t\t\t\t\t.array(z.enum([\"code\"]))\n\t\t\t\t\t.default([\"code\"])\n\t\t\t\t\t.optional(),\n\t\t\t\ttype: z.enum([\"web\", \"native\", \"user-agent-based\"]).optional(),\n\t\t\t}),\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Register an OAuth2 application\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"OAuth2 application registered successfully\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t/** @returns {OauthClient} */\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tclient_id: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Unique identifier for the client\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tclient_secret: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Secret key for the client\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tclient_secret_expires_at: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Time the client secret will expire. If 0, the client secret will never expire.\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tscope: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Space-separated scopes allowed by the client\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser_id: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"ID of the user who registered the client, null if registered anonymously\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tclient_id_issued_at: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Creation timestamp of this client\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tclient_name: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Name of the OAuth2 application\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tclient_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"URI of the OAuth2 application\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tlogo_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Icon URI for the application\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tcontacts: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"List representing ways to contact people responsible for this client, typically email addresses\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttos_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Client's terms of service uri\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tpolicy_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Client's policy uri\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tsoftware_id: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Unique identifier assigned by the developer to help in the dynamic registration process\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tsoftware_version: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Version identifier for the software_id\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tsoftware_statement: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"JWT containing metadata values about the client software as claims\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tredirect_uris: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"uri\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"List of allowed redirect uris\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttoken_endpoint_auth_method: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Response types the client may use\",\n\t\t\t\t\t\t\t\t\t\t\t\tenum: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"client_secret_basic\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"client_secret_post\",\n\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tgrant_types: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tenum: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"authorization_code\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"client_credentials\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"refresh_token\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Requested authentication method for the token endpoint\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tresponse_types: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tenum: [\"code\"],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Requested authentication method for the token endpoint\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tpublic: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Whether the client is public as determined by the type\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttype: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Type of the client\",\n\t\t\t\t\t\t\t\t\t\t\t\tenum: [\"web\", \"native\", \"user-agent-based\"],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tdisabled: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Whether the client is disabled\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tadditionalProperties: true,\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Additional metadata for the application\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"client_id\"],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\treturn createOAuthClientEndpoint(ctx, opts, {\n\t\t\t\tisRegister: false,\n\t\t\t});\n\t\t},\n\t);\n\nexport const getOAuthClient = (opts: OAuthOptions<Scope[]>) =>\n\tcreateAuthEndpoint(\n\t\t\"/oauth2/get-client\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tquery: z.object({\n\t\t\t\tclient_id: z.string(),\n\t\t\t}),\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Get OAuth2 formatted client details\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\treturn getClientEndpoint(ctx, opts);\n\t\t},\n\t);\n\nexport const getOAuthClientPublic = (opts: OAuthOptions<Scope[]>) =>\n\tcreateAuthEndpoint(\n\t\t\"/oauth2/public-client\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tquery: z.object({\n\t\t\t\tclient_id: z.string(),\n\t\t\t}),\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Gets publically available client fields\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\treturn getClientPublicEndpoint(ctx, opts);\n\t\t},\n\t);\n\nexport const getOAuthClients = (opts: OAuthOptions<Scope[]>) =>\n\tcreateAuthEndpoint(\n\t\t\"/oauth2/get-clients\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"Get OAuth2 formatted client details for a user or organization\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\treturn getClientsEndpoint(ctx, opts);\n\t\t},\n\t);\n\nexport const adminUpdateOAuthClient = (opts: OAuthOptions<Scope[]>) =>\n\tcreateAuthEndpoint(\n\t\t\"/admin/oauth2/update-client\",\n\t\t{\n\t\t\tmethod: \"PATCH\",\n\t\t\tbody: z.object({\n\t\t\t\tclient_id: z.string(),\n\t\t\t\tupdate: z.object({\n\t\t\t\t\tredirect_uris: z.array(SafeUrlSchema).min(1).optional(),\n\t\t\t\t\tscope: z.string().optional(),\n\t\t\t\t\tclient_name: z.string().optional(),\n\t\t\t\t\tclient_uri: z.string().optional(),\n\t\t\t\t\tlogo_uri: z.string().optional(),\n\t\t\t\t\tcontacts: z.array(z.string().min(1)).min(1).optional(),\n\t\t\t\t\ttos_uri: z.string().optional(),\n\t\t\t\t\tpolicy_uri: z.string().optional(),\n\t\t\t\t\tsoftware_id: z.string().optional(),\n\t\t\t\t\tsoftware_version: z.string().optional(),\n\t\t\t\t\tsoftware_statement: z.string().optional(),\n\t\t\t\t\tpost_logout_redirect_uris: z.array(SafeUrlSchema).min(1).optional(),\n\t\t\t\t\t// NOTE: token_endpoint_auth_method is currently immutable since it changes isPublic definition\n\t\t\t\t\tgrant_types: z\n\t\t\t\t\t\t.array(\n\t\t\t\t\t\t\tz.enum([\n\t\t\t\t\t\t\t\t\"authorization_code\",\n\t\t\t\t\t\t\t\t\"client_credentials\",\n\t\t\t\t\t\t\t\t\"refresh_token\",\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.optional(),\n\t\t\t\t\tresponse_types: z.array(z.enum([\"code\"])).optional(),\n\t\t\t\t\ttype: z.enum([\"web\", \"native\", \"user-agent-based\"]).optional(),\n\t\t\t\t\t// SERVER_ONLY applicable fields\n\t\t\t\t\tclient_secret_expires_at: z\n\t\t\t\t\t\t.union([z.string(), z.number()])\n\t\t\t\t\t\t.optional(),\n\t\t\t\t\tskip_consent: z.boolean().optional(),\n\t\t\t\t\tenable_end_session: z.boolean().optional(),\n\t\t\t\t\tmetadata: z.record(z.string(), z.unknown()).optional(),\n\t\t\t\t}),\n\t\t\t}),\n\t\t\tmetadata: {\n\t\t\t\tSERVER_ONLY: true,\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Updates OAuth2 formatted client details.\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\treturn updateClientEndpoint(ctx, opts);\n\t\t},\n\t);\n\nexport const updateOAuthClient = (opts: OAuthOptions<Scope[]>) =>\n\tcreateAuthEndpoint(\n\t\t\"/oauth2/update-client\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tbody: z.object({\n\t\t\t\tclient_id: z.string(),\n\t\t\t\tupdate: z.object({\n\t\t\t\t\tredirect_uris: z.array(SafeUrlSchema).min(1).optional(),\n\t\t\t\t\tscope: z.string().optional(),\n\t\t\t\t\tclient_name: z.string().optional(),\n\t\t\t\t\tclient_uri: z.string().optional(),\n\t\t\t\t\tlogo_uri: z.string().optional(),\n\t\t\t\t\tcontacts: z.array(z.string().min(1)).min(1).optional(),\n\t\t\t\t\ttos_uri: z.string().optional(),\n\t\t\t\t\tpolicy_uri: z.string().optional(),\n\t\t\t\t\tsoftware_id: z.string().optional(),\n\t\t\t\t\tsoftware_version: z.string().optional(),\n\t\t\t\t\tsoftware_statement: z.string().optional(),\n\t\t\t\t\tpost_logout_redirect_uris: z.array(SafeUrlSchema).min(1).optional(),\n\t\t\t\t\t// NOTE: token_endpoint_auth_method is currently immutable since it changes isPublic definition\n\t\t\t\t\tgrant_types: z\n\t\t\t\t\t\t.array(\n\t\t\t\t\t\t\tz.enum([\n\t\t\t\t\t\t\t\t\"authorization_code\",\n\t\t\t\t\t\t\t\t\"client_credentials\",\n\t\t\t\t\t\t\t\t\"refresh_token\",\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.optional(),\n\t\t\t\t\tresponse_types: z.array(z.enum([\"code\"])).optional(),\n\t\t\t\t\ttype: z.enum([\"web\", \"native\", \"user-agent-based\"]).optional(),\n\t\t\t\t}),\n\t\t\t}),\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Updates OAuth2 formatted client details.\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\treturn updateClientEndpoint(ctx, opts);\n\t\t},\n\t);\n\nexport const rotateClientSecret = (opts: OAuthOptions<Scope[]>) =>\n\tcreateAuthEndpoint(\n\t\t\"/oauth2/client/rotate-secret\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tbody: z.object({\n\t\t\t\tclient_id: z.string(),\n\t\t\t}),\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Rotates a confidential client's secret\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\treturn rotateClientSecretEndpoint(ctx, opts);\n\t\t},\n\t);\n\nexport const deleteOAuthClient = (opts: OAuthOptions<Scope[]>) =>\n\tcreateAuthEndpoint(\n\t\t\"/oauth2/delete-client\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tbody: z.object({\n\t\t\t\tclient_id: z.string(),\n\t\t\t}),\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Deletes an oauth client\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\treturn deleteClientEndpoint(ctx, opts);\n\t\t},\n\t);\n","import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { APIError, getSessionFromCtx } from \"better-auth/api\";\nimport type { OAuthConsent, OAuthOptions, Scope } from \"../types\";\nimport { getClient } from \"../utils\";\n\nasync function getConsent(\n\tctx: GenericEndpointContext & { query: { id: string } },\n\topts: OAuthOptions<Scope[]>,\n\tid: string,\n) {\n\treturn await ctx.context.adapter.findOne<OAuthConsent<Scope[]>>({\n\t\tmodel: \"oauthConsent\",\n\t\twhere: [\n\t\t\t{\n\t\t\t\tfield: \"id\",\n\t\t\t\tvalue: id,\n\t\t\t},\n\t\t],\n\t});\n}\n\nexport async function getConsentEndpoint(\n\tctx: GenericEndpointContext & { query: { id: string } },\n\topts: OAuthOptions<Scope[]>,\n) {\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session) throw new APIError(\"UNAUTHORIZED\");\n\n\tconst { id } = ctx.query;\n\tif (!id) {\n\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\terror_description: \"missing id parameter\",\n\t\t\terror: \"not_found\",\n\t\t});\n\t}\n\tconst consent = await getConsent(ctx, opts, id);\n\n\tif (!consent) {\n\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\terror_description: \"no consent\",\n\t\t\terror: \"not_found\",\n\t\t});\n\t}\n\tif (consent.userId !== session.user.id) {\n\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t}\n\treturn consent;\n}\n\nexport async function getConsentsEndpoint(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session) throw new APIError(\"UNAUTHORIZED\");\n\n\treturn await ctx.context.adapter.findMany<OAuthConsent<Scope[]>>({\n\t\tmodel: \"oauthConsent\",\n\t\twhere: [\n\t\t\t{\n\t\t\t\tfield: \"userId\",\n\t\t\t\tvalue: session.user.id,\n\t\t\t},\n\t\t],\n\t});\n}\n\nexport async function deleteConsentEndpoint(\n\tctx: GenericEndpointContext & { body: { id: string } },\n\topts: OAuthOptions<Scope[]>,\n) {\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session) throw new APIError(\"UNAUTHORIZED\");\n\n\tconst { id } = ctx.body;\n\tif (!id) {\n\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\terror_description: \"missing id parameter\",\n\t\t\terror: \"not_found\",\n\t\t});\n\t}\n\n\tconst consent = await getConsent(ctx, opts, id);\n\tif (!consent) {\n\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\terror_description: \"no consent\",\n\t\t\terror: \"not_found\",\n\t\t});\n\t}\n\tif (consent.userId !== session.user.id) throw new APIError(\"UNAUTHORIZED\");\n\n\tawait ctx.context.adapter.delete({\n\t\tmodel: \"oauthConsent\",\n\t\twhere: [\n\t\t\t{\n\t\t\t\tfield: \"id\",\n\t\t\t\tvalue: id,\n\t\t\t},\n\t\t],\n\t});\n}\n\nexport async function updateConsentEndpoint(\n\tctx: GenericEndpointContext & { body: { id: string } },\n\topts: OAuthOptions<Scope[]>,\n) {\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session) throw new APIError(\"UNAUTHORIZED\");\n\n\tconst { id } = ctx.body;\n\tif (!id) {\n\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\terror_description: \"missing id parameter\",\n\t\t\terror: \"not_found\",\n\t\t});\n\t}\n\tconst consent = await getConsent(ctx, opts, id);\n\tif (!consent) {\n\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\terror_description: \"no consent\",\n\t\t\terror: \"not_found\",\n\t\t});\n\t}\n\n\tconst client = await getClient(ctx, opts, consent.clientId);\n\tif (!consent) {\n\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\terror_description: \"no consent\",\n\t\t\terror: \"not_found\",\n\t\t});\n\t}\n\tif (consent.userId !== session.user.id) {\n\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t}\n\n\tconst allowedScopes = client?.scopes ?? opts.scopes ?? [];\n\n\t// Check if scopes are granted to that client\n\tconst updates = ctx.body.update as Partial<OAuthConsent>;\n\tconst scopes = updates.scopes;\n\tif (scopes && !scopes.every((val) => allowedScopes?.includes(val))) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: `unable to provide scopes to ${client?.referenceId ?? client?.userId}`,\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\tconst iat = Math.floor(Date.now() / 1000);\n\treturn await ctx.context.adapter.update<OAuthConsent<Scope[]>>({\n\t\tmodel: \"oauthConsent\",\n\t\twhere: [\n\t\t\t{\n\t\t\t\tfield: \"id\",\n\t\t\t\tvalue: id,\n\t\t\t},\n\t\t],\n\t\tupdate: {\n\t\t\t...updates,\n\t\t\tupdatedAt: new Date(iat * 1000),\n\t\t},\n\t});\n}\n","import { createAuthEndpoint, sessionMiddleware } from \"better-auth/api\";\nimport * as z from \"zod\";\nimport type { OAuthOptions, Scope } from \"../types\";\nimport {\n\tdeleteConsentEndpoint,\n\tgetConsentEndpoint,\n\tgetConsentsEndpoint,\n\tupdateConsentEndpoint,\n} from \"./endpoints\";\n\nexport const getOAuthConsent = (opts: OAuthOptions<Scope[]>) =>\n\tcreateAuthEndpoint(\n\t\t\"/oauth2/get-consent\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tquery: z.object({\n\t\t\t\tid: z.string(),\n\t\t\t}),\n\t\t\tuse: [sessionMiddleware],\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Gets details of a specific OAuth2 consent for a user\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\treturn getConsentEndpoint(ctx, opts);\n\t\t},\n\t);\n\nexport const getOAuthConsents = (opts: OAuthOptions<Scope[]>) =>\n\tcreateAuthEndpoint(\n\t\t\"/oauth2/get-consents\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Gets all available OAuth2 consents for a user\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\treturn getConsentsEndpoint(ctx, opts);\n\t\t},\n\t);\n\nexport const updateOAuthConsent = (opts: OAuthOptions<Scope[]>) =>\n\tcreateAuthEndpoint(\n\t\t\"/oauth2/update-consent\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tbody: z.object({\n\t\t\t\tid: z.string(),\n\t\t\t\tupdate: z.object({\n\t\t\t\t\tscopes: z.array(z.string()),\n\t\t\t\t}),\n\t\t\t}),\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Updates consent granted to a client.\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\treturn updateConsentEndpoint(ctx, opts);\n\t\t},\n\t);\n\nexport const deleteOAuthConsent = (opts: OAuthOptions<Scope[]>) =>\n\tcreateAuthEndpoint(\n\t\t\"/oauth2/delete-consent\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\tbody: z.object({\n\t\t\t\tid: z.string(),\n\t\t\t}),\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Deletes consent granted to a client\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\treturn deleteConsentEndpoint(ctx, opts);\n\t\t},\n\t);\n","import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { logger } from \"@better-auth/core/env\";\nimport { verifyJwsAccessToken } from \"better-auth/oauth2\";\nimport { APIError } from \"better-call\";\nimport type { JSONWebKeySet } from \"jose\";\nimport { decodeRefreshToken } from \"./token\";\nimport type {\n\tOAuthOpaqueAccessToken,\n\tOAuthOptions,\n\tOAuthRefreshToken,\n\tScope,\n} from \"./types\";\nimport {\n\tbasicToClientCredentials,\n\tgetJwtPlugin,\n\tgetStoredToken,\n\tvalidateClientCredentials,\n} from \"./utils\";\n\n/**\n * IMPORTANT NOTES:\n * Revocation follows RFC7009\n * https://datatracker.ietf.org/doc/html/rfc7009\n * - APIError: Continue catches (returnable to client)\n * - Error: Should immediately stop catches (internal error)\n */\n\n/**\n * Revokes a JWT access token against the configured JWKs.\n * (does nothing if successful since a JWT is not stored on the server)\n */\nasync function revokeJwtAccessToken(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\ttoken: string,\n) {\n\tconst jwtPlugin = opts.disableJwtPlugin\n\t\t? undefined\n\t\t: getJwtPlugin(ctx.context);\n\tconst jwtPluginOptions = jwtPlugin?.options;\n\n\t// Verify JWT Payload\n\ttry {\n\t\tawait verifyJwsAccessToken(token, {\n\t\t\tjwksFetch: jwtPluginOptions?.jwks?.remoteUrl\n\t\t\t\t? jwtPluginOptions.jwks.remoteUrl\n\t\t\t\t: async () => {\n\t\t\t\t\t\tconst jwksRes = await jwtPlugin?.endpoints.getJwks(ctx);\n\t\t\t\t\t\t// @ts-expect-error response is a JSONWebKeySet but within the response field\n\t\t\t\t\t\treturn jwksRes?.response as JSONWebKeySet | undefined;\n\t\t\t\t\t},\n\t\t\tverifyOptions: {\n\t\t\t\taudience: opts.validAudiences ?? ctx.context.baseURL,\n\t\t\t\tissuer: jwtPluginOptions?.jwt?.issuer ?? ctx.context.baseURL,\n\t\t\t},\n\t\t});\n\t} catch (error) {\n\t\tif (error instanceof Error) {\n\t\t\tif (error.name === \"TypeError\" || error.name === \"JWSInvalid\") {\n\t\t\t\t// likely an opaque token\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\terror_description: \"invalid JWT signature\",\n\t\t\t\t\terror: \"invalid_request\",\n\t\t\t\t});\n\t\t\t} else if (error.name === \"JWTExpired\") {\n\t\t\t\treturn null;\n\t\t\t} else if (error.name === \"JWTInvalid\") {\n\t\t\t\t// audience or issuer mismatch\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tthrow new Error(error as unknown as string);\n\t}\n}\n\n/**\n * Searches for an opaque access token in the database and validates it\n */\nasync function revokeOpaqueAccessToken(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\ttoken: string,\n\tclientId: string,\n) {\n\tlet tokenValue = token;\n\tif (opts.prefix?.opaqueAccessToken) {\n\t\tif (tokenValue.startsWith(opts.prefix.opaqueAccessToken)) {\n\t\t\ttokenValue = tokenValue.replace(opts.prefix.opaqueAccessToken, \"\");\n\t\t} else {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\terror_description: \"opaque access token not found\",\n\t\t\t\terror: \"invalid_request\",\n\t\t\t});\n\t\t}\n\t}\n\tconst accessToken:\n\t\t| (OAuthOpaqueAccessToken<Scope[]> & { id?: string })\n\t\t| null = await ctx.context.adapter.findOne<OAuthOpaqueAccessToken<Scope[]>>(\n\t\t{\n\t\t\tmodel: \"oauthAccessToken\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"token\",\n\t\t\t\t\tvalue: await getStoredToken(\n\t\t\t\t\t\topts.storeTokens,\n\t\t\t\t\t\ttokenValue,\n\t\t\t\t\t\t\"access_token\",\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t);\n\tif (!accessToken) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"opaque access token not found\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tif (!accessToken.clientId || accessToken.clientId !== clientId) {\n\t\treturn null;\n\t}\n\n\taccessToken.id\n\t\t? await ctx.context.adapter.delete({\n\t\t\t\tmodel: \"oauthAccessToken\",\n\t\t\t\twhere: [{ field: \"id\", value: accessToken.id }],\n\t\t\t})\n\t\t: await ctx.context.adapter.delete({\n\t\t\t\tmodel: \"oauthAccessToken\",\n\t\t\t\twhere: [{ field: \"token\", value: accessToken.token }],\n\t\t\t});\n}\n\n/**\n * Validates a refresh token in the session store.\n */\nasync function revokeRefreshToken(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\ttoken: string,\n\tclientId: string,\n) {\n\tconst refreshToken = await ctx.context.adapter.findOne<\n\t\tOAuthRefreshToken<Scope[]> & { id: string }\n\t>({\n\t\tmodel: \"oauthRefreshToken\",\n\t\twhere: [\n\t\t\t{\n\t\t\t\tfield: \"token\",\n\t\t\t\tvalue: await getStoredToken(opts.storeTokens, token, \"refresh_token\"),\n\t\t\t},\n\t\t],\n\t});\n\tif (!refreshToken) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"token not found\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tif (refreshToken.revoked) {\n\t\tawait ctx.context.adapter.deleteMany({\n\t\t\tmodel: \"oauthRefreshToken\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"clientId\",\n\t\t\t\t\tvalue: clientId,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tfield: \"userId\",\n\t\t\t\t\tvalue: refreshToken.userId,\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"refresh token revoked\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\tif (!refreshToken.clientId || refreshToken.clientId !== clientId) {\n\t\treturn null;\n\t}\n\n\tconst iat = Math.floor(Date.now() / 1000);\n\tawait Promise.allSettled([\n\t\t// Removes all access tokens associated with the refresh token\n\t\tctx.context.adapter.deleteMany({\n\t\t\tmodel: \"oauthAccessToken\",\n\t\t\twhere: [{ field: \"refreshId\", value: refreshToken.id }],\n\t\t}),\n\t\t// Update the refresh token\n\t\tctx.context.adapter.update({\n\t\t\tmodel: \"oauthRefreshToken\",\n\t\t\twhere: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t\tvalue: refreshToken.id,\n\t\t\t\t},\n\t\t\t],\n\t\t\tupdate: {\n\t\t\t\trevoked: new Date(iat * 1000),\n\t\t\t},\n\t\t}),\n\t]);\n}\n\n/**\n * We don't know the access token format so we try to validate it\n * as a JWT first, then as an opaque token.\n */\nasync function revokeAccessToken(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\tclientId: string,\n\ttoken: string,\n) {\n\ttry {\n\t\treturn await revokeJwtAccessToken(ctx, opts, token);\n\t} catch (err) {\n\t\tif (err instanceof APIError) {\n\t\t\t// continue\n\t\t} else if (err instanceof Error) {\n\t\t\tthrow err;\n\t\t} else {\n\t\t\tthrow new Error(err as unknown as string);\n\t\t}\n\t}\n\ttry {\n\t\treturn await revokeOpaqueAccessToken(ctx, opts, token, clientId);\n\t} catch (err) {\n\t\tif (err instanceof APIError) {\n\t\t\t// nothing\n\t\t} else if (err instanceof Error) {\n\t\t\tthrow err;\n\t\t} else {\n\t\t\tthrow new Error(\"Unknown error validating access token\");\n\t\t}\n\t}\n\tthrow new APIError(\"BAD_REQUEST\", {\n\t\terror_description: \"Invalid access token\",\n\t\terror: \"invalid_request\",\n\t});\n}\n\nexport async function revokeEndpoint(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n) {\n\tlet {\n\t\tclient_id,\n\t\tclient_secret,\n\t\ttoken,\n\t\ttoken_type_hint,\n\t}: {\n\t\tclient_id?: string;\n\t\tclient_secret?: string;\n\t\ttoken: string;\n\t\ttoken_type_hint?: \"access_token\" | \"refresh_token\";\n\t} = ctx.body;\n\n\t// Convert basic authorization\n\tconst authorization = ctx.request?.headers.get(\"authorization\") || null;\n\tif (authorization?.startsWith(\"Basic \")) {\n\t\tconst res = basicToClientCredentials(authorization);\n\t\tclient_id = res?.client_id;\n\t\tclient_secret = res?.client_secret;\n\t}\n\t// client_id is always required, client_secret is required for confidential clients\n\tif (!client_id) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"missing required credentials\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\n\t// Check token\n\tif (typeof token === \"string\" && token.startsWith(\"Bearer \")) {\n\t\ttoken = token.replace(\"Bearer \", \"\");\n\t}\n\tif (!token?.length) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"missing a required token for introspection\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t}\n\n\t// Validate client credentials\n\tconst client = await validateClientCredentials(\n\t\tctx,\n\t\topts,\n\t\tclient_id,\n\t\tclient_secret,\n\t);\n\n\ttry {\n\t\tif (token_type_hint === undefined || token_type_hint === \"access_token\") {\n\t\t\ttry {\n\t\t\t\treturn await revokeAccessToken(ctx, opts, client.clientId, token);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof APIError) {\n\t\t\t\t\tif (token_type_hint === \"access_token\") {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t} // else continue\n\t\t\t\t} else if (error instanceof Error) {\n\t\t\t\t\tthrow error;\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(error as unknown as string);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (token_type_hint === undefined || token_type_hint === \"refresh_token\") {\n\t\t\ttry {\n\t\t\t\tconst refreshToken = await decodeRefreshToken(opts, token);\n\t\t\t\treturn await revokeRefreshToken(\n\t\t\t\t\tctx,\n\t\t\t\t\topts,\n\t\t\t\t\trefreshToken.token,\n\t\t\t\t\tclient.clientId,\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof APIError) {\n\t\t\t\t\tif (token_type_hint === \"refresh_token\") {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t} // else continue\n\t\t\t\t} else if (error instanceof Error) {\n\t\t\t\t\tthrow error;\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(error as unknown as string);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"token not found\",\n\t\t\terror: \"invalid_request\",\n\t\t});\n\t} catch (error) {\n\t\tif (error instanceof APIError) {\n\t\t\tif (error.name === \"BAD_REQUEST\") {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tthrow error;\n\t\t} else if (error instanceof Error) {\n\t\t\tlogger.error(\"Introspection error:\", error.message, error.stack);\n\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\");\n\t\t} else {\n\t\t\tlogger.error(\"Introspection error:\", error);\n\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\");\n\t\t}\n\t}\n}\n","import type { BetterAuthPluginDBSchema } from \"@better-auth/core/db\";\n\nexport const schema = {\n\toauthClient: {\n\t\tmodelName: \"oauthClient\",\n\t\tfields: {\n\t\t\t// Important Fields\n\t\t\tclientId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\tunique: true,\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tclientSecret: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tdisabled: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdefaultValue: false,\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tskipConsent: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tenableEndSession: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tscopes: {\n\t\t\t\ttype: \"string[]\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\t// Recommended client data\n\t\t\tuserId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tupdatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\t// UI Metadata\n\t\t\tname: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\turi: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\ticon: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tcontacts: {\n\t\t\t\ttype: \"string[]\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\ttos: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tpolicy: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\t// User Software Identifiers\n\t\t\tsoftwareId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tsoftwareVersion: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tsoftwareStatement: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\t// Authentication Metadata\n\t\t\tredirectUris: {\n\t\t\t\ttype: \"string[]\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tpostLogoutRedirectUris: {\n\t\t\t\ttype: \"string[]\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\ttokenEndpointAuthMethod: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tgrantTypes: {\n\t\t\t\ttype: \"string[]\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tresponseTypes: {\n\t\t\t\ttype: \"string[]\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\t// RFC6749 Spec\n\t\t\tpublic: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\ttype: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\t// All other metadata\n\t\t\treferenceId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tmetadata: {\n\t\t\t\ttype: \"json\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t},\n\t},\n\t/**\n\t * An opaque refresh token created with \"offline_access\"\n\t *\n\t * Refresh tokens are linked to a session.\n\t */\n\toauthRefreshToken: {\n\t\tfields: {\n\t\t\ttoken: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tclientId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"oauthClient\",\n\t\t\t\t\tfield: \"clientId\",\n\t\t\t\t},\n\t\t\t},\n\t\t\t// Session used during authorization\n\t\t\tsessionId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"session\",\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t\t// session can be deleted but refresh still active\n\t\t\t\t\tonDelete: \"set null\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tuserId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t},\n\t\t\t},\n\t\t\treferenceId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\texpiresAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t},\n\t\t\trevoked: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\t// Immutable\n\t\t\tscopes: {\n\t\t\t\ttype: \"string[]\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t},\n\t},\n\t/**\n\t * An opaque access token sent when there is no audience\n\t * to assigned to the JWT.\n\t *\n\t * Access tokens are linked to a session, better-auth\n\t * authors SHALL always check for valid session!\n\t *\n\t * AccessTokens SHALL only be created at refresh,\n\t * destroyed at revoke, and read at introspection.\n\t * NEVER update an access token! Typically a refresh and\n\t * revoke (if not expired) may want to occur at the same time.\n\t */\n\toauthAccessToken: {\n\t\tmodelName: \"oauthAccessToken\",\n\t\tfields: {\n\t\t\ttoken: {\n\t\t\t\ttype: \"string\",\n\t\t\t\tunique: true,\n\t\t\t},\n\t\t\tclientId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"oauthClient\",\n\t\t\t\t\tfield: \"clientId\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tsessionId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\t// Optional for client credentials grant\n\t\t\t\trequired: false,\n\t\t\t\t// Not unique, multiple sessions could exist\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"session\",\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t\t// session can be deleted but refresh still active\n\t\t\t\t\tonDelete: \"set null\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tuserId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t},\n\t\t\t},\n\t\t\treferenceId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\trefreshId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"oauthRefreshToken\",\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t},\n\t\t\t},\n\t\t\texpiresAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t},\n\t\t\t// Shall be same as refreshId.scopes if using refreshId\n\t\t\tscopes: {\n\t\t\t\ttype: \"string[]\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t},\n\t},\n\toauthConsent: {\n\t\tmodelName: \"oauthConsent\",\n\t\tfields: {\n\t\t\tclientId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"oauthClient\",\n\t\t\t\t\tfield: \"clientId\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tuserId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\treferences: {\n\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\tfield: \"id\",\n\t\t\t\t},\n\t\t\t},\n\t\t\treferenceId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tscopes: {\n\t\t\t\ttype: \"string[]\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t},\n\t\t\tupdatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n","import { defineRequestState } from \"@better-auth/core/context\";\nimport { logger } from \"@better-auth/core/env\";\nimport { BetterAuthError } from \"@better-auth/core/error\";\nimport {\n\tAPIError,\n\tcreateAuthEndpoint,\n\tcreateAuthMiddleware,\n\tgetOAuthState,\n\tsessionMiddleware,\n} from \"better-auth/api\";\nimport { parseSetCookieHeader } from \"better-auth/cookies\";\nimport { constantTimeEqual, makeSignature } from \"better-auth/crypto\";\nimport { mergeSchema } from \"better-auth/db\";\nimport type { BetterAuthPlugin } from \"better-auth/types\";\nimport * as z from \"zod\";\nimport { authorizeEndpoint } from \"./authorize\";\nimport { consentEndpoint } from \"./consent\";\nimport { continueEndpoint } from \"./continue\";\nimport { introspectEndpoint } from \"./introspect\";\nimport { rpInitiatedLogoutEndpoint } from \"./logout\";\nimport { authServerMetadata, oidcServerMetadata } from \"./metadata\";\nimport * as oauthClientEndpoints from \"./oauthClient\";\nimport * as oauthConsentEndpoints from \"./oauthConsent\";\nimport { registerEndpoint } from \"./register\";\nimport { revokeEndpoint } from \"./revoke\";\nimport { schema } from \"./schema\";\nimport { tokenEndpoint } from \"./token\";\nimport type { OAuthOptions, Scope } from \"./types\";\nimport { SafeUrlSchema } from \"./types/zod\";\nimport { userInfoEndpoint } from \"./userinfo\";\nimport { deleteFromPrompt, getJwtPlugin } from \"./utils\";\n\nexport const oAuthState = defineRequestState<{ query?: string } | null>(\n\t() => null,\n);\n\n/**\n * oAuth 2.1 provider plugin for Better Auth.\n *\n * @see https://better-auth.com/docs/plugins/oauth-provider\n * @param options - The options for the oAuth Provider plugin.\n * @returns A Better Auth plugin.\n */\nexport const oauthProvider = <O extends OAuthOptions<Scope[]>>(options: O) => {\n\tlet clientRegistrationAllowedScopes = options.clientRegistrationAllowedScopes;\n\tif (options.clientRegistrationDefaultScopes) {\n\t\tconst _allowedScopes = clientRegistrationAllowedScopes\n\t\t\t? new Set([\n\t\t\t\t\t...clientRegistrationAllowedScopes,\n\t\t\t\t\t...options.clientRegistrationDefaultScopes,\n\t\t\t\t])\n\t\t\t: new Set([...options.clientRegistrationDefaultScopes]);\n\t\tclientRegistrationAllowedScopes = Array.from(_allowedScopes);\n\t}\n\n\t// Validate scopes\n\tconst scopes = new Set(\n\t\t(options.scopes ?? [\"openid\", \"profile\", \"email\", \"offline_access\"]).filter(\n\t\t\t(val) => val.length,\n\t\t),\n\t);\n\tif (clientRegistrationAllowedScopes) {\n\t\tfor (const sc of clientRegistrationAllowedScopes) {\n\t\t\tif (!scopes.has(sc)) {\n\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t`clientRegistrationAllowedScope ${sc} not found in scopes`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\tfor (const sc of options.advertisedMetadata?.scopes_supported ?? []) {\n\t\tif (!scopes?.has(sc)) {\n\t\t\tthrow new BetterAuthError(\n\t\t\t\t`advertisedMetadata.scopes_supported ${sc} not found in scopes`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// Validate claims\n\tconst claims = new Set([\n\t\t\"sub\",\n\t\t\"iss\",\n\t\t\"aud\",\n\t\t\"exp\",\n\t\t\"iat\",\n\t\t\"sid\",\n\t\t\"scope\",\n\t\t\"azp\",\n\t\t...(scopes.has(\"email\") ? [\"email\", \"email_verified\"] : []),\n\t\t...(scopes.has(\"profile\")\n\t\t\t? [\"name\", \"picture\", \"family_name\", \"given_name\"]\n\t\t\t: []),\n\t]);\n\n\tconst opts: O & { claims?: string[] } = {\n\t\tcodeExpiresIn: 600, // 10 min\n\t\taccessTokenExpiresIn: 3600, // 1 hour\n\t\tm2mAccessTokenExpiresIn: 3600, // 1 hour\n\t\trefreshTokenExpiresIn: 2592000, // 30 days\n\t\tallowUnauthenticatedClientRegistration: false,\n\t\tallowDynamicClientRegistration: false,\n\t\tdisableJwtPlugin: false,\n\t\tstoreClientSecret: options.disableJwtPlugin ? \"encrypted\" : \"hashed\",\n\t\tstoreTokens: \"hashed\",\n\t\tgrantTypes: [\"authorization_code\", \"client_credentials\", \"refresh_token\"],\n\t\t...options,\n\t\tscopes: Array.from(scopes),\n\t\tclaims: Array.from(claims),\n\t\tclientRegistrationAllowedScopes,\n\t};\n\n\t// TODO: device_code grant also allows for refresh tokens\n\tif (\n\t\topts.grantTypes &&\n\t\topts.grantTypes.includes(\"refresh_token\") &&\n\t\t!opts.grantTypes.includes(\"authorization_code\")\n\t) {\n\t\tthrow new BetterAuthError(\n\t\t\t\"refresh_token grant requires authorization_code grant\",\n\t\t);\n\t}\n\n\tif (\n\t\topts.disableJwtPlugin &&\n\t\t(opts.storeClientSecret === \"hashed\" ||\n\t\t\t(typeof opts.storeClientSecret === \"object\" &&\n\t\t\t\t\"hash\" in opts.storeClientSecret))\n\t) {\n\t\tthrow new BetterAuthError(\n\t\t\t\"unable to store hashed secrets because id tokens will be signed with secret\",\n\t\t);\n\t}\n\n\tif (\n\t\t!opts.disableJwtPlugin &&\n\t\t(opts.storeClientSecret === \"encrypted\" ||\n\t\t\t(typeof opts.storeClientSecret === \"object\" &&\n\t\t\t\t(\"encrypt\" in opts.storeClientSecret ||\n\t\t\t\t\t\"decrypt\" in opts.storeClientSecret)))\n\t) {\n\t\tthrow new BetterAuthError(\n\t\t\t\"encryption method not recommended, please use 'hashed' or the 'hash' function\",\n\t\t);\n\t}\n\n\treturn {\n\t\tid: \"oauthProvider\",\n\t\toptions: opts as NoInfer<O>,\n\t\tinit: (ctx) => {\n\t\t\t// Require session id storage on database (secondary-storage only solution not yet supported)\n\t\t\tif (ctx.options.session && !ctx.options.session.storeSessionInDatabase) {\n\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\"OAuth Provider requires `session.storeSessionInDatabase: true` when using secondaryStorage\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Check for jwt plugin registration\n\t\t\tif (!opts.disableJwtPlugin) {\n\t\t\t\tconst jwtPlugin = getJwtPlugin(ctx);\n\t\t\t\tconst jwtPluginOptions = jwtPlugin.options;\n\n\t\t\t\t// Issuer and well-known endpoint checks\n\t\t\t\tconst issuer = jwtPluginOptions?.jwt?.issuer ?? ctx.baseURL;\n\t\t\t\tconst issuerPath = new URL(issuer).pathname;\n\t\t\t\t// oAuth Server Config\n\t\t\t\tif (\n\t\t\t\t\t!opts.silenceWarnings?.oauthAuthServerConfig &&\n\t\t\t\t\t!(ctx.options.basePath === \"/\" && issuerPath === \"/\")\n\t\t\t\t) {\n\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t`Please ensure '/.well-known/oauth-authorization-server${issuerPath === \"/\" ? \"\" : issuerPath}' exists. Upon completion, clear with silenceWarnings.oauthAuthServerConfig.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// OpenId Config\n\t\t\t\tif (\n\t\t\t\t\t!opts.silenceWarnings?.openidConfig &&\n\t\t\t\t\tctx.options.basePath !== issuerPath &&\n\t\t\t\t\topts.scopes?.includes(\"openid\")\n\t\t\t\t) {\n\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t`Please ensure '${issuerPath}${issuerPath.endsWith(\"/\") ? \"\" : \"/\"}.well-known/openid-configuration' exists. Upon completion, clear with silenceWarnings.openidConfig.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\thooks: {\n\t\t\tbefore: [\n\t\t\t\t{\n\t\t\t\t\t// Add oauth_query to request state\n\t\t\t\t\tmatcher(ctx) {\n\t\t\t\t\t\treturn ctx.body?.oauth_query;\n\t\t\t\t\t},\n\t\t\t\t\thandler: createAuthMiddleware(async (ctx) => {\n\t\t\t\t\t\t// Verify query signature\n\t\t\t\t\t\tconst query = ctx.body.oauth_query;\n\t\t\t\t\t\tlet queryParams = new URLSearchParams(query);\n\t\t\t\t\t\tconst sig = queryParams.get(\"sig\");\n\t\t\t\t\t\tconst exp = Number(queryParams.get(\"exp\"));\n\t\t\t\t\t\tqueryParams.delete(\"sig\");\n\t\t\t\t\t\tqueryParams = new URLSearchParams(queryParams);\n\t\t\t\t\t\tconst verifySig = await makeSignature(\n\t\t\t\t\t\t\tqueryParams.toString(),\n\t\t\t\t\t\t\tctx.context.secret,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t!sig ||\n\t\t\t\t\t\t\t!constantTimeEqual(sig, verifySig) ||\n\t\t\t\t\t\t\tnew Date(exp * 1000) < new Date()\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\terror: \"invalid_signature\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tqueryParams.delete(\"exp\");\n\t\t\t\t\t\tawait oAuthState.set({\n\t\t\t\t\t\t\tquery: new URLSearchParams(queryParams).toString(),\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// If path starts oauth2 authorize (ie /sign-in/social, /sign-in/oauth2), add to additional data body\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tctx.path === \"/sign-in/social\" ||\n\t\t\t\t\t\t\tctx.path === \"/sign-in/oauth2\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tif (ctx.body.additionalData?.query) return;\n\t\t\t\t\t\t\tif (!ctx.body.additionalData) ctx.body.additionalData = {};\n\t\t\t\t\t\t\tctx.body.additionalData.query = queryParams.toString();\n\t\t\t\t\t\t}\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t],\n\t\t\tafter: [\n\t\t\t\t{\n\t\t\t\t\t// Should only capture when session cookie is set (ie after login)\n\t\t\t\t\tmatcher(ctx) {\n\t\t\t\t\t\treturn parseSetCookieHeader(\n\t\t\t\t\t\t\tctx.context.responseHeaders?.get(\"set-cookie\") || \"\",\n\t\t\t\t\t\t).has(ctx.context.authCookies.sessionToken.name);\n\t\t\t\t\t},\n\t\t\t\t\thandler: createAuthMiddleware(async (ctx) => {\n\t\t\t\t\t\t// Check if session cookie is being set and obtain its session (needed in context)\n\t\t\t\t\t\tconst sessionToken = parseSetCookieHeader(\n\t\t\t\t\t\t\tctx.context.responseHeaders?.get(\"set-cookie\") || \"\",\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.get(ctx.context.authCookies.sessionToken.name)\n\t\t\t\t\t\t\t?.value.split(\".\")[0];\n\t\t\t\t\t\tif (!sessionToken) return;\n\t\t\t\t\t\t// Continue with authorization request by using the initial prompt\n\t\t\t\t\t\t// but clearing the login prompt cookie if forced login prompt\n\t\t\t\t\t\tconst _query =\n\t\t\t\t\t\t\t(await oAuthState.get())?.query ??\n\t\t\t\t\t\t\t((await getOAuthState())?.query as string | undefined);\n\t\t\t\t\t\tif (!_query) return;\n\t\t\t\t\t\tconst query = new URLSearchParams(_query);\n\n\t\t\t\t\t\tconst session =\n\t\t\t\t\t\t\tawait ctx.context.internalAdapter.findSession(sessionToken);\n\t\t\t\t\t\tif (!session) return;\n\t\t\t\t\t\tctx.context.session = session;\n\n\t\t\t\t\t\tctx.query = deleteFromPrompt(query, \"login\");\n\t\t\t\t\t\treturn await authorizeEndpoint(ctx, opts);\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\tendpoints: {\n\t\t\t/**\n\t\t\t * A server-only endpoint that helps provide the\n\t\t\t * oAuth Server configuration at the well-known endpoint.\n\t\t\t *\n\t\t\t * Provided at /.well-known/oauth-authorization-server/[issuer-path]\n\t\t\t * (root if no issuer-path).\n\t\t\t */\n\t\t\tgetOAuthServerConfig: createAuthEndpoint(\n\t\t\t\t\"/.well-known/oauth-authorization-server\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tSERVER_ONLY: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tif (opts.scopes && opts.scopes.includes(\"openid\")) {\n\t\t\t\t\t\tconst metadata = oidcServerMetadata(ctx, opts);\n\t\t\t\t\t\treturn metadata;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst jwtPluginOptions = opts.disableJwtPlugin\n\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t: getJwtPlugin(ctx.context).options;\n\t\t\t\t\t\tconst authMetadata = authServerMetadata(ctx, jwtPluginOptions, {\n\t\t\t\t\t\t\tscopes_supported:\n\t\t\t\t\t\t\t\topts.advertisedMetadata?.scopes_supported ?? opts.scopes,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn authMetadata;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t\t\t/**\n\t\t\t * A server-only endpoint that helps provide the\n\t\t\t * OpenId configuration at the well-known endpoint.\n\t\t\t *\n\t\t\t * Provided at [issuer-path]/.well-known/openid-configuration\n\t\t\t * (root if no issuer-path).\n\t\t\t */\n\t\t\tgetOpenIdConfig: createAuthEndpoint(\n\t\t\t\t\"/.well-known/openid-configuration\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tSERVER_ONLY: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tif (opts.scopes && !opts.scopes.includes(\"openid\")) {\n\t\t\t\t\t\tthrow new APIError(\"NOT_FOUND\");\n\t\t\t\t\t}\n\t\t\t\t\tconst metadata = oidcServerMetadata(ctx, opts);\n\t\t\t\t\treturn metadata;\n\t\t\t\t},\n\t\t\t),\n\t\t\toauth2Authorize: createAuthEndpoint(\n\t\t\t\t\"/oauth2/authorize\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tquery: z.object({\n\t\t\t\t\t\tresponse_type: z.enum([\"code\"]),\n\t\t\t\t\t\tclient_id: z.string(),\n\t\t\t\t\t\tredirect_uri: SafeUrlSchema.optional(),\n\t\t\t\t\t\tscope: z.string().optional(),\n\t\t\t\t\t\tstate: z.string().optional(),\n\t\t\t\t\t\tcode_challenge: z.string().optional(),\n\t\t\t\t\t\tcode_challenge_method: z.enum([\"S256\"]).optional(),\n\t\t\t\t\t\tnonce: z.string().optional(),\n\t\t\t\t\t\tprompt: z\n\t\t\t\t\t\t\t.enum([\n\t\t\t\t\t\t\t\t\"consent\",\n\t\t\t\t\t\t\t\t\"login\",\n\t\t\t\t\t\t\t\t\"create\",\n\t\t\t\t\t\t\t\t\"select_account\",\n\t\t\t\t\t\t\t\t\"login consent\",\n\t\t\t\t\t\t\t\t\"select_account consent\",\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t\t.optional(),\n\t\t\t\t\t}),\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\topenapi: {\n\t\t\t\t\t\t\tdescription: \"Authorize an OAuth2 request\",\n\t\t\t\t\t\t\tparameters: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: \"response_type\",\n\t\t\t\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\t\t\t\tschema: { type: \"string\" },\n\t\t\t\t\t\t\t\t\tdescription: \"OAuth2 response type (e.g., 'code')\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: \"client_id\",\n\t\t\t\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\t\t\t\tschema: { type: \"string\" },\n\t\t\t\t\t\t\t\t\tdescription: \"OAuth2 client ID\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: \"redirect_uri\",\n\t\t\t\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\t\t\t\tschema: { type: \"string\", format: \"uri\" },\n\t\t\t\t\t\t\t\t\tdescription: \"OAuth2 redirect URI\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: \"scope\",\n\t\t\t\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\t\t\t\tschema: { type: \"string\" },\n\t\t\t\t\t\t\t\t\tdescription: \"OAuth2 scopes (space-separated)\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: \"state\",\n\t\t\t\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\t\t\t\tschema: { type: \"string\" },\n\t\t\t\t\t\t\t\t\tdescription: \"OAuth2 state parameter\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: \"code_challenge\",\n\t\t\t\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\t\t\t\tschema: { type: \"string\" },\n\t\t\t\t\t\t\t\t\tdescription: \"PKCE code challenge\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: \"code_challenge_method\",\n\t\t\t\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\t\t\t\tschema: { type: \"string\" },\n\t\t\t\t\t\t\t\t\tdescription: \"PKCE code challenge method\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: \"nonce\",\n\t\t\t\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\t\t\t\tschema: { type: \"string\" },\n\t\t\t\t\t\t\t\t\tdescription: \"OpenID Connect nonce\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: \"prompt\",\n\t\t\t\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\t\t\t\tschema: { type: \"string\" },\n\t\t\t\t\t\t\t\t\tdescription: \"OAuth2 prompt parameter\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\t\t\"302\": {\n\t\t\t\t\t\t\t\t\tdescription: \"Redirect to client with code or error\",\n\t\t\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\t\t\tLocation: {\n\t\t\t\t\t\t\t\t\t\t\tdescription: \"Redirect URI with code or error\",\n\t\t\t\t\t\t\t\t\t\t\tschema: { type: \"string\", format: \"uri\" },\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"400\": {\n\t\t\t\t\t\t\t\t\tdescription: \"Invalid request\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\terror: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\terror_description: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\tstate: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trequired: [\"error\"],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\treturn authorizeEndpoint(ctx, opts, {\n\t\t\t\t\t\tisAuthorize: true,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t),\n\t\t\toauth2Consent: createAuthEndpoint(\n\t\t\t\t\"/oauth2/consent\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: z.object({\n\t\t\t\t\t\taccept: z.boolean().meta({\n\t\t\t\t\t\t\tdescription: \"Accept or deny user consent for a set of scopes\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tscope: z.string().optional().meta({\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\"List of accept of accepted space-separated scopes. If none is provided, then all originally requested scopes are accepted.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t\toauth_query: z.string().optional().meta({\n\t\t\t\t\t\t\tdescription: \"The redirected page's query parameters\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t}),\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\topenapi: {\n\t\t\t\t\t\t\tdescription: \"Handle OAuth2 consent\",\n\t\t\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\t\t\tdescription: \"Consent processed successfully\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tredirect_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"uri\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"The URI to redirect to, either with an authorization code or an error\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trequired: [\"redirect_uri\"],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\treturn consentEndpoint(ctx, opts);\n\t\t\t\t},\n\t\t\t),\n\t\t\toauth2Continue: createAuthEndpoint(\n\t\t\t\t\"/oauth2/continue\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: z.object({\n\t\t\t\t\t\tselected: z.boolean().optional().meta({\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\"Confirms an account has been selected and authorization can proceed.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tcreated: z.boolean().optional().meta({\n\t\t\t\t\t\t\tdescription: \"Confirms an account was registered\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tpostLogin: z.boolean().optional().meta({\n\t\t\t\t\t\t\tdescription: \"Confirms organization and/or team selection.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t\toauth_query: z.string().optional().meta({\n\t\t\t\t\t\t\tdescription: \"The redirected page's query parameters\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t}),\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\topenapi: {\n\t\t\t\t\t\t\tdescription: \"Continues OAuth2 authorization flow\",\n\t\t\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\t\t\tdescription: \"Consent processed successfully\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tredirect_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"uri\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"The URI to redirect to, either with an authorization code or an error\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trequired: [\"redirect_uri\"],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\treturn continueEndpoint(ctx, opts);\n\t\t\t\t},\n\t\t\t),\n\t\t\toauth2Token: createAuthEndpoint(\n\t\t\t\t\"/oauth2/token\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: z.object({\n\t\t\t\t\t\tgrant_type: z.enum([\n\t\t\t\t\t\t\t\"authorization_code\",\n\t\t\t\t\t\t\t\"client_credentials\",\n\t\t\t\t\t\t\t\"refresh_token\",\n\t\t\t\t\t\t]),\n\t\t\t\t\t\tclient_id: z.string().optional(),\n\t\t\t\t\t\tclient_secret: z.string().optional(),\n\t\t\t\t\t\tcode: z.string().optional(),\n\t\t\t\t\t\tcode_verifier: z.string().optional(),\n\t\t\t\t\t\tredirect_uri: SafeUrlSchema.optional(),\n\t\t\t\t\t\trefresh_token: z.string().optional(),\n\t\t\t\t\t\tresource: z.string().optional(),\n\t\t\t\t\t\tscope: z.string().optional(),\n\t\t\t\t\t}),\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tallowedMediaTypes: [\"application/x-www-form-urlencoded\"],\n\t\t\t\t\t\topenapi: {\n\t\t\t\t\t\t\tdescription: \"Obtain an OAuth2.1 access token\",\n\t\t\t\t\t\t\trequestBody: {\n\t\t\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\tgrant_type: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tenum: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"authorization_code\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"client_credentials\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"refresh_token\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"OAuth2 grant type\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tclient_id: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"OAuth2 client ID\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tclient_secret: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"OAuth2 client secret\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tcode: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Authorization code (for authorization_code grant)\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tcode_verifier: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"PKCE code verifier (for authorization_code grant)\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tredirect_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"uri\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Redirect URI (for authorization_code grant)\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trefresh_token: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Refresh token (for refresh_token grant)\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tresource: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Requested token resource (ie audience) to obtain a JWT formatted access token\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tscope: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Requested scopes (for client_credentials grant)\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trequired: [\"grant_type\"],\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\t\t\tdescription: \"Access token response\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\taccess_token: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"The access token issued by the authorization server\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\ttoken_type: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"The type of the token issued\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tenum: [\"Bearer\"],\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\texpires_in: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Lifetime in seconds of the access token\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\trefresh_token: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Refresh token, if issued\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tscope: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Scopes granted by the access token\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tid_token: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"ID Token (if OpenID Connect)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trequired: [\"access_token\", \"token_type\", \"expires_in\"],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"400\": {\n\t\t\t\t\t\t\t\t\tdescription: \"Invalid request or error response\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\terror: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\terror_description: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\terror_uri: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trequired: [\"error\"],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\treturn tokenEndpoint(ctx, opts);\n\t\t\t\t},\n\t\t\t),\n\t\t\toauth2Introspect: createAuthEndpoint(\n\t\t\t\t\"/oauth2/introspect\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: z.object({\n\t\t\t\t\t\tclient_id: z.string().optional(),\n\t\t\t\t\t\tclient_secret: z.string().optional(),\n\t\t\t\t\t\ttoken: z.string(),\n\t\t\t\t\t\ttoken_type_hint: z\n\t\t\t\t\t\t\t.enum([\"access_token\", \"refresh_token\"])\n\t\t\t\t\t\t\t.optional(),\n\t\t\t\t\t}),\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tallowedMediaTypes: [\"application/x-www-form-urlencoded\"],\n\t\t\t\t\t\topenapi: {\n\t\t\t\t\t\t\tdescription: \"Introspect an OAuth2 access or refresh token\",\n\t\t\t\t\t\t\trequestBody: {\n\t\t\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\tclient_id: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"OAuth2 client ID\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tclient_secret: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"OAuth2 client secret\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"The token to introspect (access or refresh token)\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\ttoken_type_hint: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tenum: [\"access_token\", \"refresh_token\"],\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Hint about the type of the token submitted for introspection\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tresource: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Introspects a token for a specific resource.\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trequired: [\"token\"],\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\t\t\tdescription: \"Token introspection response\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tactive: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Whether the token is active\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tscope: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Scopes associated with the token\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tclient_id: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Client ID associated with the token\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tusername: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Username associated with the token\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\ttoken_type: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Type of the token\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\texp: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Expiration time of the token (seconds since epoch)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tiat: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Issued at time (seconds since epoch)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tnbf: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Not before time (seconds since epoch)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tsub: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Subject of the token\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\taud: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Audience of the token\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tiss: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Issuer of the token\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tjti: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"JWT ID\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trequired: [\"active\"],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"400\": {\n\t\t\t\t\t\t\t\t\tdescription: \"Invalid request or error response\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\terror: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\terror_description: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\terror_uri: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trequired: [\"error\"],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\treturn introspectEndpoint(ctx, opts);\n\t\t\t\t},\n\t\t\t),\n\t\t\toauth2Revoke: createAuthEndpoint(\n\t\t\t\t\"/oauth2/revoke\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: z.object({\n\t\t\t\t\t\tclient_id: z.string().optional(),\n\t\t\t\t\t\tclient_secret: z.string().optional(),\n\t\t\t\t\t\ttoken: z.string(),\n\t\t\t\t\t\ttoken_type_hint: z\n\t\t\t\t\t\t\t.enum([\"access_token\", \"refresh_token\"])\n\t\t\t\t\t\t\t.optional(),\n\t\t\t\t\t}),\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tallowedMediaTypes: [\"application/x-www-form-urlencoded\"],\n\t\t\t\t\t\topenapi: {\n\t\t\t\t\t\t\tdescription: \"Revoke an OAuth2 access or refresh token\",\n\t\t\t\t\t\t\trequestBody: {\n\t\t\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\tclient_id: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"OAuth2 client ID\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tclient_secret: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"OAuth2 client secret\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"The token to revoke (access or refresh token)\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\ttoken_type_hint: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tenum: [\"access_token\", \"refresh_token\"],\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Hint about the type of the token submitted for revocation\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trequired: [\"token\"],\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\"Token revoked successfully. The response body is empty.\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Empty object on success\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"400\": {\n\t\t\t\t\t\t\t\t\tdescription: \"Invalid request or error response\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\terror: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\terror_description: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\terror_uri: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trequired: [\"error\"],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\treturn revokeEndpoint(ctx, opts);\n\t\t\t\t},\n\t\t\t),\n\t\t\toauth2UserInfo: createAuthEndpoint(\n\t\t\t\t\"/oauth2/userinfo\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\topenapi: {\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\"Get OpenID Connect user information (UserInfo endpoint)\",\n\t\t\t\t\t\t\tsecurity: [\n\t\t\t\t\t\t\t\t{ bearerAuth: [] },\n\t\t\t\t\t\t\t\t{ OAuth2: [\"openid\", \"profile\", \"email\"] },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tparameters: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: \"Authorization\",\n\t\t\t\t\t\t\t\t\tin: \"header\",\n\t\t\t\t\t\t\t\t\trequired: false,\n\t\t\t\t\t\t\t\t\tschema: { type: \"string\" },\n\t\t\t\t\t\t\t\t\tdescription: \"Bearer access token\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\t\t\tdescription: \"User information retrieved successfully\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tsub: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Subject identifier (user ID)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\temail: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"email\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"User's email address, included if 'email' scope is granted\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"User's full name, included if 'profile' scope is granted\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tpicture: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"uri\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"User's profile picture URL, included if 'profile' scope is granted\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tgiven_name: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"User's given name, included if 'profile' scope is granted\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tfamily_name: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"User's family name, included if 'profile' scope is granted\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\temail_verified: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Whether the email is verified, included if 'email' scope is granted\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trequired: [\"sub\"],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"401\": {\n\t\t\t\t\t\t\t\t\tdescription: \"Unauthorized - invalid or missing access token\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\terror: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\terror_description: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trequired: [\"error\"],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"403\": {\n\t\t\t\t\t\t\t\t\tdescription: \"Forbidden - insufficient scope\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\terror: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\terror_description: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trequired: [\"error\"],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\treturn userInfoEndpoint(ctx, opts);\n\t\t\t\t},\n\t\t\t),\n\t\t\toauth2EndSession: createAuthEndpoint(\n\t\t\t\t\"/oauth2/end-session\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tquery: z.object({\n\t\t\t\t\t\tid_token_hint: z.string(),\n\t\t\t\t\t\tclient_id: z.string().optional(),\n\t\t\t\t\t\tpost_logout_redirect_uri: SafeUrlSchema.optional(),\n\t\t\t\t\t\tstate: z.string().optional(),\n\t\t\t\t\t}),\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\topenapi: {\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\"RP-Initiated Logout endpoint. Allows clients to notify the OP that the End-User has logged out.\",\n\t\t\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\"Logout successful. May include redirect_uri if post_logout_redirect_uri was provided.\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tredirect_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"uri\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"URI to redirect to after logout (if post_logout_redirect_uri was provided)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Success message\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\treturn rpInitiatedLogoutEndpoint(ctx, opts);\n\t\t\t\t},\n\t\t\t),\n\t\t\tregisterOAuthClient: createAuthEndpoint(\n\t\t\t\t\"/oauth2/register\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: z.object({\n\t\t\t\t\t\tredirect_uris: z.array(SafeUrlSchema).min(1).min(1),\n\t\t\t\t\t\tscope: z.string().optional(),\n\t\t\t\t\t\tclient_name: z.string().optional(),\n\t\t\t\t\t\tclient_uri: z.string().optional(),\n\t\t\t\t\t\tlogo_uri: z.string().optional(),\n\t\t\t\t\t\tcontacts: z.array(z.string().min(1)).min(1).optional(),\n\t\t\t\t\t\ttos_uri: z.string().optional(),\n\t\t\t\t\t\tpolicy_uri: z.string().optional(),\n\t\t\t\t\t\tsoftware_id: z.string().optional(),\n\t\t\t\t\t\tsoftware_version: z.string().optional(),\n\t\t\t\t\t\tsoftware_statement: z.string().optional(),\n\t\t\t\t\t\tpost_logout_redirect_uris: z.array(SafeUrlSchema).min(1).optional(),\n\t\t\t\t\t\ttoken_endpoint_auth_method: z\n\t\t\t\t\t\t\t.enum([\"none\", \"client_secret_basic\", \"client_secret_post\"])\n\t\t\t\t\t\t\t.default(\"client_secret_basic\")\n\t\t\t\t\t\t\t.optional(),\n\t\t\t\t\t\tgrant_types: z\n\t\t\t\t\t\t\t.array(\n\t\t\t\t\t\t\t\tz.enum([\n\t\t\t\t\t\t\t\t\t\"authorization_code\",\n\t\t\t\t\t\t\t\t\t\"client_credentials\",\n\t\t\t\t\t\t\t\t\t\"refresh_token\",\n\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.default([\"authorization_code\"])\n\t\t\t\t\t\t\t.optional(),\n\t\t\t\t\t\tresponse_types: z\n\t\t\t\t\t\t\t.array(z.enum([\"code\"]))\n\t\t\t\t\t\t\t.default([\"code\"])\n\t\t\t\t\t\t\t.optional(),\n\t\t\t\t\t\ttype: z.enum([\"web\", \"native\", \"user-agent-based\"]).optional(),\n\t\t\t\t\t}),\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\topenapi: {\n\t\t\t\t\t\t\tdescription: \"Register an OAuth2 application\",\n\t\t\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\t\t\tdescription: \"OAuth2 application registered successfully\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\t/** @returns {OauthClient} */\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tclient_id: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Unique identifier for the client\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tclient_secret: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Secret key for the client\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tclient_secret_expires_at: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Time the client secret will expire. If 0, the client secret will never expire.\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tscope: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Space-separated scopes allowed by the client\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tuser_id: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"ID of the user who registered the client, null if registered anonymously\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tclient_id_issued_at: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Creation timestamp of this client\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tclient_name: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Name of the OAuth2 application\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tclient_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Name of the OAuth2 application\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tlogo_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Icon URL for the application\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tcontacts: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"List representing ways to contact people responsible for this client, typically email addresses\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\ttos_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Client's terms of service uri\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tpolicy_uri: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Client's policy uri\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tsoftware_id: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Unique identifier assigned by the developer to help in the dynamic registration process\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tsoftware_version: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Version identifier for the software_id\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tsoftware_statement: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"JWT containing metadata values about the client software as claims\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tredirect_uris: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"uri\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"List of allowed redirect uris\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tpost_logout_redirect_uris: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"uri\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"List of allowed logout redirect uris\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\ttoken_endpoint_auth_method: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Requested authentication method for the token endpoint\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tenum: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"client_secret_basic\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"client_secret_post\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tgrant_types: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tenum: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"authorization_code\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"client_credentials\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"refresh_token\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Requested authentication method for the token endpoint\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tresponse_types: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tenum: [\"code\"],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Requested authentication method for the token endpoint\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tpublic: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Whether the client is public as determined by the type\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Type of the client\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tenum: [\"web\", \"native\", \"user-agent-based\"],\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Whether the client is disabled\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trequired: [\"client_id\"],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\treturn registerEndpoint(ctx, opts);\n\t\t\t\t},\n\t\t\t),\n\t\t\tadminCreateOAuthClient: oauthClientEndpoints.adminCreateOAuthClient(opts),\n\t\t\tcreateOAuthClient: oauthClientEndpoints.createOAuthClient(opts),\n\t\t\tgetOAuthClient: oauthClientEndpoints.getOAuthClient(opts),\n\t\t\tgetOAuthClientPublic: oauthClientEndpoints.getOAuthClientPublic(opts),\n\t\t\tgetOAuthClients: oauthClientEndpoints.getOAuthClients(opts),\n\t\t\tadminUpdateOAuthClient: oauthClientEndpoints.adminUpdateOAuthClient(opts),\n\t\t\tupdateOAuthClient: oauthClientEndpoints.updateOAuthClient(opts),\n\t\t\trotateClientSecret: oauthClientEndpoints.rotateClientSecret(opts),\n\t\t\tdeleteOAuthClient: oauthClientEndpoints.deleteOAuthClient(opts),\n\t\t\tgetOAuthConsent: oauthConsentEndpoints.getOAuthConsent(opts),\n\t\t\tgetOAuthConsents: oauthConsentEndpoints.getOAuthConsents(opts),\n\t\t\tupdateOAuthConsent: oauthConsentEndpoints.updateOAuthConsent(opts),\n\t\t\tdeleteOAuthConsent: oauthConsentEndpoints.deleteOAuthConsent(opts),\n\t\t},\n\t\tschema: mergeSchema(schema, opts?.schema),\n\t} satisfies BetterAuthPlugin;\n};\n"],"mappings":"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N,UAAU;IACV;GACD,MAAM;IACL,MAAM;IACN,UAAU;IACV;GACD,UAAU;IACT,MAAM;IACN,UAAU;IACV;GACD,KAAK;IACJ,MAAM;IACN,UAAU;IACV;GACD,QAAQ;IACP,MAAM;IACN,UAAU;IACV;GAED,YAAY;IACX,MAAM;IACN,UAAU;IACV;GACD,iBAAiB;IAChB,MAAM;IACN,UAAU;IACV;GACD,mBAAmB;IAClB,MAAM;IACN,UAAU;IACV;GAED,cAAc;IACb,MAAM;IACN,UAAU;IACV;GACD,wBAAwB;IACvB,MAAM;IACN,UAAU;IACV;GACD,yBAAyB;IACxB,MAAM;IACN,UAAU;IACV;GACD,YAAY;IACX,MAAM;IACN,UAAU;IACV;GACD,eAAe;IACd,MAAM;IACN,UAAU;IACV;GAED,QAAQ;IACP,MAAM;IACN,UAAU;IACV;GACD,MAAM;IACL,MAAM;IACN,UAAU;IACV;GAED,aAAa;IACZ,MAAM;IACN,UAAU;IACV;GACD,UAAU;IACT,MAAM;IACN,UAAU;IACV;GACD;EACD;CAMD,mBAAmB,EAClB,QAAQ;EACP,OAAO;GACN,MAAM;GACN,UAAU;GACV;EACD,UAAU;GACT,MAAM;GACN,UAAU;GACV,YAAY;IACX,OAAO;IACP,OAAO;IACP;GACD;EAED,WAAW;GACV,MAAM;GACN,UAAU;GACV,YAAY;IACX,OAAO;IACP,OAAO;IAEP,UAAU;IACV;GACD;EACD,QAAQ;GACP,MAAM;GACN,UAAU;GACV,YAAY;IACX,OAAO;IACP,OAAO;IACP;GACD;EACD,aAAa;GACZ,MAAM;GACN,UAAU;GACV;EACD,WAAW,EACV,MAAM,QACN;EACD,WAAW,EACV,MAAM,QACN;EACD,SAAS;GACR,MAAM;GACN,UAAU;GACV;EAED,QAAQ;GACP,MAAM;GACN,UAAU;GACV;EACD,EACD;CAaD,kBAAkB;EACjB,WAAW;EACX,QAAQ;GACP,OAAO;IACN,MAAM;IACN,QAAQ;IACR;GACD,UAAU;IACT,MAAM;IACN,UAAU;IACV,YAAY;KACX,OAAO;KACP,OAAO;KACP;IACD;GACD,WAAW;IACV,MAAM;IAEN,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AAC,UAAU;KAC/B,OAAO,EAAE,QAAQ,CAAC,UAAU;KAC5B,CAAC;IACF,UAAU;KACT,mBAAmB,CAAC,oCAAoC;KACxD,SAAS;MACR,aAAa;MACb,aAAa;OACZ,UAAU;OACV,SAAS,EACR,oBAAoB,EACnB,QAAQ;QACP,MAAM;QACN,YAAY;SACX,YAAY;UACX,MAAM;UACN,MAAM;WACL;WACA;WACA;WACA;UACD,aAAa;UACb;SACD,WAAW;UACV,MAAM;UACN,aAAa;UACb;SACD,eAAe;UACd,MAAM;UACN,aAAa;UACb;SACD,MAAM;UACL,MAAM;UACN,aACC;UACD;SACD,eAAe;UACd,MAAM;UACN,aACC;UACD;SACD,cAAc;UACb,MAAM;UACN,QAAQ;UACR,aACC;UACD;SACD,eAAe;UACd,MAAM;UACN,aACC;UACD;SACD,UAAU;UACT,MAAM;UACN,aACC;UACD;SACD,OAAO;UACN,MAAM;UACN,aACC;UACD;SACD;QACD,UAAU,CAAC,aAAa;QACxB,EACD,EACD;OACD;MACD,WAAW;OACV,OAAO;QACN,aAAa;QACb,SAAS,EACR,oBAAoB,EACnB,QAAQ;SACP,MAAM;SACN,YAAY;UACX,cAAc;WACb,MAAM;WACN,aACC;WACD;UACD,YAAY;WACX,MAAM;WACN,aAAa;WACb,MAAM,CAAC,SAAS;WAChB;UACD,YAAY;WACX,MAAM;WACN,aACC;WACD;UACD,eAAe;WACd,MAAM;WACN,aAAa;WACb;UACD,OAAO;WACN,MAAM;WACN,aAAa;WACb;UACD,UAAU;WACT,MAAM;WACN,aAAa;WACb;UACD;SACD,UAAU;UAAC;UAAgB;UAAc;UAAa;SACtD,EACD,EACD;QACD;OACD,OAAO;QACN,aAAa;QACb,SAAS,EACR,oBAAoB,EACnB,QAAQ;SACP,MAAM;SACN,YAAY;UACX,OAAO,EAAE,MAAM,UAAU;UACzB,mBAAmB,EAAE,MAAM,UAAU;UACrC,WAAW,EAAE,MAAM,UAAU;UAC7B;SACD,UAAU,CAAC,QAAQ;SACnB,EACD,EACD;QACD;OACD;MACD;KACD;IACD,EACD,OAAO,QAAQ;AACd,WAAO,cAAc,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"}
@@ -1479,4 +1479,5 @@ interface ResourceServerMetadata {
1479
1479
  dpop_bound_access_tokens_required?: boolean;
1480
1480
  }
1481
1481
  //#endregion
1482
- export { Awaitable as _, ResourceServerMetadata as a, OAuthConsent as c, OAuthRefreshToken as d, Prompt as f, VerificationValue as g, StoreTokenType as h, OIDCMetadata as i, OAuthOpaqueAccessToken as l, Scope as m, GrantType as n, AuthorizePrompt as o, SchemaClient as p, OAuthClient as r, OAuthAuthorizationQuery as s, AuthServerMetadata as t, OAuthOptions as u };
1482
+ export { Awaitable as _, ResourceServerMetadata as a, OAuthConsent as c, OAuthRefreshToken as d, Prompt as f, VerificationValue as g, StoreTokenType as h, OIDCMetadata as i, OAuthOpaqueAccessToken as l, Scope as m, GrantType as n, AuthorizePrompt as o, SchemaClient as p, OAuthClient as r, OAuthAuthorizationQuery as s, AuthServerMetadata as t, OAuthOptions as u };
1483
+ //# sourceMappingURL=oauth-BrFoF22H.d.mts.map
@@ -2003,4 +2003,5 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
2003
2003
  };
2004
2004
  };
2005
2005
  //#endregion
2006
- export { oauthProvider as t };
2006
+ export { oauthProvider as t };
2007
+ //# sourceMappingURL=oauth-BxSSTB3p.d.mts.map
@@ -256,6 +256,16 @@ async function validateClientCredentials(ctx, options, clientId, clientSecret, s
256
256
  return client;
257
257
  }
258
258
  /**
259
+ * Parse client metadata that may be stored as JSON string or already parsed object.
260
+ * Handles database adapters that auto-parse JSON columns.
261
+ *
262
+ * @internal
263
+ */
264
+ function parseClientMetadata(metadata) {
265
+ if (!metadata) return void 0;
266
+ return typeof metadata === "string" ? JSON.parse(metadata) : metadata;
267
+ }
268
+ /**
259
269
  * Parse space-separated prompt string into a set of prompts
260
270
  *
261
271
  * @param prompt
@@ -283,4 +293,5 @@ function deleteFromPrompt(query, prompt) {
283
293
  }
284
294
 
285
295
  //#endregion
286
- export { getJwtPlugin as a, parsePrompt as c, validateClientCredentials as d, handleMcpErrors as f, getClient as i, storeClientSecret as l, decryptStoredClientSecret as n, getOAuthProviderPlugin as o, mcpHandler as p, deleteFromPrompt as r, getStoredToken as s, basicToClientCredentials as t, storeToken as u };
296
+ export { getJwtPlugin as a, parseClientMetadata as c, storeToken as d, validateClientCredentials as f, getClient as i, parsePrompt as l, mcpHandler as m, decryptStoredClientSecret as n, getOAuthProviderPlugin as o, handleMcpErrors as p, deleteFromPrompt as r, getStoredToken as s, basicToClientCredentials as t, storeClientSecret as u };
297
+ //# sourceMappingURL=utils-DnfreTWo.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils-DnfreTWo.mjs","names":["audiencePath: string"],"sources":["../src/mcp.ts","../src/utils/index.ts"],"sourcesContent":["import { verifyAccessToken } from \"better-auth/oauth2\";\nimport { APIError } from \"better-call\";\nimport type { JWTPayload } from \"jose\";\nimport type { Awaitable } from \"./types/helpers\";\n\n/**\n * A request middleware handler that checks and responds with\n * a WWW-Authenticate header for unauthenticated responses.\n *\n * @external\n */\nexport const mcpHandler = (\n\t/** Resource is the same url as the audience */\n\tverifyOptions: Parameters<typeof verifyAccessToken>[1],\n\thandler: (req: Request, jwt: JWTPayload) => Awaitable<Response>,\n\topts?: {\n\t\t/** Maps non-url (ie urn, client) resources to resource_metadata */\n\t\tresourceMetadataMappings: Record<string, string>;\n\t},\n) => {\n\treturn async (req: Request) => {\n\t\tconst authorization = req.headers?.get(\"authorization\") ?? undefined;\n\t\tconst accessToken = authorization?.startsWith(\"Bearer \")\n\t\t\t? authorization.replace(\"Bearer \", \"\")\n\t\t\t: authorization;\n\t\ttry {\n\t\t\tif (!accessToken?.length) {\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: \"missing authorization header\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst token = await verifyAccessToken(accessToken, verifyOptions);\n\t\t\treturn handler(req, token);\n\t\t} catch (error) {\n\t\t\ttry {\n\t\t\t\thandleMcpErrors(error, verifyOptions.verifyOptions.audience, opts);\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof APIError) {\n\t\t\t\t\treturn new Response(err.message, {\n\t\t\t\t\t\t...err,\n\t\t\t\t\t\tstatus: err.statusCode,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tthrow new Error(String(err));\n\t\t\t}\n\t\t\tthrow new Error(String(error));\n\t\t}\n\t};\n};\n\n/**\n * The following handles all MCP errors and API errors\n *\n * @internal\n */\nexport function handleMcpErrors(\n\terror: unknown,\n\tresource: string | string[],\n\topts?: {\n\t\t/** Maps non-url (ie urn, client) resources to resource_metadata */\n\t\tresourceMetadataMappings?: Record<string, string>;\n\t},\n) {\n\tif (error instanceof APIError && error.status === \"UNAUTHORIZED\") {\n\t\tconst _resources = Array.isArray(resource) ? resource : [resource];\n\t\tconst wwwAuthenticateValue = _resources\n\t\t\t.map((v) => {\n\t\t\t\tlet audiencePath: string;\n\t\t\t\tif (URL.canParse?.(v)) {\n\t\t\t\t\tconst url = new URL(v);\n\t\t\t\t\taudiencePath = url.pathname.endsWith(\"/\")\n\t\t\t\t\t\t? url.pathname.slice(0, -1)\n\t\t\t\t\t\t: url.pathname;\n\t\t\t\t\treturn `Bearer resource_metadata=\"${url.origin}/.well-known/oauth-protected-resource${\n\t\t\t\t\t\taudiencePath\n\t\t\t\t\t}\"`;\n\t\t\t\t} else {\n\t\t\t\t\tconst resourceMetadata = opts?.resourceMetadataMappings?.[v];\n\t\t\t\t\tif (!resourceMetadata) {\n\t\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\t\tmessage: `missing resource_metadata mapping for ${v}`,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn `Bearer resource_metadata=${resourceMetadata}`;\n\t\t\t\t}\n\t\t\t})\n\t\t\t.join(\", \");\n\t\tthrow new APIError(\n\t\t\t\"UNAUTHORIZED\",\n\t\t\t{\n\t\t\t\tmessage: error.message,\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"WWW-Authenticate\": wwwAuthenticateValue,\n\t\t\t},\n\t\t);\n\t} else if (error instanceof Error) {\n\t\tthrow error;\n\t} else {\n\t\tthrow new Error(error as unknown as string);\n\t}\n}\n","import type { AuthContext, GenericEndpointContext } from \"@better-auth/core\";\nimport { BetterAuthError } from \"@better-auth/core/error\";\nimport { base64, base64Url } from \"@better-auth/utils/base64\";\nimport { createHash } from \"@better-auth/utils/hash\";\nimport {\n\tconstantTimeEqual,\n\tsymmetricDecrypt,\n\tsymmetricEncrypt,\n} from \"better-auth/crypto\";\nimport type { jwt } from \"better-auth/plugins\";\nimport type { Auth } from \"better-auth/types\";\nimport { APIError } from \"better-call\";\nimport type { oauthProvider } from \"..\";\nimport type {\n\tOAuthOptions,\n\tPrompt,\n\tSchemaClient,\n\tScope,\n\tStoreTokenType,\n} from \"../types\";\n\nclass TTLCache<K, V extends { expiresAt?: Date }> {\n\tprivate cache = new Map<K, V>();\n\tconstructor() {}\n\n\tset(key: K, value: V) {\n\t\tthis.cache.set(key, value);\n\t}\n\n\tget(key: K): V | undefined {\n\t\tconst entry = this.cache.get(key);\n\t\tif (!entry) return undefined;\n\t\tif (entry.expiresAt && entry.expiresAt < new Date()) {\n\t\t\tthis.cache.delete(key);\n\t\t\treturn undefined;\n\t\t}\n\t\treturn entry;\n\t}\n}\n\n/**\n * Gets the oAuth Provider Plugin\n * @internal\n */\nexport const getOAuthProviderPlugin = (ctx: AuthContext | Auth) => {\n\treturn ctx.options.plugins?.find(\n\t\t(plugin) => plugin.id === \"oauthProvider\",\n\t) as ReturnType<typeof oauthProvider>;\n};\n\n/**\n * Gets the JWT Plugin\n * @internal\n */\nexport const getJwtPlugin = (ctx: AuthContext): ReturnType<typeof jwt> => {\n\tconst plugin = ctx.getPlugin<ReturnType<typeof jwt>>(\"jwt\");\n\tif (!plugin) {\n\t\tthrow new BetterAuthError(\"jwt_config\", \"jwt plugin not found\");\n\t}\n\treturn plugin;\n};\n\nconst cachedTrustedClients = new TTLCache<string, SchemaClient<Scope[]>>();\n\n/**\n * Get a client by ID, checking trusted clients first, then database\n */\nexport async function getClient(\n\tctx: GenericEndpointContext,\n\toptions: OAuthOptions<Scope[]>,\n\tclientId: string,\n) {\n\tconst trustedClient = cachedTrustedClients.get(clientId);\n\tif (trustedClient) {\n\t\treturn Object.assign({}, trustedClient);\n\t}\n\n\tconst dbClient = await ctx.context.adapter.findOne<SchemaClient<Scope[]>>({\n\t\tmodel: options.schema?.oauthClient?.modelName ?? \"oauthClient\",\n\t\twhere: [{ field: \"clientId\", value: clientId }],\n\t});\n\n\tif (dbClient && options.cachedTrustedClients?.has(clientId)) {\n\t\tcachedTrustedClients.set(clientId, Object.assign({}, dbClient));\n\t}\n\n\treturn dbClient;\n}\n\n/**\n * Default client secret hasher using SHA-256\n *\n * @internal\n */\nconst defaultHasher = async (value: string) => {\n\tconst hash = await createHash(\"SHA-256\").digest(\n\t\tnew TextEncoder().encode(value),\n\t);\n\tconst hashed = base64Url.encode(new Uint8Array(hash), {\n\t\tpadding: false,\n\t});\n\treturn hashed;\n};\n\n/**\n * Decrypts a storedClientSecret for signing\n *\n * @internal\n */\nexport async function decryptStoredClientSecret(\n\tctx: GenericEndpointContext,\n\tstorageMethod: OAuthOptions<Scope[]>[\"storeClientSecret\"],\n\tstoredClientSecret: string,\n) {\n\tif (storageMethod === \"encrypted\") {\n\t\treturn await symmetricDecrypt({\n\t\t\tkey: ctx.context.secret,\n\t\t\tdata: storedClientSecret,\n\t\t});\n\t} else if (typeof storageMethod === \"object\" && \"decrypt\" in storageMethod) {\n\t\treturn await storageMethod.decrypt(storedClientSecret);\n\t}\n\n\tthrow new BetterAuthError(\n\t\t`Unsupported decryption storageMethod type '${storageMethod}'`,\n\t);\n}\n\n/**\n * Verify stored client secret against provided client secret\n *\n * @internal\n */\nasync function verifyStoredClientSecret(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\tstoredClientSecret: string,\n\tclientSecret?: string,\n): Promise<boolean> {\n\tconst storageMethod =\n\t\topts.storeClientSecret ?? (opts.disableJwtPlugin ? \"encrypted\" : \"hashed\");\n\n\tif (clientSecret && opts.prefix?.clientSecret) {\n\t\tif (clientSecret.startsWith(opts.prefix?.clientSecret)) {\n\t\t\tclientSecret = clientSecret.replace(opts.prefix.clientSecret, \"\");\n\t\t} else {\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\terror_description: \"invalid client_secret\",\n\t\t\t\terror: \"invalid_client\",\n\t\t\t});\n\t\t}\n\t}\n\n\tif (storageMethod === \"hashed\") {\n\t\tconst hashedClientSecret = clientSecret\n\t\t\t? await defaultHasher(clientSecret)\n\t\t\t: undefined;\n\t\treturn (\n\t\t\t!!hashedClientSecret &&\n\t\t\tconstantTimeEqual(hashedClientSecret, storedClientSecret)\n\t\t);\n\t} else if (typeof storageMethod === \"object\" && \"hash\" in storageMethod) {\n\t\tif (storageMethod.verify) {\n\t\t\treturn (\n\t\t\t\t!!clientSecret &&\n\t\t\t\t(await storageMethod.verify(clientSecret, storedClientSecret))\n\t\t\t);\n\t\t} else {\n\t\t\tconst hashedClientSecret = clientSecret\n\t\t\t\t? await storageMethod.hash(clientSecret)\n\t\t\t\t: undefined;\n\t\t\treturn (\n\t\t\t\t!!hashedClientSecret &&\n\t\t\t\tconstantTimeEqual(hashedClientSecret, storedClientSecret)\n\t\t\t);\n\t\t}\n\t} else if (\n\t\tstorageMethod === \"encrypted\" ||\n\t\t(typeof storageMethod === \"object\" && \"decrypt\" in storageMethod)\n\t) {\n\t\tconst decryptedClientSecret = await decryptStoredClientSecret(\n\t\t\tctx,\n\t\t\tstorageMethod,\n\t\t\tstoredClientSecret,\n\t\t);\n\t\treturn (\n\t\t\t!!clientSecret && constantTimeEqual(decryptedClientSecret, clientSecret)\n\t\t);\n\t}\n\n\tthrow new BetterAuthError(\n\t\t`Unsupported verify storageMethod type '${storageMethod}'`,\n\t);\n}\n\n/**\n * Store client secret according to the configured storage method\n *\n * @internal\n */\nexport async function storeClientSecret(\n\tctx: GenericEndpointContext,\n\topts: OAuthOptions<Scope[]>,\n\tclientSecret: string,\n) {\n\tconst storageMethod =\n\t\topts.storeClientSecret ?? (opts.disableJwtPlugin ? \"encrypted\" : \"hashed\");\n\n\tif (storageMethod === \"encrypted\") {\n\t\treturn await symmetricEncrypt({\n\t\t\tkey: ctx.context.secret,\n\t\t\tdata: clientSecret,\n\t\t});\n\t} else if (storageMethod === \"hashed\") {\n\t\treturn await defaultHasher(clientSecret);\n\t} else if (typeof storageMethod === \"object\" && \"hash\" in storageMethod) {\n\t\treturn await storageMethod.hash(clientSecret);\n\t} else if (typeof storageMethod === \"object\" && \"encrypt\" in storageMethod) {\n\t\treturn await storageMethod.encrypt(clientSecret);\n\t}\n\n\tthrow new BetterAuthError(\n\t\t`Unsupported storeClientSecret type '${storageMethod}'`,\n\t);\n}\n\n/**\n * Stores a token value (ie opaque tokens, refresh tokens, transaction tokens, verification codes)\n * on the database in a secure hashed format.\n *\n * @internal\n */\nexport async function storeToken(\n\tstorageMethod: OAuthOptions<Scope[]>[\"storeTokens\"] = \"hashed\",\n\ttoken: string,\n\ttype: StoreTokenType,\n) {\n\tif (storageMethod === \"hashed\") {\n\t\treturn await defaultHasher(token);\n\t} else if (typeof storageMethod === \"object\" && \"hash\" in storageMethod) {\n\t\treturn await storageMethod.hash(token, type);\n\t}\n\n\tthrow new BetterAuthError(\n\t\t`storeToken: unsupported storageMethod type '${storageMethod}'`,\n\t);\n}\n\n/**\n * Gets a hashed token value to find on the database.\n *\n * @internal\n */\nexport async function getStoredToken(\n\tstorageMethod: OAuthOptions<Scope[]>[\"storeTokens\"] = \"hashed\",\n\ttoken: string,\n\ttype: StoreTokenType,\n) {\n\tif (storageMethod === \"hashed\") {\n\t\tconst hashedToken = await defaultHasher(token);\n\t\treturn hashedToken;\n\t} else if (typeof storageMethod === \"object\" && \"hash\" in storageMethod) {\n\t\tconst hashedToken = await storageMethod.hash(token, type);\n\t\treturn hashedToken;\n\t}\n\n\tthrow new BetterAuthError(\n\t\t`getStoredToken: unsupported storageMethod type '${storageMethod}'`,\n\t);\n}\n\n/**\n * Converts a BASIC authorization header\n * into its client_id and client_secret representation\n *\n * @internal\n */\nexport function basicToClientCredentials(authorization: string) {\n\tif (authorization.startsWith(\"Basic \")) {\n\t\tconst encoded = authorization.replace(\"Basic \", \"\");\n\t\tconst decoded = new TextDecoder().decode(base64.decode(encoded));\n\t\tif (!decoded.includes(\":\")) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\terror_description: \"invalid authorization header format\",\n\t\t\t\terror: \"invalid_client\",\n\t\t\t});\n\t\t}\n\t\tconst [id, secret] = decoded.split(\":\", 2);\n\t\tif (!id || !secret) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\terror_description: \"invalid authorization header format\",\n\t\t\t\terror: \"invalid_client\",\n\t\t\t});\n\t\t}\n\t\treturn {\n\t\t\tclient_id: id,\n\t\t\tclient_secret: secret,\n\t\t};\n\t}\n}\n\n/**\n * Validates client credentials failing on mismatches\n * and incorrectly provided information\n *\n * @internal\n */\nexport async function validateClientCredentials(\n\tctx: GenericEndpointContext,\n\toptions: OAuthOptions<Scope[]>,\n\tclientId: string,\n\tclientSecret?: string, // optional because required if client is confidential or this value is defined\n\tscopes?: string[], // checks requested scopes against allowed scopes\n) {\n\tconst client = await getClient(ctx, options, clientId);\n\tif (!client) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"missing client\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\tif (client.disabled) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"client is disabled\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\n\t// Require secret for confidential clients\n\tif (!client.public && !clientSecret) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"client secret must be provided\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\n\t// Secret should not be received\n\tif (clientSecret && !client.clientSecret) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\terror_description: \"public client, client secret should not be received\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\n\t// Compare Secrets when secret is provided\n\tif (\n\t\tclientSecret &&\n\t\t!(await verifyStoredClientSecret(\n\t\t\tctx,\n\t\t\toptions,\n\t\t\tclient.clientSecret!,\n\t\t\tclientSecret,\n\t\t))\n\t) {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\terror_description: \"invalid client_secret\",\n\t\t\terror: \"invalid_client\",\n\t\t});\n\t}\n\n\t// If scopes set, check against client allowed scopes\n\tif (scopes && client.scopes) {\n\t\tconst validScopes = new Set(client.scopes);\n\t\tfor (const sc of scopes) {\n\t\t\tif (!validScopes.has(sc)) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\terror_description: `client does not allow scope ${sc}`,\n\t\t\t\t\terror: \"invalid_scope\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn client;\n}\n\n/**\n * Parse client metadata that may be stored as JSON string or already parsed object.\n * Handles database adapters that auto-parse JSON columns.\n *\n * @internal\n */\nexport function parseClientMetadata(\n\tmetadata: string | object | undefined,\n): object | undefined {\n\tif (!metadata) return undefined;\n\treturn typeof metadata === \"string\" ? JSON.parse(metadata) : metadata;\n}\n\n/**\n * Parse space-separated prompt string into a set of prompts\n *\n * @param prompt\n */\nexport function parsePrompt(prompt: string) {\n\tconst prompts = prompt.split(\" \").map((p) => p.trim());\n\tconst set = new Set<Prompt>();\n\tfor (const p of prompts) {\n\t\tif (\n\t\t\tp === \"login\" ||\n\t\t\tp === \"consent\" ||\n\t\t\tp === \"create\" ||\n\t\t\tp === \"select_account\" ||\n\t\t\tp === \"none\"\n\t\t) {\n\t\t\tset.add(p);\n\t\t}\n\t}\n\treturn new Set(set);\n}\n\n/**\n * Deletes a prompt value\n *\n * @param ctx\n * @param prompt - the prompt value to delete\n */\nexport function deleteFromPrompt(query: URLSearchParams, prompt: Prompt) {\n\tconst prompts = query.get(\"prompt\")?.split(\" \");\n\tconst foundPrompt = prompts?.findIndex((v) => v === prompt) ?? -1;\n\tif (foundPrompt >= 0) {\n\t\tprompts?.splice(foundPrompt, 1);\n\t\tprompts?.length\n\t\t\t? query.set(\"prompt\", prompts.join(\" \"))\n\t\t\t: query.delete(\"prompt\");\n\t}\n\treturn Object.fromEntries(query);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/oauth-provider",
3
- "version": "1.4.17",
3
+ "version": "1.4.18",
4
4
  "type": "module",
5
5
  "description": "An oauth provider plugin for Better Auth",
6
6
  "main": "dist/index.mjs",
@@ -42,8 +42,8 @@
42
42
  "@modelcontextprotocol/sdk": "^1.25.2",
43
43
  "listhen": "^1.9.0",
44
44
  "tsdown": "^0.17.2",
45
- "@better-auth/core": "1.4.17",
46
- "better-auth": "1.4.17"
45
+ "@better-auth/core": "1.4.18",
46
+ "better-auth": "1.4.18"
47
47
  },
48
48
  "dependencies": {
49
49
  "jose": "^6.1.0",
@@ -53,8 +53,8 @@
53
53
  "@better-auth/utils": "0.3.0",
54
54
  "@better-fetch/fetch": "1.1.21",
55
55
  "better-call": "1.1.8",
56
- "@better-auth/core": "1.4.17",
57
- "better-auth": "1.4.17"
56
+ "@better-auth/core": "1.4.18",
57
+ "better-auth": "1.4.18"
58
58
  },
59
59
  "files": [
60
60
  "dist"
@@ -74,6 +74,7 @@
74
74
  "license": "MIT",
75
75
  "scripts": {
76
76
  "test": "vitest",
77
+ "coverage": "vitest run --coverage --coverage.provider=istanbul",
77
78
  "lint:package": "publint run --strict",
78
79
  "build": "tsdown",
79
80
  "dev": "tsdown --watch",