Skip to content

Restricted access through invite-only sign ups

Build applications that enable organization owners to invite users to join their organization. Scalekit takes care of sending the invite emails, verifying their email addresses, and creating the user accounts end to end.

Invite-only signup is ideal for the following scenarios:

  • Closed beta applications: You want to control who can access your application during the beta phase.
  • Enterprise applications: Organization admins need to invite team members to join their workspace.
  • B2B SaaS platforms: You want to restrict access to invited users only
  • Exclusive communities: Applications that require invitation-based membership.

Scalekit helps you implement invite-only signup flows while handling the complexity of user management and authentication.

Set up invite-only signup page with Scalekit

Section titled “Set up invite-only signup page with Scalekit”

You can implement invite-only signup by configuring Scalekit to disable public signups and using the invitation flow. This ensures that only invited users can create accounts.

  1. Configure your application for invite-only access

    Section titled “Configure your application for invite-only access”

    npm install @scalekit-sdk/node

    Copy your API credentials from the Scalekit dashboard’s API Config section and set them as environment variables.

    Terminal window
    SCALEKIT_ENVIRONMENT_URL='<YOUR_ENVIRONMENT_URL>'
    SCALEKIT_CLIENT_ID='<ENVIRONMENT_CLIENT_ID>'
    SCALEKIT_CLIENT_SECRET='<ENVIRONMENT_CLIENT_SECRET>'

    Create a new Scalekit client instance after initializing the environment variables.

    utils/auth.js
    import { Scalekit } from '@scalekit-sdk/node';
    export let scalekit = new Scalekit(
    process.env.SCALEKIT_ENVIRONMENT_URL,
    process.env.SCALEKIT_CLIENT_ID,
    process.env.SCALEKIT_CLIENT_SECRET
    );
  2. Generate the authorization URL by passing a registered callback URL and scopes to the Scalekit SDK. Note that we don’t include the prompt: 'create' parameter since public signup is disabled.

    Express.js
    const redirectUri = 'http://localhost:3000/api/callback';
    const options = {
    scopes: ['openid', 'profile', 'email', 'offline_access'],
    };
    const authorizationUrl = scalekit.getAuthorizationUrl(redirectUri, options);
    res.redirect(authorizationUrl);

    This will redirect the user to Scalekit’s managed sign-in page without signup options.

  3. Retrieve user profile after authentication

    Section titled “Retrieve user profile after authentication”

    Scalekit triggers a callback to your registered callback URL with an authorization code. Exchange the code to get the user’s profile information.

    import scalekit from '@/utils/auth.js'
    const redirectUri = 'http://localhost:3000/api/callback';
    // Get the authorization code from the scalekit initiated callback
    app.get('/api/callback', async (req, res) => {
    const { code, error, error_description } = req.query;
    if (error) {
    return res.status(401).json({ error, error_description });
    }
    try {
    // Exchange the authorization code for a user profile
    const authResult = await scalekit.authenticateWithCode(
    code, redirectUri
    );
    const { user } = authResult;
    // "user" object contains the user's profile information
    // Next step: Create a session and log in the user
    5 collapsed lines
    res.redirect('/dashboard/profile');
    } catch (err) {
    console.error('Error exchanging code:', err);
    res.status(500).json({ error: 'Failed to authenticate user' });
    }
    });

    The authenticateWithCode method returns an object containing the user’s profile information (user object) and idToken (JWT).

    {
    user: {
    email: "john.doe@example.com",
    emailVerified: true,
    givenName: "John",
    name: "John Doe",
    id: "usr_74599896446906854"
    },
    idToken: "eyJhbGciO..",
    accessToken: "eyJhbGciOi..",
    refreshToken: "rt_8f7d6e5c4b3a2d1e0f9g8h7i6j..",
    expiresIn: 299
    }

    You can decode the idToken to access user information like email, name, and profile verification status directly from the token claims.

With these configurations, your B2B application now has a sign-in page but no public signup option, ensuring that only invited users can access your application. After successful authentication, you can proceed to create a session.

