refactor: account linking

This commit is contained in:
Bereket Engida
2024-09-28 00:46:04 +03:00
parent ab851ad3cf
commit f4e1d96662
4 changed files with 18 additions and 34 deletions

View File

@@ -92,4 +92,10 @@ export const auth = betterAuth({
clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
},
},
account: {
accountLinking: {
trustedProviders: ["google", "github"],
requireEmailVerified: true,
},
},
});

View File

@@ -77,19 +77,18 @@ The account table stores the authentication data of the user. The account table
Account linking allows users to link multiple authentication methods to the same account. This is useful when users want to sign in using different methods.
By default better auth doesn't allow account linking. To enable account linking, you must pass `enabled: true` in `account` options when initializing better auth.
By default better auth allows account linking for all providers. You can disable account linking by setting `accountLinking.enabled` to `false`.
```ts
const auth = new BetterAuth({
account: {
accountLinking: {
enabled: true,
enabled: false,
}
},
});
```
You can also specify, the list of providers that should be trusted. Trusted providers are providers that can be linked to the account without verifying the user's email.
You can also specify, the list of providers that should be trusted. When a user signs in using a trusted provider, if the provider returns the `emailVerified` field in the user data, the account will be linked to the user.
```ts
const auth = new BetterAuth({
@@ -101,20 +100,3 @@ const auth = new BetterAuth({
},
});
```
By defualt the provider needs to returned `emailVerified` field in the user data to link the account. You can change this behavior by setting `requireEmailVerified` to `false`.
<Callout type="warn">
We strongly recommend you only link accounts that have verified emails to prevent account hijacking.
</Callout>
```ts
const auth = new BetterAuth({
account: {
accountLinking: {
enabled: true,
requireEmailVerified: false,
}
},
});
```

View File

@@ -97,21 +97,24 @@ export const callbackOAuth = createAuthEndpoint(
c.context.options.account?.accountLinking?.trustedProviders;
const isTrustedProvider = trustedProviders
? trustedProviders.includes(provider.id as "apple")
: false;
if (!hasBeenLinked && (!user.emailVerified || !isTrustedProvider)) {
: true;
const shouldLink =
!hasBeenLinked && user.emailVerified && isTrustedProvider;
if (!shouldLink) {
let url: URL;
try {
url = new URL(currentURL || callbackURL);
url.searchParams.set("error", "user_already_exists");
url.searchParams.set("error", "account_not_linked");
} catch (e) {
throw c.redirect(
`${c.context.baseURL}/error?error=user_already_exists`,
`${c.context.baseURL}/error?error=account_not_linked`,
);
}
throw c.redirect(url.toString());
}
if (!hasBeenLinked && user.emailVerified) {
if (shouldLink) {
try {
await c.context.internalAdapter.linkAccount({
providerId: provider.id,

View File

@@ -167,16 +167,9 @@ export interface BetterAuthOptions {
*/
enabled?: boolean;
/**
* List of trusted providers. If the
* provider is not in this list
* `emailVerified` field is ignored.
* List of trusted providers
*/
trustedProviders?: Array<OAuthProviderList[number] | "email-password">;
/**
* Require email verified field
* to be true to link the account
*/
requireEmailVerified?: boolean;
};
};
/**