Authentication

Local accounts, TOTP MFA, SAML 2.0 SSO, guest submission, and API keys.

Open Help Desk supports four authentication paths. They can be combined — for example, SAML SSO for most users plus TOTP MFA for admin accounts, with API keys for scripted access.

MethodWho it's forEnabled by default
Local accountsAll rolesYes
TOTP MFAAll roles (layered on local auth)No — set MFA_ENABLED=true
SAML 2.0All roles (replaces local for non-admins)No — set SAML_ENABLED=true
Guest submissionUnauthenticated visitorsNo — set GUEST_SUBMISSION_ENABLED=true
API keysScripts and integrationsYes (self-service by users)

Local accounts

Local authentication is enabled by default. Users log in with their email address and password. Passwords are hashed with bcrypt at a cost factor of 12.

Account creation

Accounts are created in one of three ways:

Password requirements

Passwords must be at least 10 characters. There is no additional complexity enforcement — length is the most effective password policy for user-chosen passwords. Admins can force a password reset from Admin → Users → [user] → Reset password.

When SAML is enabled

Enabling SAML disables local auth for Staff and User accounts. Admin accounts always retain local-auth access as a deliberate failsafe — if the IdP is unavailable, admins can still log in at the standard login page and choose Sign in with password.

TOTP MFA

Set MFA_ENABLED=true in your environment to enable time-based one-time password (TOTP) MFA across the application. TOTP works with Google Authenticator, Authy, 1Password, Bitwarden, and any RFC 6238-compliant app.

Enrollment flow

A user who has not yet enrolled in MFA is redirected to the enrollment page after their next successful password login.

1

Scan the QR code

The enrollment page displays a QR code and a text secret. Scan the code with your TOTP app, or enter the secret manually.

2

Confirm with a live code

Enter the current 6-digit code from the TOTP app. This verifies that enrollment succeeded and activates MFA on the account.

3

Save recovery codes

Recovery codes are displayed once after enrollment. Store them securely — each code is single-use and cannot be retrieved later. If you lose both your device and your recovery codes, an admin must reset your MFA from the user management panel.

Login flow with MFA enrolled

  1. User enters email and password. Credentials are validated.
  2. The session is marked as MFA pending — authenticated but not yet fully authorized.
  3. The user is redirected to the MFA verification page and prompted for their TOTP code.
  4. On successful code entry, the session is promoted to fully authenticated and the user is redirected to the dashboard.

The MFA pending session has a 5-minute expiry. If the user doesn't complete MFA verification within 5 minutes of the password step, they must restart the login.

Admin enforcement

Admins can enforce MFA for specific roles from Admin → Settings → Authentication → Require MFA for. Users with enforced MFA who have not yet enrolled are redirected to enrollment on their next login and cannot proceed until they complete it.

Recovery codes

At the MFA verification prompt, users can click Use recovery code and enter one of their saved codes instead of a TOTP code. Each recovery code is permanently invalidated after use. If fewer than 3 recovery codes remain, the app prompts the user to regenerate a new set from their profile.

Admin MFA reset

To reset a user's MFA (e.g. after they lose their device and all recovery codes): Admin → Users → [user] → Reset MFA. This deletes the TOTP secret and all recovery codes. The user is prompted to re-enroll on their next login.

TOTP codes in the API

For programmatic login, submit the TOTP code to POST /api/auth/mfa/verify after a successful password login. See the API: Auth endpoints.

SAML 2.0 SSO

Open Help Desk acts as a SAML 2.0 Service Provider (SP). It works with any standards-compliant Identity Provider.

General setup

1

Generate an SP certificate and private key

SAML requires the SP to present a certificate to the IdP for request signing and response verification.

openssl req -x509 -newkey rsa:4096 \
  -keyout saml.key -out saml.crt \
  -days 3650 -nodes \
  -subj "/CN=Open Help Desk"

Store both files somewhere accessible to the container (e.g. a Docker volume or secret). Set the container paths in SAML_CERT_FILE and SAML_KEY_FILE.

2

Register the SP with your IdP

Once the app is running, your SP metadata is at:

https://<BASE_URL>/api/auth/saml/metadata

Import this URL into your IdP's application configuration. The ACS (Assertion Consumer Service) URL is:

https://<BASE_URL>/api/auth/saml/acs

At minimum, configure your IdP to send these attributes in the SAML assertion:

Attribute nameValue
emailUser's email address
firstNameUser's given name
lastNameUser's family name
3

Set the IdP metadata URL and enable SAML

SAML_ENABLED=true
SAML_METADATA_URL=https://your-idp.example.com/saml/metadata
SAML_CERT_FILE=/run/secrets/saml.crt
SAML_KEY_FILE=/run/secrets/saml.key

Restart the application. The server fetches and caches the IdP metadata on startup.

4

Test with a non-admin account

Open a private browser window and click Sign in with SSO. Your admin account's local-auth login is still available by clicking Sign in with password.

IdP-specific setup guides

