Sourcebot logo

    JumpCloud SSO Authentication Failure (copy)

    Recent Chats

    Sign in to access your chat history.

    So I've just managed to get Sourcebot spun up this morning, and upon configuring JC SSO, the request appears to fail. The SB login screen gives a generic "An error occurred during authentication. Please try again" banner.

    Looking at the request flows, I can see the following response from the JC auth request: error=invalid_state&error_description=The+state+is+missing+or+does+not+have+enough+characters+and+is+therefore+considered+too+weak.+Request+parameter+%27state%27+must+be+at+least+be+8+characters+long+to+ensure+sufficient+entropy.&state=

    Answer

    JumpCloud SSO invalid_state Error

    The error you're seeing — invalid_state / The state is missing or does not have enough characters — is not a bug in Sourcebot's code, but almost certainly a configuration issue with the AUTH_SECRET environment variable.

    Root Cause

    Sourcebot uses Auth.js (NextAuth.js) for authentication. During an OIDC flow (like JumpCloud SSO), Auth.js generates a cryptographic state parameter that it sends to the identity provider as a CSRF protection measure. This state is derived from the AUTH_SECRET value.

    The default AUTH_SECRET in the docker-compose.yml is a placeholder value of all zeros docker-compose.yml:21-21:

    1AUTH_SECRET=${AUTH_SECRET:-000000000000000000000000000000000}

    If you haven't overridden AUTH_SECRET with a properly generated random secret, Auth.js will produce a weak or degenerate state value. JumpCloud is stricter than some other OIDC providers and enforces a minimum of 8 characters of entropy on the state parameter — hence the rejection.

    How to Fix

    1. Generate a proper AUTH_SECRET using the command suggested in the docker-compose comment:

      1openssl rand -base64 33
    2. Set AUTH_SECRET in your environment (either in a .env file or directly in your docker-compose.yml override) with the generated value.

    3. Also verify AUTH_URL is set correctly docker-compose.yml:20-20. It must match the externally accessible URL of your Sourcebot instance (e.g., https://sourcebot.coolcorp.com), not the default http://localhost:3000. Auth.js uses this to construct the callback URL and state validation. A mismatch here can also cause state issues.

    4. Restart Sourcebot after making changes.

    Verifying Your JumpCloud Configuration

    Make sure your JumpCloud SSO app is configured per the docs idp.mdx:527-568:

    • SSO type is set to "OIDC"
    • Redirect URI is <your_AUTH_URL>/api/auth/callback/jumpcloud
    • Login URL is <your_AUTH_URL>/login
    • The issuer is typically https://oauth.id.jumpcloud.com

    And your Sourcebot config file includes the JumpCloud identity provider idp.mdx:546-565:

    1{
    2 "identityProviders": [
    3 {
    4 "provider": "jumpcloud",
    5 "purpose": "sso",
    6 "clientId": { "env": "JUMPCLOUD_IDENTITY_PROVIDER_CLIENT_ID" },
    7 "clientSecret": { "env": "JUMPCLOUD_IDENTITY_PROVIDER_CLIENT_SECRET" },
    8 "issuer": { "env": "JUMPCLOUD_IDENTITY_PROVIDER_ISSUER" }
    9 }
    10 ]
    11}

    The JumpCloud provider is created as a generic OIDC provider in sso.ts:437-447, which relies on Auth.js's standard OIDC state handling — so the fix is entirely on the configuration side.

    Summary

    CheckWhat to verify
    AUTH_SECRETMust be a strong random string (≥33 chars), not the default zeros
    AUTH_URLMust match your external Sourcebot URL exactly
    JumpCloud redirect URIMust be <AUTH_URL>/api/auth/callback/jumpcloud
    JumpCloud issuer env varTypically https://oauth.id.jumpcloud.com
    docker-compose.yml
    idp.mdx
    sso.ts

    AUTH_SECRET is set to a suitable value.

    However the login attempts are still failing. It looks like the generated request URL for JumpCloud doesn't include the state param. Example:

    1https://oauth.id.jumpcloud.com/oauth2/auth?response_type=code&client_id=804deecf-d**redacted**&redirect_uri=https%3A%2F%2Fsourcebot.**redacted**%2Fapi%2Fauth%2Fcallback%2Fjumpcloud&code_challenge=**redacted**&code_challenge_method=S256&scope=openid+profile+email

    Answer

    Root Cause: Missing checks in createJumpCloudProvider

    This is a bug in Sourcebot's createJumpCloudProvider implementation. The state parameter is absent from the authorization URL because the JumpCloud provider is defined as a plain object without a checks field, which tells Auth.js which security mechanisms to use during the OIDC flow.

    The Problem

    The createJumpCloudProvider function sso.ts:437-447 returns a bare object with just the minimum fields:

    1{
    2 id: 'jumpcloud',
    3 name: "JumpCloud",
    4 type: "oidc",
    5 clientId: clientId,
    6 clientSecret: clientSecret,
    7 issuer: issuer,
    8 allowDangerousEmailAccountLinking: ...
    9}

    Auth.js uses the checks array on a provider config to decide what to include in the authorization URL. Without it explicitly set, Auth.js defaults to ["pkce"] only for OIDC providers — meaning it generates a code_challenge and code_challenge_method (which you can see in your URL), but omits the state parameter, since "state" is not in the checks list.

    JumpCloud's OIDC implementation requires the state parameter to be present and at least 8 characters long.

    Compare With a Working Provider

    Compare with createAuthentikProvider sso.ts:427-435 or createOktaProvider sso.ts:306-314 — these use the official next-auth provider wrappers (e.g. Authentik(...), Okta(...)) which include proper defaults like checks: ["pkce", "state"] internally. The JumpCloud provider uses a raw object and misses this.

    The Fix

    The createJumpCloudProvider function needs checks: ["pkce", "state"] added to the provider object sso.ts:437-447:

    1const createJumpCloudProvider = (clientId: string, clientSecret: string, issuer: string): Provider => {
    2 return {
    3 id: 'jumpcloud' satisfies IdentityProviderType,
    4 name: "JumpCloud",
    5 type: "oidc",
    6 clientId: clientId,
    7 clientSecret: clientSecret,
    8 issuer: issuer,
    9 checks: ["pkce", "state"], // ← ADD THIS
    10 allowDangerousEmailAccountLinking: env.AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING === 'true',
    11 } as Provider;
    12}

    This will cause Auth.js to include both the code_challenge (PKCE) and the state parameter in the redirect URL sent to JumpCloud, satisfying JumpCloud's entropy requirement.

    Workaround Until Fixed

    If you cannot patch the code directly, you could raise this as a bug with the Sourcebot team referencing the createJumpCloudProvider function sso.ts:437-447 — the fix is a one-line addition and straightforward.

    sso.ts

    This chat is read-only.