better-auth 1.7.2 → 1.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/dispatch.mjs +4 -1
- package/dist/api/index.d.mts +6 -22
- package/dist/api/index.mjs +5 -1
- package/dist/api/routes/account.d.mts +1 -9
- package/dist/api/routes/account.mjs +0 -6
- package/dist/api/routes/callback.mjs +0 -2
- package/dist/api/routes/password.mjs +0 -2
- package/dist/api/routes/session.mjs +12 -5
- package/dist/api/routes/sign-in.d.mts +2 -2
- package/dist/api/routes/sign-in.mjs +1 -5
- package/dist/api/routes/sign-up.mjs +0 -2
- package/dist/api/routes/update-user.mjs +0 -2
- package/dist/api/to-auth-endpoints.mjs +2 -0
- package/dist/auth/base.mjs +13 -1
- package/dist/auth/trusted-origins.mjs +6 -4
- package/dist/client/config.d.mts +2 -0
- package/dist/client/config.mjs +1 -0
- package/dist/client/vue/index.d.mts +31 -20
- package/dist/client/vue/index.mjs +23 -5
- package/dist/context/create-context.mjs +2 -0
- package/dist/cookies/session-store.d.mts +0 -1
- package/dist/cookies/session-store.mjs +16 -5
- package/dist/db/adapter-kysely.mjs +1 -2
- package/dist/db/get-migration.d.mts +1 -0
- package/dist/db/get-migration.mjs +10 -32
- package/dist/db/internal-adapter.mjs +14 -17
- package/dist/db/schema.d.mts +0 -1
- package/dist/db/with-hooks.mjs +2 -1
- package/dist/index.mjs +0 -1
- package/dist/oauth2/account-key.mjs +1 -5
- package/dist/oauth2/link-account.d.mts +0 -1
- package/dist/oauth2/link-account.mjs +5 -11
- package/dist/package.mjs +1 -1
- package/dist/plugins/admin/routes.mjs +0 -3
- package/dist/plugins/device-authorization/index.d.mts +11 -11
- package/dist/plugins/email-otp/routes.mjs +0 -2
- package/dist/plugins/generic-oauth/index.mjs +14 -10
- package/dist/plugins/generic-oauth/providers/auth0.mjs +2 -4
- package/dist/plugins/generic-oauth/providers/keycloak.mjs +6 -9
- package/dist/plugins/generic-oauth/providers/line.mjs +0 -1
- package/dist/plugins/generic-oauth/providers/okta.mjs +6 -9
- package/dist/plugins/generic-oauth/providers/slack.mjs +0 -1
- package/dist/plugins/generic-oauth/types.d.mts +0 -9
- package/dist/plugins/haveibeenpwned/index.d.mts +9 -1
- package/dist/plugins/haveibeenpwned/index.mjs +31 -11
- package/dist/plugins/index.d.mts +3 -3
- package/dist/plugins/index.mjs +2 -2
- package/dist/plugins/last-login-method/index.mjs +1 -0
- package/dist/plugins/oauth-proxy/index.d.mts +17 -0
- package/dist/plugins/oauth-proxy/index.mjs +145 -99
- package/dist/plugins/one-tap/index.mjs +0 -1
- package/dist/plugins/open-api/generator.mjs +15 -1
- package/dist/plugins/open-api/index.mjs +0 -1
- package/dist/plugins/organization/has-permission.mjs +4 -2
- package/dist/plugins/phone-number/routes.mjs +0 -3
- package/dist/plugins/siwe/index.mjs +0 -3
- package/dist/plugins/test-utils/auth-helpers.mjs +8 -3
- package/dist/plugins/test-utils/index.d.mts +1 -1
- package/dist/plugins/test-utils/types.d.mts +10 -9
- package/dist/plugins/two-factor/client.d.mts +1 -0
- package/dist/plugins/two-factor/error-code.d.mts +1 -0
- package/dist/plugins/two-factor/error-code.mjs +1 -0
- package/dist/plugins/two-factor/index.d.mts +1 -0
- package/dist/plugins/two-factor/index.mjs +3 -2
- package/dist/state.d.mts +0 -13
- package/dist/test-utils/test-instance.mjs +10 -9
- package/package.json +12 -12
- package/dist/utils/index.mjs +0 -5
|
@@ -93,7 +93,6 @@ const genericOAuth = (options) => {
|
|
|
93
93
|
return null;
|
|
94
94
|
});
|
|
95
95
|
if (discovered) {
|
|
96
|
-
if (!discovered.issuer && !c.accountIssuer) throw new Error(`Provider "${c.providerId}": discovery did not return an issuer. Configure accountIssuer explicitly to establish a stable account namespace.`);
|
|
97
96
|
authorizationUrl ??= discovered.authorization_endpoint;
|
|
98
97
|
tokenUrl ??= discovered.token_endpoint;
|
|
99
98
|
userInfoUrl ??= discovered.userinfo_endpoint;
|
|
@@ -106,7 +105,8 @@ const genericOAuth = (options) => {
|
|
|
106
105
|
try {
|
|
107
106
|
jwksUrl = new URL(discovered.jwks_uri, c.discoveryUrl);
|
|
108
107
|
} catch {
|
|
109
|
-
|
|
108
|
+
ctx.logger.error(`Provider "${c.providerId}": invalid jwks_uri "${discovered.jwks_uri}" in discovery document. Provider skipped.`);
|
|
109
|
+
continue;
|
|
110
110
|
}
|
|
111
111
|
idTokenConfig = {
|
|
112
112
|
jwks: createRemoteJWKSet(jwksUrl),
|
|
@@ -115,16 +115,24 @@ const genericOAuth = (options) => {
|
|
|
115
115
|
algorithms: isOidc ? signingAlgs : void 0
|
|
116
116
|
};
|
|
117
117
|
}
|
|
118
|
-
}
|
|
119
|
-
|
|
118
|
+
}
|
|
119
|
+
if (!authorizationUrl || !tokenUrl && !c.getToken) {
|
|
120
|
+
ctx.logger.error(`Provider "${c.providerId}": discovery left no usable authorization endpoint or token exchange. Provider skipped.`);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (c.requireIdTokenVerification && !idTokenConfig) {
|
|
125
|
+
if (c.discoveryUrl) {
|
|
126
|
+
ctx.logger.error(`Provider "${c.providerId}": requires verified ID tokens, but discovery did not provide a usable issuer and jwks_uri. Provider skipped.`);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
throw new Error(`Provider "${c.providerId}": requires verified ID tokens, but discovery did not provide a usable issuer and jwks_uri.`);
|
|
120
130
|
}
|
|
121
|
-
if (c.requireIdTokenVerification && !idTokenConfig) throw new Error(`Provider "${c.providerId}": requires verified ID tokens, but discovery did not provide a usable issuer and jwks_uri.`);
|
|
122
131
|
const tokenEndpointAuth = c.tokenEndpointAuth;
|
|
123
132
|
if (c.clientSecret && isSecretlessTokenEndpointAuth(tokenEndpointAuth)) throw new Error(`Provider "${c.providerId}": tokenEndpointAuth.method "${tokenEndpointAuth?.method}" cannot be combined with clientSecret`);
|
|
124
133
|
if (!c.clientSecret && isClientSecretTokenEndpointAuth(tokenEndpointAuth)) throw new Error(`Provider "${c.providerId}": tokenEndpointAuth.method "${tokenEndpointAuth?.method}" requires clientSecret`);
|
|
125
134
|
if (!c.clientSecret && !tokenEndpointAuth && c.authentication === "basic") throw new Error(`Provider "${c.providerId}": authentication "basic" requires clientSecret`);
|
|
126
135
|
const accountSubject = c.accountSubject;
|
|
127
|
-
const accountIssuer = c.accountIssuer;
|
|
128
136
|
const provider = {
|
|
129
137
|
id: c.providerId,
|
|
130
138
|
name: c.name ?? c.providerId,
|
|
@@ -137,10 +145,6 @@ const genericOAuth = (options) => {
|
|
|
137
145
|
});
|
|
138
146
|
return isOidc ? genericProfile.sub ?? "" : genericProfile.id ?? "";
|
|
139
147
|
},
|
|
140
|
-
accountIssuer: typeof accountIssuer === "function" ? ({ tokens, profile }) => accountIssuer({
|
|
141
|
-
tokens,
|
|
142
|
-
profile
|
|
143
|
-
}) : accountIssuer ?? issuer,
|
|
144
148
|
idToken: idTokenConfig,
|
|
145
149
|
requiresIdTokenNonce: idTokenConfig !== void 0 && c.disableIdTokenNonceBinding !== true,
|
|
146
150
|
allowIdpInitiated: c.allowIdpInitiated,
|
|
@@ -27,12 +27,10 @@ function auth0(options) {
|
|
|
27
27
|
"profile",
|
|
28
28
|
"email"
|
|
29
29
|
];
|
|
30
|
-
const
|
|
31
|
-
const discoveryUrl = `https://${domain}/.well-known/openid-configuration`;
|
|
30
|
+
const domainUrl = options.domain.startsWith("http://") || options.domain.startsWith("https://") ? options.domain : `https://${options.domain}`;
|
|
32
31
|
return {
|
|
33
32
|
providerId: "auth0",
|
|
34
|
-
|
|
35
|
-
discoveryUrl,
|
|
33
|
+
discoveryUrl: `https://${new URL(domainUrl).host}/.well-known/openid-configuration`,
|
|
36
34
|
clientId: options.clientId,
|
|
37
35
|
clientSecret: options.clientSecret,
|
|
38
36
|
tokenEndpointAuth: options.tokenEndpointAuth,
|
|
@@ -22,20 +22,17 @@
|
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
function keycloak(options) {
|
|
25
|
-
const defaultScopes = [
|
|
26
|
-
"openid",
|
|
27
|
-
"profile",
|
|
28
|
-
"email"
|
|
29
|
-
];
|
|
30
|
-
const issuer = options.issuer.replace(/\/$/, "");
|
|
31
25
|
return {
|
|
32
26
|
providerId: "keycloak",
|
|
33
|
-
|
|
34
|
-
discoveryUrl: `${issuer}/.well-known/openid-configuration`,
|
|
27
|
+
discoveryUrl: `${options.issuer.replace(/\/$/, "")}/.well-known/openid-configuration`,
|
|
35
28
|
clientId: options.clientId,
|
|
36
29
|
clientSecret: options.clientSecret,
|
|
37
30
|
tokenEndpointAuth: options.tokenEndpointAuth,
|
|
38
|
-
scopes: options.scopes ??
|
|
31
|
+
scopes: options.scopes ?? [
|
|
32
|
+
"openid",
|
|
33
|
+
"profile",
|
|
34
|
+
"email"
|
|
35
|
+
],
|
|
39
36
|
redirectURI: options.redirectURI,
|
|
40
37
|
endSessionEndpoint: options.endSessionEndpoint,
|
|
41
38
|
postLogoutRedirectURI: options.postLogoutRedirectURI,
|
|
@@ -22,20 +22,17 @@
|
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
function okta(options) {
|
|
25
|
-
const defaultScopes = [
|
|
26
|
-
"openid",
|
|
27
|
-
"profile",
|
|
28
|
-
"email"
|
|
29
|
-
];
|
|
30
|
-
const issuer = options.issuer.replace(/\/$/, "");
|
|
31
25
|
return {
|
|
32
26
|
providerId: "okta",
|
|
33
|
-
|
|
34
|
-
discoveryUrl: `${issuer}/.well-known/openid-configuration`,
|
|
27
|
+
discoveryUrl: `${options.issuer.replace(/\/$/, "")}/.well-known/openid-configuration`,
|
|
35
28
|
clientId: options.clientId,
|
|
36
29
|
clientSecret: options.clientSecret,
|
|
37
30
|
tokenEndpointAuth: options.tokenEndpointAuth,
|
|
38
|
-
scopes: options.scopes ??
|
|
31
|
+
scopes: options.scopes ?? [
|
|
32
|
+
"openid",
|
|
33
|
+
"profile",
|
|
34
|
+
"email"
|
|
35
|
+
],
|
|
39
36
|
redirectURI: options.redirectURI,
|
|
40
37
|
endSessionEndpoint: options.endSessionEndpoint,
|
|
41
38
|
postLogoutRedirectURI: options.postLogoutRedirectURI,
|
|
@@ -41,7 +41,6 @@ function slack(options) {
|
|
|
41
41
|
return {
|
|
42
42
|
providerId: "slack",
|
|
43
43
|
accountSubject: ({ profile }) => profile.sub ?? "",
|
|
44
|
-
accountIssuer: "https://slack.com",
|
|
45
44
|
authorizationUrl: "https://slack.com/openid/connect/authorize",
|
|
46
45
|
tokenUrl: "https://slack.com/api/openid.connect.token",
|
|
47
46
|
userInfoUrl: "https://slack.com/api/openid.connect.userInfo",
|
|
@@ -36,15 +36,6 @@ interface GenericOAuthConfig<ID extends string = string> {
|
|
|
36
36
|
* mapping cannot redefine provider identity.
|
|
37
37
|
*/
|
|
38
38
|
accountSubject?: ((context: OAuthAccountKeyContext<GenericOAuthUserInfo>) => Awaitable<string | number>) | undefined;
|
|
39
|
-
/**
|
|
40
|
-
* Stable issuer namespace paired with the provider account ID.
|
|
41
|
-
*
|
|
42
|
-
* Discovery providers use the discovered issuer by default. Set this for
|
|
43
|
-
* providers without discovery, provider aliases that share one identity
|
|
44
|
-
* namespace, or tenant-specific issuers derived from verified provider data.
|
|
45
|
-
* The resolver must not use unverified request input.
|
|
46
|
-
*/
|
|
47
|
-
accountIssuer?: string | ((context: OAuthAccountKeyContext<GenericOAuthUserInfo>) => Awaitable<string>) | undefined;
|
|
48
39
|
/**
|
|
49
40
|
* URL to fetch OAuth 2.0 configuration.
|
|
50
41
|
* If provided, the authorization and token endpoints will be fetched from this URL.
|
|
@@ -9,6 +9,14 @@ declare module "@better-auth/core" {
|
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Checks whether a password appears in the Have I Been Pwned password corpus.
|
|
14
|
+
* Only the first five characters of its SHA-1 hash are sent to the service.
|
|
15
|
+
*
|
|
16
|
+
* @returns Whether the password has been compromised.
|
|
17
|
+
* @throws {APIError} When the password could not be checked.
|
|
18
|
+
*/
|
|
19
|
+
declare function isPasswordCompromised(password: string): Promise<boolean>;
|
|
12
20
|
interface HaveIBeenPwnedOptions {
|
|
13
21
|
/**
|
|
14
22
|
* Custom error message shown when a compromised password is detected.
|
|
@@ -52,4 +60,4 @@ declare const haveIBeenPwned: (options?: HaveIBeenPwnedOptions | undefined) => {
|
|
|
52
60
|
};
|
|
53
61
|
};
|
|
54
62
|
//#endregion
|
|
55
|
-
export { HaveIBeenPwnedOptions, haveIBeenPwned };
|
|
63
|
+
export { HaveIBeenPwnedOptions, haveIBeenPwned, isPasswordCompromised };
|
|
@@ -7,26 +7,46 @@ import { createHash } from "@better-auth/utils/hash";
|
|
|
7
7
|
import { betterFetch } from "@better-fetch/fetch";
|
|
8
8
|
//#region src/plugins/haveibeenpwned/index.ts
|
|
9
9
|
const ERROR_CODES = defineErrorCodes({ PASSWORD_COMPROMISED: "The password you entered has been compromised. Please choose a different password." });
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
function getPasswordCompromiseCount(response, hashSuffix) {
|
|
11
|
+
const matchingEntryPrefix = `${hashSuffix.toUpperCase()}:`;
|
|
12
|
+
for (const line of response.split(/\r?\n/)) {
|
|
13
|
+
if (line.slice(0, matchingEntryPrefix.length).toUpperCase() !== matchingEntryPrefix) continue;
|
|
14
|
+
const compromiseCountText = line.slice(matchingEntryPrefix.length);
|
|
15
|
+
const compromiseCount = Number(compromiseCountText);
|
|
16
|
+
if (!(Number.isSafeInteger(compromiseCount) && compromiseCount >= 0 && String(compromiseCount) === compromiseCountText)) throw new Error("Invalid password compromise count");
|
|
17
|
+
return compromiseCount;
|
|
18
|
+
}
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Checks whether a password appears in the Have I Been Pwned password corpus.
|
|
23
|
+
* Only the first five characters of its SHA-1 hash are sent to the service.
|
|
24
|
+
*
|
|
25
|
+
* @returns Whether the password has been compromised.
|
|
26
|
+
* @throws {APIError} When the password could not be checked.
|
|
27
|
+
*/
|
|
28
|
+
async function isPasswordCompromised(password) {
|
|
15
29
|
try {
|
|
30
|
+
const sha1Hash = (await createHash("SHA-1", "hex").digest(password)).toUpperCase();
|
|
31
|
+
const prefix = sha1Hash.substring(0, 5);
|
|
32
|
+
const suffix = sha1Hash.substring(5);
|
|
16
33
|
const { data, error } = await betterFetch(`https://api.pwnedpasswords.com/range/${prefix}`, { headers: {
|
|
17
34
|
"Add-Padding": "true",
|
|
18
35
|
"User-Agent": "BetterAuth Password Checker"
|
|
19
36
|
} });
|
|
20
37
|
if (error) throw new APIError("INTERNAL_SERVER_ERROR", { message: `Failed to check password. Status: ${error.status}` });
|
|
21
|
-
|
|
22
|
-
message: customMessage || ERROR_CODES.PASSWORD_COMPROMISED.message,
|
|
23
|
-
code: ERROR_CODES.PASSWORD_COMPROMISED.code
|
|
24
|
-
});
|
|
38
|
+
return getPasswordCompromiseCount(data, suffix) > 0;
|
|
25
39
|
} catch (error) {
|
|
26
40
|
if (isAPIError(error)) throw error;
|
|
27
41
|
throw new APIError("INTERNAL_SERVER_ERROR", { message: "Failed to check password. Please try again later." });
|
|
28
42
|
}
|
|
29
43
|
}
|
|
44
|
+
async function rejectCompromisedPassword(password, customMessage) {
|
|
45
|
+
if (await isPasswordCompromised(password)) throw APIError.from("BAD_REQUEST", {
|
|
46
|
+
message: customMessage || ERROR_CODES.PASSWORD_COMPROMISED.message,
|
|
47
|
+
code: ERROR_CODES.PASSWORD_COMPROMISED.code
|
|
48
|
+
});
|
|
49
|
+
}
|
|
30
50
|
const haveIBeenPwned = (options) => {
|
|
31
51
|
const paths = options?.paths || [
|
|
32
52
|
"/sign-up/email",
|
|
@@ -48,7 +68,7 @@ const haveIBeenPwned = (options) => {
|
|
|
48
68
|
if (options?.enabled === false) return originalHash(password);
|
|
49
69
|
const c = getCurrentAuthEndpointContext();
|
|
50
70
|
if (!c.path || !paths.includes(c.path)) return originalHash(password);
|
|
51
|
-
await
|
|
71
|
+
await rejectCompromisedPassword(password, options?.customPasswordCompromisedMessage);
|
|
52
72
|
return originalHash(password);
|
|
53
73
|
}
|
|
54
74
|
} } };
|
|
@@ -58,4 +78,4 @@ const haveIBeenPwned = (options) => {
|
|
|
58
78
|
};
|
|
59
79
|
};
|
|
60
80
|
//#endregion
|
|
61
|
-
export { haveIBeenPwned };
|
|
81
|
+
export { haveIBeenPwned, isPasswordCompromised };
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -31,7 +31,7 @@ import { PatreonOptions, patreon } from "./generic-oauth/providers/patreon.mjs";
|
|
|
31
31
|
import { SlackOptions, slack } from "./generic-oauth/providers/slack.mjs";
|
|
32
32
|
import { YandexOptions, yandex } from "./generic-oauth/providers/yandex.mjs";
|
|
33
33
|
import { BaseOAuthProviderOptions, genericOAuth } from "./generic-oauth/index.mjs";
|
|
34
|
-
import { HaveIBeenPwnedOptions, haveIBeenPwned } from "./haveibeenpwned/index.mjs";
|
|
34
|
+
import { HaveIBeenPwnedOptions, haveIBeenPwned, isPasswordCompromised } from "./haveibeenpwned/index.mjs";
|
|
35
35
|
import { JWKOptions, JWSAlgorithms, Jwk, JwtOptions, ResolvedSigningKey } from "./jwt/types.mjs";
|
|
36
36
|
import { getJwtToken, resolveSigningKey, signJWT } from "./jwt/sign.mjs";
|
|
37
37
|
import { createJwk, generateExportedKeyPair, toExpJWT } from "./jwt/utils.mjs";
|
|
@@ -53,7 +53,7 @@ import { OpenAPIOptions, openAPI } from "./open-api/index.mjs";
|
|
|
53
53
|
import { PhoneNumberOptions, UserWithPhoneNumber } from "./phone-number/types.mjs";
|
|
54
54
|
import { phoneNumber } from "./phone-number/index.mjs";
|
|
55
55
|
import { SIWEPluginOptions, siwe } from "./siwe/index.mjs";
|
|
56
|
-
import { LoginResult, TestCookie, TestHelpers, TestUtilsOptions } from "./test-utils/types.mjs";
|
|
56
|
+
import { LoginResult, TestAuthOptions, TestCookie, TestHelpers, TestUtilsOptions } from "./test-utils/types.mjs";
|
|
57
57
|
import { testUtils } from "./test-utils/index.mjs";
|
|
58
58
|
import { BackupCodeOptions, backupCode2fa, encodeBackupCodes, generateBackupCodes, getBackupCodes, verifyBackupCode } from "./two-factor/backup-codes/index.mjs";
|
|
59
59
|
import { OTPOptions, otp2fa } from "./two-factor/otp/index.mjs";
|
|
@@ -66,4 +66,4 @@ import { USERNAME_ERROR_CODES } from "./username/error-codes.mjs";
|
|
|
66
66
|
import { UsernameOptions, UsernamePlugin, UsernamePluginWithoutDisplayUsername, username } from "./username/index.mjs";
|
|
67
67
|
import { hasPermission } from "./organization/has-permission.mjs";
|
|
68
68
|
import { DefaultOrganizationPlugin, DynamicAccessControlEndpoints, OrganizationCreator, OrganizationEndpoints, OrganizationPlugin, TeamEndpoints, organization, parseRoles } from "./organization/organization.mjs";
|
|
69
|
-
export { AccessControl, AdminOptions, AnonymousOptions, AnonymousSession, ArrayElement, Auth0Options, AuthorizeResponse, BackupCodeOptions, BaseCaptchaOptions, BaseOAuthProviderOptions, BearerOptions, CaptchaFoxOptions, CaptchaOptions, CloudflareTurnstileOptions, CustomSessionPluginOptions, DefaultOrganizationPlugin, DeviceAuthorizationGrant, DeviceAuthorizationGrantAuthorization, DeviceAuthorizationOptions, DeviceAuthorizationPluginOptions, DeviceAuthorizationRequest, DeviceCode, DeviceCodeRedemptionAuthorization, DeviceCodeRedemptionResult, DynamicAccessControlEndpoints, MULTI_SESSION_ERROR_CODES as ERROR_CODES, EmailOTPOptions, ExactRoleStatements, FieldSchema, GenericOAuthConfig, GenericOAuthOptions, GenericOAuthUserInfo, GoogleRecaptchaOptions, GumroadOptions, HCaptchaOptions, HIDE_METADATA, HaveIBeenPwnedOptions, HubSpotOptions, InferAdminRolesFromOption, InferInvitation, InferMember, InferOptionSchema, InferOrganization, InferOrganizationRolesFromOption, InferOrganizationZodRolesFromOption, InferPluginContext, InferPluginErrorCodes, InferPluginIDs, InferTeam, Invitation, InvitationInput, InvitationStatus, JWKOptions, JWSAlgorithms, Jwk, JwtOptions, KeycloakOptions, LastLoginMethodOptions, LineOptions, LoginResult, MagicLinkOptions, Member, MemberInput, MicrosoftEntraIdOptions, MultiSessionConfig, OAUTH_POPUP_COMPLETE_SCRIPT, OAUTH_POPUP_DATA_ELEMENT_ID, OAUTH_POPUP_ERROR_CODES, OAUTH_POPUP_MESSAGE_TYPE, OAUTH_POPUP_SCRIPT_CSP_HASH, OAuthPopupData, OAuthPopupMessage, OAuthProxyOptions, OTPOptions, OktaOptions, OneTapOptions, OneTimeTokenOptions, OpenAPIModelSchema, OpenAPIOptions, OpenAPIParameter, OpenAPISchema, Organization, OrganizationCreator, OrganizationEndpoints, OrganizationInput, OrganizationOptions, OrganizationPlugin, OrganizationRole, OrganizationSchema, POPUP_MARKER_COOKIE, Path, PatreonOptions, PhoneNumberOptions, Provider, ResolvedSigningKey, Role, RoleAuthorizeRequest, RoleInput, RoleStatements, SIWEPluginOptions, SessionWithImpersonatedBy, SlackOptions, Statements, SubArray, Subset, TOTPOptions, TWO_FACTOR_ERROR_CODES, Team, TeamEndpoints, TeamInput, TeamMember, TeamMemberInput, TestCookie, TestHelpers, TestUtilsOptions, TimeString, TwoFactorOptions, TwoFactorProvider, TwoFactorTable, USERNAME_ERROR_CODES, UserWithAnonymous, UserWithPhoneNumber, UserWithRole, UserWithTwoFactor, UsernameOptions, UsernamePlugin, UsernamePluginWithoutDisplayUsername, YandexOptions, admin, anonymous, auth0, backupCode2fa, bearer, captcha, createAccessControl, createJwk, customSession, defaultRolesSchema, deviceAuthorization, deviceAuthorizationOptionsSchema, emailOTP, encodeBackupCodes, generateBackupCodes, generateExportedKeyPair, generator, genericOAuth, getBackupCodes, getJwtToken, getOrgAdapter, gumroad, hasPermission, haveIBeenPwned, hubspot, invitationSchema, invitationStatus, jwt, keycloak, lastLoginMethod, line, magicLink, memberSchema, microsoftEntraId, ms, multiSession, oAuthProxy, oauthPopup, okta, oneTap, oneTimeToken, openAPI, organization, organizationRoleSchema, organizationSchema, otp2fa, parseRoles, patreon, phoneNumber, redeemDeviceCode, resolveSigningKey, role, roleSchema, sec, signJWT, siwe, slack, teamMemberSchema, teamSchema, testUtils, toExpJWT, totp2fa, twoFactor, twoFactorClient, username, verifyBackupCode, verifyJWT, yandex };
|
|
69
|
+
export { AccessControl, AdminOptions, AnonymousOptions, AnonymousSession, ArrayElement, Auth0Options, AuthorizeResponse, BackupCodeOptions, BaseCaptchaOptions, BaseOAuthProviderOptions, BearerOptions, CaptchaFoxOptions, CaptchaOptions, CloudflareTurnstileOptions, CustomSessionPluginOptions, DefaultOrganizationPlugin, DeviceAuthorizationGrant, DeviceAuthorizationGrantAuthorization, DeviceAuthorizationOptions, DeviceAuthorizationPluginOptions, DeviceAuthorizationRequest, DeviceCode, DeviceCodeRedemptionAuthorization, DeviceCodeRedemptionResult, DynamicAccessControlEndpoints, MULTI_SESSION_ERROR_CODES as ERROR_CODES, EmailOTPOptions, ExactRoleStatements, FieldSchema, GenericOAuthConfig, GenericOAuthOptions, GenericOAuthUserInfo, GoogleRecaptchaOptions, GumroadOptions, HCaptchaOptions, HIDE_METADATA, HaveIBeenPwnedOptions, HubSpotOptions, InferAdminRolesFromOption, InferInvitation, InferMember, InferOptionSchema, InferOrganization, InferOrganizationRolesFromOption, InferOrganizationZodRolesFromOption, InferPluginContext, InferPluginErrorCodes, InferPluginIDs, InferTeam, Invitation, InvitationInput, InvitationStatus, JWKOptions, JWSAlgorithms, Jwk, JwtOptions, KeycloakOptions, LastLoginMethodOptions, LineOptions, LoginResult, MagicLinkOptions, Member, MemberInput, MicrosoftEntraIdOptions, MultiSessionConfig, OAUTH_POPUP_COMPLETE_SCRIPT, OAUTH_POPUP_DATA_ELEMENT_ID, OAUTH_POPUP_ERROR_CODES, OAUTH_POPUP_MESSAGE_TYPE, OAUTH_POPUP_SCRIPT_CSP_HASH, OAuthPopupData, OAuthPopupMessage, OAuthProxyOptions, OTPOptions, OktaOptions, OneTapOptions, OneTimeTokenOptions, OpenAPIModelSchema, OpenAPIOptions, OpenAPIParameter, OpenAPISchema, Organization, OrganizationCreator, OrganizationEndpoints, OrganizationInput, OrganizationOptions, OrganizationPlugin, OrganizationRole, OrganizationSchema, POPUP_MARKER_COOKIE, Path, PatreonOptions, PhoneNumberOptions, Provider, ResolvedSigningKey, Role, RoleAuthorizeRequest, RoleInput, RoleStatements, SIWEPluginOptions, SessionWithImpersonatedBy, SlackOptions, Statements, SubArray, Subset, TOTPOptions, TWO_FACTOR_ERROR_CODES, Team, TeamEndpoints, TeamInput, TeamMember, TeamMemberInput, TestAuthOptions, TestCookie, TestHelpers, TestUtilsOptions, TimeString, TwoFactorOptions, TwoFactorProvider, TwoFactorTable, USERNAME_ERROR_CODES, UserWithAnonymous, UserWithPhoneNumber, UserWithRole, UserWithTwoFactor, UsernameOptions, UsernamePlugin, UsernamePluginWithoutDisplayUsername, YandexOptions, admin, anonymous, auth0, backupCode2fa, bearer, captcha, createAccessControl, createJwk, customSession, defaultRolesSchema, deviceAuthorization, deviceAuthorizationOptionsSchema, emailOTP, encodeBackupCodes, generateBackupCodes, generateExportedKeyPair, generator, genericOAuth, getBackupCodes, getJwtToken, getOrgAdapter, gumroad, hasPermission, haveIBeenPwned, hubspot, invitationSchema, invitationStatus, isPasswordCompromised, jwt, keycloak, lastLoginMethod, line, magicLink, memberSchema, microsoftEntraId, ms, multiSession, oAuthProxy, oauthPopup, okta, oneTap, oneTimeToken, openAPI, organization, organizationRoleSchema, organizationSchema, otp2fa, parseRoles, patreon, phoneNumber, redeemDeviceCode, resolveSigningKey, role, roleSchema, sec, signJWT, siwe, slack, teamMemberSchema, teamSchema, testUtils, toExpJWT, totp2fa, twoFactor, twoFactorClient, username, verifyBackupCode, verifyJWT, yandex };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -25,7 +25,7 @@ import { patreon } from "./generic-oauth/providers/patreon.mjs";
|
|
|
25
25
|
import { slack } from "./generic-oauth/providers/slack.mjs";
|
|
26
26
|
import { yandex } from "./generic-oauth/providers/yandex.mjs";
|
|
27
27
|
import { genericOAuth } from "./generic-oauth/index.mjs";
|
|
28
|
-
import { haveIBeenPwned } from "./haveibeenpwned/index.mjs";
|
|
28
|
+
import { haveIBeenPwned, isPasswordCompromised } from "./haveibeenpwned/index.mjs";
|
|
29
29
|
import { createJwk, generateExportedKeyPair, toExpJWT } from "./jwt/utils.mjs";
|
|
30
30
|
import { getJwtToken, resolveSigningKey, signJWT } from "./jwt/sign.mjs";
|
|
31
31
|
import { verifyJWT } from "./jwt/verify.mjs";
|
|
@@ -46,4 +46,4 @@ import { siwe } from "./siwe/index.mjs";
|
|
|
46
46
|
import { testUtils } from "./test-utils/index.mjs";
|
|
47
47
|
import { twoFactor } from "./two-factor/index.mjs";
|
|
48
48
|
import { username } from "./username/index.mjs";
|
|
49
|
-
export { MULTI_SESSION_ERROR_CODES as ERROR_CODES, HIDE_METADATA, OAUTH_POPUP_COMPLETE_SCRIPT, OAUTH_POPUP_DATA_ELEMENT_ID, OAUTH_POPUP_ERROR_CODES, OAUTH_POPUP_MESSAGE_TYPE, OAUTH_POPUP_SCRIPT_CSP_HASH, POPUP_MARKER_COOKIE, TWO_FACTOR_ERROR_CODES, USERNAME_ERROR_CODES, admin, anonymous, auth0, bearer, captcha, createAccessControl, createJwk, customSession, deviceAuthorization, deviceAuthorizationOptionsSchema, emailOTP, generateExportedKeyPair, genericOAuth, getJwtToken, getOrgAdapter, gumroad, hasPermission, haveIBeenPwned, hubspot, jwt, keycloak, lastLoginMethod, line, magicLink, microsoftEntraId, multiSession, oAuthProxy, oauthPopup, okta, oneTap, oneTimeToken, openAPI, organization, parseRoles, patreon, phoneNumber, redeemDeviceCode, resolveSigningKey, role, signJWT, siwe, slack, testUtils, toExpJWT, twoFactor, twoFactorClient, username, verifyJWT, yandex };
|
|
49
|
+
export { MULTI_SESSION_ERROR_CODES as ERROR_CODES, HIDE_METADATA, OAUTH_POPUP_COMPLETE_SCRIPT, OAUTH_POPUP_DATA_ELEMENT_ID, OAUTH_POPUP_ERROR_CODES, OAUTH_POPUP_MESSAGE_TYPE, OAUTH_POPUP_SCRIPT_CSP_HASH, POPUP_MARKER_COOKIE, TWO_FACTOR_ERROR_CODES, USERNAME_ERROR_CODES, admin, anonymous, auth0, bearer, captcha, createAccessControl, createJwk, customSession, deviceAuthorization, deviceAuthorizationOptionsSchema, emailOTP, generateExportedKeyPair, genericOAuth, getJwtToken, getOrgAdapter, gumroad, hasPermission, haveIBeenPwned, hubspot, isPasswordCompromised, jwt, keycloak, lastLoginMethod, line, magicLink, microsoftEntraId, multiSession, oAuthProxy, oauthPopup, okta, oneTap, oneTimeToken, openAPI, organization, parseRoles, patreon, phoneNumber, redeemDeviceCode, resolveSigningKey, role, signJWT, siwe, slack, testUtils, toExpJWT, twoFactor, twoFactorClient, username, verifyJWT, yandex };
|
|
@@ -13,6 +13,7 @@ const lastLoginMethod = (userConfig) => {
|
|
|
13
13
|
if (path.includes("siwe")) return "siwe";
|
|
14
14
|
if (path.includes("/passkey/verify-authentication")) return "passkey";
|
|
15
15
|
if (path.startsWith("/magic-link/verify")) return "magic-link";
|
|
16
|
+
if (path === "/sign-in/email-otp") return "email-otp";
|
|
16
17
|
return null;
|
|
17
18
|
};
|
|
18
19
|
const getResolveContext = (ctx) => {
|
|
@@ -58,6 +58,10 @@ declare const oAuthProxy: <O extends OAuthProxyOptions>(opts?: O) => {
|
|
|
58
58
|
version: string;
|
|
59
59
|
options: NoInfer<O>;
|
|
60
60
|
endpoints: {
|
|
61
|
+
/**
|
|
62
|
+
* @deprecated OAuth proxy callbacks now use `/callback/:id/oauth-proxy`.
|
|
63
|
+
* This endpoint will be removed in the next minor release.
|
|
64
|
+
*/
|
|
61
65
|
oAuthProxy: _$better_call0.StrictEndpoint<"/oauth-proxy-callback", {
|
|
62
66
|
method: "GET";
|
|
63
67
|
operationId: string;
|
|
@@ -69,6 +73,7 @@ declare const oAuthProxy: <O extends OAuthProxyOptions>(opts?: O) => {
|
|
|
69
73
|
metadata: {
|
|
70
74
|
openapi: {
|
|
71
75
|
operationId: string;
|
|
76
|
+
deprecated: boolean;
|
|
72
77
|
description: string;
|
|
73
78
|
parameters: ({
|
|
74
79
|
in: "query";
|
|
@@ -97,6 +102,18 @@ declare const oAuthProxy: <O extends OAuthProxyOptions>(opts?: O) => {
|
|
|
97
102
|
};
|
|
98
103
|
};
|
|
99
104
|
}, never>;
|
|
105
|
+
oAuthProxyCompletion: _$better_call0.StrictEndpoint<"/callback/:id/oauth-proxy", {
|
|
106
|
+
method: "GET";
|
|
107
|
+
operationId: string;
|
|
108
|
+
query: z.ZodObject<{
|
|
109
|
+
callbackURL: z.ZodString;
|
|
110
|
+
profile: z.ZodOptional<z.ZodString>;
|
|
111
|
+
}, z.core.$strip>;
|
|
112
|
+
use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<void>>[];
|
|
113
|
+
metadata: {
|
|
114
|
+
scope: "http";
|
|
115
|
+
};
|
|
116
|
+
}, never>;
|
|
100
117
|
};
|
|
101
118
|
hooks: {
|
|
102
119
|
before: {
|