Skip to content

Conversation

@santiagomera
Copy link
Contributor

Summary

Fix #199

This PR adds flexible registration control to the PasswordProvider, enabling scenarios where sign-ups are restricted or completely disabled while supporting admin-created users through external system.

New Configuration Options

allowRegistration - Controls whether new user registration is allowed:

  • boolean: true (default) allows user registration, false disables user registration
  • function: (email: string) => boolean | Promise<boolean> for custom validation logic (e.g., domain restrictions)

userExists - Callback to check if a user exists in an external system:

  • (email: string) => boolean | Promise<boolean>
  • Used during password reset flow to validate existing users when registration is disabled
  • Only invoked when allowRegistration === false

Implementation Details

Registration Flow Changes

  • When allowRegistration: false: Registration routes redirect to login page
  • When allowRegistration: function: Function validates each registration attempt on form submission
  • UI updates: Registration links conditionally hidden when disabled

Password Reset Flow for Admin-Created Users

First-time log in when registration is disabled is handled with the existing password reset flow (new users need to reset their password before being able to log in).
At the password update step, if the user if not found in Storage and the user exists in external system, it is created in Storage and the regular reset logic continues.

Examples

Admin-Created User First Login

  1. Admin creates user "[email protected]" in external system (no OpenAuth storage entry)
  2. User visits login page, sees "First time logging in? Reset your password" link
  3. User clicks reset link, enters email, receives verification code
  4. User enters code, proceeds to password setting screen
  5. When user sets password:
    • OpenAuth checks storage → user not found
    • OpenAuth calls userExists("[email protected]") → returns true
    • OpenAuth creates storage entry for user
    • User completes password setup successfully
  6. Future logins work normally

Domain-Restricted Registration

PasswordProvider(PasswordUI({
  allowRegistration: (email) => {
    return email.endsWith("@company.com") || email.endsWith("@contractor.com")
  },
  sendCode: sendEmailCode
}))

Disabled Registration with External Users

PasswordProvider(PasswordUI({
  allowRegistration: false,
  userExists: async (email) => {
    return await corporateDirectory.userExists(email)
  },
  sendCode: sendEmailCode
}))

Breaking Changes

There shouldn't be.

@changeset-bot
Copy link

changeset-bot bot commented Jun 9, 2025

⚠️ No Changeset found

Latest commit: 80169d9

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@santiagomera
Copy link
Contributor Author

Added access control to the CodeProvider since it's just a similar but simpler case than the PasswordProvider.

@santiagomera santiagomera changed the title Add registration control to PasswordProvider Add registration/access control to PasswordProvider and CodeProvider Jun 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a Flag to Disable User Registration in PasswordUI and PasswordProvider

1 participant