For applications where you want to build custom invitation flows in your own UI, Scalekit provides APIs to programmatically invite users. This is ideal when organization admins or workspace owners need to invite team members directly from your application’s dashboard.

Common use cases include:

  • Admin dashboards: Organization admins can invite users from a settings or team management page.
  • Bulk invitations: Import and invite multiple users at once from CSV files or directory systems.
  • Custom workflows: Implement approval processes or conditional invitations based on business logic.
  • Integration with existing systems: Connect invitation flows with your CRM, HR systems, or user directories.
  1. To invite a user to an organization, create a user membership with their email address and the target organization ID. Scalekit handles sending the invitation email and managing the signup process.

    const newUser = await scalekit.user.createUserAndMembership('org_xxxxxxxxxxxx', {
    email: "user@example.com",
    externalId: "crm-user-87425",
    userProfile: {
    firstName: "John",
    lastName: "Doe"
    },
    metadata: {
    plan: "free",
    department: "Engineering"
    },
    sendInvitationEmail: true
    });

    Key parameters:

    • email: The email address of the user to invite (required)
    • organization_id: The ID of the organization they’re joining (required)
    • sendActivationEmail: Set to true to automatically send invitation emails (recommended)
    • roles: Optional array of roles to assign to the invited user
    • metadata: Optional custom data to associate with the membership
  2. When a user is successfully invited, Scalekit returns a user object with membership details. The membership status will be INVITED until the user accepts the invitation.

    Example invitation response
    {
    "user": {
    "id": "usr_01HTR0ABCXYZ",
    "environmentId": "env_01HTQZ99MMNZ",
    "createTime": "2025-06-19T15:41:22Z",
    "updateTime": "2025-06-19T15:41:22Z",
    "email": "user@example.com",
    "externalId": "crm-user-87425",
    "memberships": [
    {
    "organizationId": "org_xxxxxxxxxxxx",
    "joinTime": "2025-06-19T15:41:22Z",
    "membershipStatus": "ACTIVE",
    "roles": [
    {
    "id": "role_admin",
    "name": "admin"
    }
    ],
    "primaryIdentityProvider": "IDENTITY_PROVIDER_UNSPECIFIED",
    "metadata": {
    "plan": "free",
    "department": "Engineering"
    }
    }
    ],
    "userProfile": {
    "id": "prof_01HTR0PQRMNO",
    "firstName": "John",
    "lastName": "Doe",
    "name": "John Doe",
    "locale": "en",
    "emailVerified": false,
    "phoneNumber": "",
    "metadata": {},
    "customAttributes": {}
    },
    "metadata": {
    "plan": "free",
    "department": "Engineering"
    },
    "lastLogin": null
    }
    }
  3. When invited users click the invitation link in their email, Scalekit redirects them to your application’s registered initiate login endpoint. Your application then completes the authentication flow.

    Set up the initiate login endpoint:

    1. Register your endpoint in the Scalekit dashboard (for example, https://your-app.com/auth/login/initiate)

    2. Handle the redirect by constructing an authorization URL and redirecting the user to Scalekit’s hosted login page

    3. Complete authentication when the user returns to your callback URL

    Example endpoint implementation:

    Express.js
    app.get('/auth/login/initiate', (req, res) => {
    const redirectUri = 'http://localhost:3000/api/callback';
    const options = {
    scopes: ['openid', 'profile', 'email', 'offline_access'],
    prompt: 'create'
    };
    const authorizationUrl = scalekit.getAuthorizationUrl(redirectUri, options);
    res.redirect(authorizationUrl);
    });

    Authentication flow:

    1. User clicks invitation link → Redirected to your initiate login endpoint
    2. Your endpoint redirects → User goes to Scalekit’s hosted login page
    3. User authenticates → Scalekit verifies their email and credentials
    4. Scalekit redirects back → User returns to your callback URL with authorization code
    5. Your app exchanges code → Retrieve user profile and create session

This programmatic approach gives you full control over the invitation experience while leveraging Scalekit’s robust user management and email delivery infrastructure.