Convex Auth

repository·main·Indexed 41 days ago

https://github.com/get-convex/convex-auth

Authentication for Convex applications, supporting OAuth2 and OIDC flows through providers such as Email, Password, and Phone. The package @convex-dev/auth (version 0.0.95) provides tools for managing user sessions, account linking based on email verification trust models, and React hooks like useAuthActions for signing out users.

Tokens
38.2K
Snippets
116
Records
154
Agent score
52%

What's inside Convex Auth

  1. Overview of OAuth2 and OIDC flow implementation

    main

    The code in src/server/oauth is designed to handle OAuth2 and OpenID Connect (OIDC) flows. It is adapted from the @auth/core package. While it maintains a similar structure to @auth/core, certain types and functions have been copied over and modified because the original package's implementation relied on internal members.

    To identify logic that differs from the original @auth/core implementation, look for comments marked with ConvexAuth: within the source code.

  2. Overview of Convex Auth

    main

    Convex Auth is a library designed to implement authentication directly within your Convex backend. This architecture allows you to manage user authentication without requiring a separate authentication service or a dedicated hosting server.

    It is compatible with various application architectures, including:

    • React SPAs served from a CDN
    • Full-stack Next.js applications
    • React Native mobile applications

    Note: Convex Auth is currently in beta.

  3. Supported authentication methods in Convex Auth

    main

    Convex Auth supports three primary authentication patterns:

    1. Magic Links & OTPs: Users sign in by receiving a link or a one-time password (OTP) via email.
    2. OAuth: Integration with third-party providers such as GitHub, Google, and Apple.
    3. Passwords: Traditional email/password authentication, which includes support for password reset flows and optional email verification.
  4. Understand Convex Auth token storage and security

    main

    Convex Auth provides two tokens to the client JavaScript to facilitate authentication over WebSockets and maintain sessions:

    1. Refresh Token: Used to obtain new access tokens. It is used only once; attempting to use an "old" refresh token triggers refresh token reuse detection, which invalidates the entire session.
    2. JWT Access Token: Sent over the WebSocket connection to the backend.

    Storage Mechanisms

    By default, both tokens are stored in localStorage to allow immediate authentication across page loads. This is necessary because:

    • Web apps often treat the Convex backend as a third-party server (making cookies subject to browser blocking).
    • Browsers lack support for server-only cookies in WebSocket connections.
    • React Native/Expo environments have limited cookie support.

    To use a different storage mechanism, provide the storage prop to the ConvexAuthProvider component.

    // Example of customizing storage via ConvexAuthProvider
    <ConvexAuthProvider storage={myCustomStorage}>
      <App />
    </ConvexAuthProvider>
  5. Prevent Session Fixation attacks in Magic Link flows

    main

    Magic links are vulnerable to session fixation where a malicious actor generates a link and tricks a victim into clicking it, signing the victim into an account controlled by the attacker.

    To mitigate this, implement an interstitial page:

    1. Create a custom email provider via the Email interface.
    2. Customize the magic link URL to include both the token and the email (e.g., https://myapp.com/email-sign-in?token=${token}&email=${identifier}).
    3. On the target path, render a page that displays the email address and requires a user interaction (like a button click) to proceed.
    4. When the user clicks the button, call the signIn function with both the code (token) and email parameters.

    Because providers created via the Email interface automatically verify that the provided email matches the one used to issue the token, this prevents attackers from spoofing the identity.

  6. How One-Time Password (OTP) authentication works

    main

    OTP authentication in Convex Auth is a two-step process:

    1. Request: The user provides an identifier (email address or phone number). The system generates a code and sends it via a configured provider.
    2. Verification: The user enters the code into your application. Your Convex backend tracks the issued code to ensure secure verification and handle expiration.

    You can configure your message templates to send an OTP and a magic link simultaneously.

  7. Compare OAuth, Magic Links, and Passwords

    main

    Deciding on an authentication method involves balancing Developer Experience (DX), User Experience (UX), and Security. Use the following comparison to guide your choice:

    OAuth

    • DX: Requires configuring an OAuth provider (can be complex and may require domain control), but the provider handles security features like MFA, SSO, and password management.
    • UX: Very user-friendly as users are often already signed in to providers, but requires users to have an account with the chosen provider.
    • Security: Relies on the robust security infrastructure of the OAuth provider.
    • DX: Requires an email provider/server and domain control. Magic links are the simplest to implement. Note: React Native support for magic links is currently not documented.
    • UX: No passwords to remember, but requires email access for every new session/device. OTPs are better for devices where email access is difficult compared to magic links.
    • Security: Both are susceptible to phishing attacks (link redirection or code interception).

    Passwords

    • DX: Most complex implementation. Production-ready setups require an email provider for password recovery.
    • UX: Good for users with password managers, but difficult for those who must remember passwords.
    • Security: High risk of password reuse and requires strict handling to prevent accidental leakage (e.g., in logs).
  8. Compare Convex Auth with other authentication solutions

    main

    When deciding whether to use Convex Auth, consider the following comparisons:

    vs NextAuth (Auth.js)

    • Server Requirements: NextAuth requires a Next.js (or similar) server. Convex Auth works with or without a Next.js server and can be used directly from an SPA hosted on a CDN.
    • State Syncing: Convex Auth runs directly on your Convex backend, avoiding the complexity of syncing state between two separate servers.
    • Built-in Methods: Convex Auth includes built-in support for OTP and email+password methods.

    vs Clerk or Auth0

    • Service Overhead: Convex Auth doesn't require signing up for an external service (except for your chosen Email or OAuth providers).
    • Data Ownership: Convex Auth stores all user data directly in your Convex database, eliminating the need to sync state from an external database.
    • Domain Requirements: Convex Auth does not require you to own a top-level domain (e.g., example.com), though your email or OAuth providers might.
    • Note: Clerk and Auth0 are still recommended for highly feature-rich authentication needs.

    vs Firebase Auth or Supabase Auth

    • Data Storage: Firebase and Supabase store user data in their own databases. Convex Auth stores user data directly in your Convex database.
    • Feature Set: Convex Auth provides basic functionality. For advanced features like SSO or MFA, Clerk or Auth0 are recommended.

    vs Lucia

    • Lucia is designed for traditional servers hosting websites. Previous Convex+Lucia integrations are now deprecated.

    Framework Support

    • Currently, Convex Auth client libraries are only available for React. Support for other frameworks is not yet available but is open to community contributions.
  9. How Convex Auth manages users and sessions

    main

    Convex Auth automatically manages two primary tables in your database:

    1. users: Stores user documents created upon initial sign-up.
    2. authSessions: Stores session documents created upon sign-in. A session document exists until the session expires or the user signs out. One user can have multiple active sessions simultaneously.

    You can retrieve these documents using ctx.db.get() with the IDs obtained from server-side helper functions.

  10. How account linking works in Convex Auth

    main

    Account linking determines if multiple authentication methods (e.g., GitHub and Email) point to the same user document. Convex Auth uses a trust model based on email verification:

    1. Trusted Methods: Email-based methods (magic links, OTPs) and most OAuth providers are considered trusted. If a trusted method is used with an existing verified email, the account is linked to the existing user.
    2. Untrusted Methods: Password-based accounts without required email verification are untrusted. Using an untrusted method will create a new, separate user document even if the email matches an existing user.

    Recommendation: To prevent duplicate user accounts for the same email, either use only trusted methods or use only a single untrusted method.