Partner sign-in with your identity

Let partners sign in to your portal with your app's own session (a short-lived JWT) or your OpenID Connect IdP, with no second password.

Embed
Preview of the card
<a href="https://referalli.com/docs/portal-sign-in"><img src="https://referalli.com/docs/_api/public/orgs/07f432f4-34b9-46a7-aaad-c0e395d2e4f9/spaces/2bf4f614-3630-4fbf-85f9-5ecafa6b7d97/pages/a9199f9b-9b3a-4b10-ab77-d0eeced32475/social-card.svg?v=3e7ae33eec8b" alt="Partner sign-in with your identity" width="600" height="315"></a>

By default, partners sign in to your portal with a Referalli partner account. You can let them use your identity instead, so they need no second password:

Adapter

How it works

referalli

A Referalli partner account (the default)

custom

Your backend mints a short-lived JWT; Referalli verifies it against your JWKS. Fits any auth platform.

oidc

Your own OpenID Connect IdP, used for partners

Set this up in Settings → SSO → Partner sign-in, or with PUT /v1/org/portal-auth.

Custom: your app's session (JWT)

This fits any provider that can sign a JWT with a private key, including Clerk, Auth0, Supabase, Firebase, Cognito and Atlas JWT templates.

  1. Publish your public keys as a JWKS over HTTPS.

  2. Configure the adapter:

    curl -X PUT https://referalli.com/v1/org/portal-auth \
      -H "cookie: referalli_session=…" -H "x-org-id: org_…" \
      -H "content-type: application/json" \
      -d '{
        "adapter": "custom",
        "issuer": "https://app.example.com",
        "jwksUrl": "https://app.example.com/.well-known/jwks.json",
        "loginUrl": "https://app.example.com/partners",
        "autoEnrollProgramId": "prog_…"
      }'
  3. When a signed-in user of your app opens the partner portal, mint a token and send their browser to it:

    https://referalli.com/v1/portal-auth/<org id>/jwt?token=<jwt>&next=/portal

The token must meet all of these:

  • It is signed with an asymmetric algorithm (RS256, PS256, ES256 or EdDSA). HS256 is refused.

  • iss is your configured issuer, and aud is referalli:<org id>.

  • It carries sub (your user id), iat and exp, with exp - iat ≤ 300 seconds.

  • It carries email (used to create the account the first time) and, optionally, name.

  • Each token works once. Add a jti, or every token is unique by its hash anyway.

import { SignJWT, importPKCS8 } from 'jose';

const key = await importPKCS8(process.env.PORTAL_SIGNING_KEY, 'ES256');
const token = await new SignJWT({ email: user.email, name: user.name })
  .setProtectedHeader({ alg: 'ES256', kid: 'portal-1' })
  .setIssuer('https://app.example.com')
  .setAudience(`referalli:${ORG_ID}`)
  .setSubject(user.id)
  .setIssuedAt()
  .setExpirationTime('2m')
  .sign(key);
res.redirect(`https://referalli.com/v1/portal-auth/${ORG_ID}/jwt?token=${token}`);

If you set loginUrl, the portal's sign-in page shows a button that sends partners there.

Your OpenID Connect IdP

Choose oidc and enter the issuer, client ID and client secret. Register https://referalli.com/v1/auth/sso/callback as a redirect URI. Partners start at /v1/portal-auth/<org id>/oidc/start, and the portal's sign-in page shows the button for you. This works on your verified portal domain too.

Which partner record

After a sign-in, Referalli finds the partner's record in your program:

  1. a partner already linked to this account;

  2. else a partner you created with externalRef equal to the token's sub, not yet claimed;

  3. else, with autoEnrollProgramId set, a new partner enrolled in that program.

Never linked by email

The identity is jwt:<issuer>:<sub> or oidc:<issuer>:<sub>. A first sign-in with an email that another Referalli partner account already uses is refused with email_taken. To connect that account, the partner signs in to it first, then follows your link with &link=1.

Updated