mirror of
https://github.com/better-auth/better-auth.git
synced 2026-10-25 10:13:54 -05:00
feat(organization): add option for requiring email verificaiton (#3785)
* feat(organization): add option for requiring email verificaiton * add rejection * docs: add docs
This commit is contained in:
committed by
Bereket Engida
parent
24540ed727
commit
f88e4b8dfb
@@ -584,6 +584,25 @@ type acceptInvitation = {
|
||||
```
|
||||
</APIMethod>
|
||||
|
||||
#### Email Verification Requirement
|
||||
|
||||
If the `requireEmailVerificationOnInvitation` option is enabled in your organization configuration, users must verify their email address before they can accept invitations. This adds an extra security layer to ensure that only verified users can join your organization.
|
||||
|
||||
```ts title="auth.ts"
|
||||
import { betterAuth } from "better-auth"
|
||||
import { organization } from "better-auth/plugins"
|
||||
|
||||
export const auth = betterAuth({
|
||||
plugins: [
|
||||
organization({
|
||||
requireEmailVerificationOnInvitation: true, // [!code highlight]
|
||||
async sendInvitationEmail(data) {
|
||||
// ... your email sending logic
|
||||
}
|
||||
})
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
### Cancel Invitation
|
||||
|
||||
@@ -617,6 +636,10 @@ type rejectInvitation = {
|
||||
```
|
||||
</APIMethod>
|
||||
|
||||
<Callout type="info">
|
||||
Like accepting invitations, rejecting invitations also requires email verification when the `requireEmailVerificationOnInvitation` option is enabled. Users with unverified emails will receive an error when attempting to reject invitations.
|
||||
</Callout>
|
||||
|
||||
### Get Invitation
|
||||
|
||||
To get an invitation you can use the `organization.getInvitation` function provided by the client. You need to provide the invitation id as a query parameter.
|
||||
@@ -1759,3 +1782,5 @@ await client.organization.create({
|
||||
**cancelPendingInvitationsOnReInvite**: `boolean` - Whether to cancel pending invitations if the user is already invited to the organization. By default, it's `false`.
|
||||
|
||||
**invitationLimit**: `number` | `((user: User) => Promise<boolean> | boolean)` - The maximum number of invitations allowed for a user. By default, it's `100`. You can set it to any number you want or a function that returns a boolean.
|
||||
|
||||
**requireEmailVerificationOnInvitation**: `boolean` - Whether to require email verification before accepting or rejecting invitations. By default, it's `false`. When enabled, users must have verified their email address before they can accept or reject organization invitations.
|
||||
|
||||
@@ -31,6 +31,8 @@ export const ORGANIZATION_ERROR_CODES = {
|
||||
INVITATION_NOT_FOUND: "Invitation not found",
|
||||
YOU_ARE_NOT_THE_RECIPIENT_OF_THE_INVITATION:
|
||||
"You are not the recipient of the invitation",
|
||||
EMAIL_VERIFICATION_REQUIRED_BEFORE_ACCEPTING_OR_REJECTING_INVITATION:
|
||||
"Email verification required before accepting or rejecting invitation",
|
||||
YOU_ARE_NOT_ALLOWED_TO_CANCEL_THIS_INVITATION:
|
||||
"You are not allowed to cancel this invitation",
|
||||
INVITER_IS_NO_LONGER_A_MEMBER_OF_THE_ORGANIZATION:
|
||||
|
||||
@@ -419,6 +419,16 @@ export const acceptInvitation = <O extends OrganizationOptions>(options: O) =>
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
ctx.context.orgOptions.requireEmailVerificationOnInvitation &&
|
||||
!session.user.emailVerified
|
||||
) {
|
||||
throw new APIError("FORBIDDEN", {
|
||||
message:
|
||||
ORGANIZATION_ERROR_CODES.EMAIL_VERIFICATION_REQUIRED_BEFORE_ACCEPTING_OR_REJECTING_INVITATION,
|
||||
});
|
||||
}
|
||||
|
||||
const membershipLimit = ctx.context.orgOptions?.membershipLimit || 100;
|
||||
const membersCount = await adapter.countMembers({
|
||||
organizationId: invitation.organizationId,
|
||||
@@ -581,6 +591,16 @@ export const rejectInvitation = <O extends OrganizationOptions>(options: O) =>
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
ctx.context.orgOptions.requireEmailVerificationOnInvitation &&
|
||||
!session.user.emailVerified
|
||||
) {
|
||||
throw new APIError("FORBIDDEN", {
|
||||
message:
|
||||
ORGANIZATION_ERROR_CODES.EMAIL_VERIFICATION_REQUIRED_BEFORE_ACCEPTING_OR_REJECTING_INVITATION,
|
||||
});
|
||||
}
|
||||
|
||||
const rejectedI = await adapter.updateInvitation({
|
||||
invitationId: ctx.body.invitationId,
|
||||
status: "rejected",
|
||||
|
||||
@@ -157,6 +157,12 @@ export interface OrganizationOptions {
|
||||
* @default false
|
||||
*/
|
||||
cancelPendingInvitationsOnReInvite?: boolean;
|
||||
/**
|
||||
* Require email verification on accepting or rejecting an invitation
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
requireEmailVerificationOnInvitation?: boolean;
|
||||
/**
|
||||
* Send an email with the
|
||||
* invitation link to the user.
|
||||
|
||||
Reference in New Issue
Block a user