Okta
  1. In Okta Admin: Applications → Create App Integration → SAML 2.0
  2. On the SAML Settings page:
    • Single sign-on URL: https://<BASE_URL>/api/auth/saml/acs
    • Audience URI (SP Entity ID): https://<BASE_URL>/api/auth/saml/metadata
    • Name ID format: EmailAddress
  3. Under Attribute Statements, add:
    • emailuser.email
    • firstNameuser.firstName
    • lastNameuser.lastName
  4. Finish the app creation. Go to the Sign On tab and copy the Identity Provider metadata URL.
  5. Set that URL as SAML_METADATA_URL.
  6. Assign users or groups to the Okta application.
Microsoft Azure AD / Entra ID
  1. In the Azure portal: Microsoft Entra ID → Enterprise applications → New application → Create your own application. Choose Integrate any other application you don't find in the gallery.
  2. Go to Single sign-on → SAML.
  3. Under Basic SAML Configuration:
    • Identifier (Entity ID): https://<BASE_URL>/api/auth/saml/metadata
    • Reply URL (ACS): https://<BASE_URL>/api/auth/saml/acs
  4. Under Attributes & Claims, verify that emailaddress, givenname, and surname are present. Map them to email, firstName, and lastName respectively.
  5. Under SAML Certificates, copy the App Federation Metadata Url.
  6. Set that URL as SAML_METADATA_URL.
  7. Under Users and groups, assign the users or groups that should have access.
Google Workspace
  1. In Google Admin console: Apps → Web and mobile apps → Add app → Add custom SAML app.
  2. Give the app a name and click Continue.
  3. On the Google Identity Provider details page, click Download Metadata and host the XML at a stable URL, or note the SSO URL and certificate to build the metadata manually.
  4. Under Service provider details:
    • ACS URL: https://<BASE_URL>/api/auth/saml/acs
    • Entity ID: https://<BASE_URL>/api/auth/saml/metadata
    • Name ID format: EMAIL
  5. Under Attribute mapping:
    • Primary Email → email
    • First name → firstName
    • Last name → lastName
  6. Set the URL of your hosted metadata XML as SAML_METADATA_URL.
  7. In the app settings, turn on access for the relevant organizational units.

Just-in-time user provisioning

When a user logs in via SAML for the first time, their account is automatically created from the assertion attributes (email, firstName, lastName). The new account receives the User role. Promote accounts to Staff or Admin from Admin → Users.

Subsequent logins update the user's name if it has changed in the IdP, but do not change their role.

SP certificate rotation

To rotate the SP certificate without downtime: generate new cert/key files, update SAML_CERT_FILE and SAML_KEY_FILE, update the SP certificate in your IdP's configuration (most IdPs allow configuring a secondary certificate during the transition period), then restart the application.

Admin failsafe — Admin accounts can always log in with their local password by clicking Sign in with password on the login page, even when SAML is the default auth method. Do not lose your admin password.

Guest submission

Set GUEST_SUBMISSION_ENABLED=true to allow unauthenticated visitors to submit support tickets without creating an account.

Submission flow

  1. Guest navigates to /submit (linked from the login page when guest submission is enabled).
  2. Guest fills out the ticket form: subject, description, category, and their email address.
  3. On submission, the ticket is created and the system generates a unique tracking number (e.g. TRK-2849) and a time-limited signed access link.
  4. The access link is emailed to the address provided. The guest clicks it to view their ticket.

Access links

The email link authenticates the guest for that specific ticket only. It is:

What guests can do

Guests cannot see internal notes, other tickets, the ticket list, or any admin functionality.

Email required — Guest submission requires a functioning SMTP configuration. Without email, the guest cannot receive their access link. The system will still create the ticket, but the tracking number/link won't be deliverable.

API keys

API keys are long-lived bearer tokens for use in scripts, CI pipelines, and tool integrations where a browser-based login flow is impractical.

Creating a key

  1. Log in and navigate to My Profile → API Keys → New key.
  2. Give the key a descriptive name (e.g. monitoring-script, jira-integration).
  3. The key is shown exactly once after creation. Copy it immediately and store it in a secret manager, CI secret store, or equivalent. It cannot be retrieved after the dialog closes.

API keys are stored as SHA-256 hashes. Even if the database is compromised, the plaintext key values are not exposed.

Using a key

Pass the key as a Bearer token in the Authorization header:

curl https://helpdesk.example.com/api/tickets \
  -H "Authorization: Bearer ohd_sk_xxxxxxxxxxxxxxxxxxx"

All /api/ endpoints and the /mcp/ server accept API key auth.

Permissions

An API key inherits the full permissions of the account that created it. A key from a Staff account can do anything a Staff user can do — and nothing more. To perform admin operations via the API, create the key while logged in as an Admin.

Revoking a key

Go to My Profile → API Keys, find the key by name, and click Revoke. Revocation is immediate — in-flight requests using that key will receive 401 Unauthorized. There is no grace period.

Key naming conventions

Since the key value cannot be retrieved after creation, the name is your only way to identify a key later. Use names that describe the consumer: pagerduty-webhook, ci-pipeline-prod, alex-cli-dev. Include dates in names if you rotate keys on a schedule.

← Getting Started Admin Guide →