Authentication and email
Configure SMTP delivery, OAuth providers, optional TOTP MFA, and signup policy for self-hosted Dreadnode.
The authentication, email, and signup settings on this page are chart configuration, applied by a redeploy. Configure them in a Helm overlay, under Authentication & Email in the Admin Console, or with matching KOTS ConfigValues items. The email allow-list and other settings without a dedicated field use Advanced Helm Values. Every credential on this page has a protected Embedded Cluster field.
Helm commands on this page use $NAMESPACE. Set it to your release namespace before creating
Secrets:
export NAMESPACE=dreadnodeThe runtime signup controls under Admin → Security — IP rate limits, CIDR deny and allow policies, and disposable-domain rules — are a separate plane and need no redeploy. See Users and organizations.
Optional TOTP MFA
Section titled “Optional TOTP MFA”Users enable authenticator-app MFA under Account Settings → Security. The behavior is the same in SaaS and Enterprise deployments: password and OAuth/OIDC sign-in requires a TOTP or unused recovery code before Dreadnode issues access and refresh tokens. API keys and service credentials remain unchanged.
TOTP secrets use the existing SECRETS_ENCRYPTION_KEY. Keep that key stable across API replicas and upgrades; changing it makes enrolled factors unreadable. Recovery codes and five-minute challenge tokens are stored only as hashes.
Enabling, disabling, or resetting MFA revokes every refresh session for the user. Existing stateless access tokens can remain valid until the configured access-token TTL expires, which defaults to 30 minutes.
Reset MFA after identity verification
Section titled “Reset MFA after identity verification”Verify the account owner’s identity using your organization’s recovery procedure, then call the remediation endpoint with a recorded reason:
curl -X POST 'https://<your-domain>/api/v1/admin/users/<user-id>/mfa/reset' \ -H 'Authorization: Bearer <operator-access-token>' \ -H 'Content-Type: application/json' \ --data '{"reason":"Identity verified through the approved recovery procedure"}'# {"enabled":false}The operator needs the platform:account_remediation scope. The reset removes the factor, invalidates pending MFA challenges, revokes refresh sessions, and writes an audit event containing the operator, subject, reason, and timestamp.
Security operators can export evidence from GET /api/v1/admin/auth/mfa/audit, optionally filtering by subject_user_id. Audit rows never contain TOTP secrets, submitted codes, recovery codes, provider tokens, or MFA transaction tokens.
Email delivery
Section titled “Email delivery”By default, Dreadnode does not send email. The API logs invitation, password-reset, account-setup,
and verification links at WARNING level so an operator can deliver them manually.
When an administrator assigns organization ownership to an email without an account, Dreadnode sends a 24-hour account setup link. The recipient uses that link to set a password, verify the email, and sign in. Dreadnode never sends a temporary password. Configure email delivery before assigning owners if recipients must claim accounts without operator help.
Loops deployments can add an account-setup template ID to
EMAIL_LOOPS_TRANSACTIONAL_IDS for dedicated setup copy. When that key is absent, Dreadnode uses
the configured confirm-email template so existing deployments keep sending links.
Configure the API chart:
dreadnode-api: config: email: provider: smtp fromName: Dreadnode smtp: host: smtp.example.com port: 587 user: apikey useTls: true existingSecret: dreadnode-smtp-password passwordKey: passwordCreate the referenced Secret in the Helm release namespace:
kubectl -n "$NAMESPACE" create secret generic dreadnode-smtp-password \ --from-literal=password='<smtp-password>'Open Config → Authentication & Email, enable SMTP email delivery, then enter the relay and sender settings. The Admin Console stores the password as a protected value and creates the Kubernetes Secret.
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: smtp_enabled: value: "1" smtp_host: value: smtp.example.com smtp_port: value: "587" smtp_user: value: apikey smtp_password: valuePlaintext: '<smtp-password>' smtp_use_tls: value: "1" smtp_from_address: smtp_from_name: value: DreadnodeOAuth providers
Section titled “OAuth providers”Local password authentication remains available when you configure OAuth. Each provider can be enabled independently.
OpenID Connect
Section titled “OpenID Connect”Use the generic provider for Authentik, Keycloak, Okta, and other OpenID
Connect issuers. metadataUrl, clientId, and the client Secret are all
required.
dreadnode-api: config: oauth: oidc: clientId: <oidc-client-id> metadataUrl: https://idp.example.com/.well-known/openid-configuration existingSecret: dreadnode-oidc-oauth clientSecretKey: clientSecret displayName: Authentik scopes: openid email profileCreate the referenced Secret:
kubectl -n "$NAMESPACE" create secret generic dreadnode-oidc-oauth \ --from-literal=clientSecret='<oidc-client-secret>'Open Config → Authentication & Email, enable OpenID Connect, then enter OIDC Client ID, Client Secret, Metadata URL, Login Button Label, and Scopes.
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: oidc_enabled: value: "1" oidc_client_id: value: '<oidc-client-id>' oidc_client_secret: valuePlaintext: '<oidc-client-secret>' oidc_metadata_url: value: https://idp.example.com/.well-known/openid-configuration oidc_display_name: value: Authentik oidc_scopes: value: openid email profileRegister this redirect URI with the provider:
https://<your-domain>/auth/oidc/callbackUse the scheme and domain configured for Dreadnode. The scopes must include
openid and must cause the issuer to return an email claim in either the ID
token or userinfo response; openid email profile is the usual configuration.
New users receive the default role on first login; group and role claim mapping
is not currently supported. An issuer that sends group claims logs in normally,
and Dreadnode ignores those claims.
Create an OIDC Web Application in Okta. Dreadnode authenticates with a
client secret, so do not choose the SPA application type. Keep the default
Client secret authentication method (client_secret_basic); post-only
client authentication is not supported. Configure:
- Sign-in redirect URI:
https://<your-domain>/auth/oidc/callback, matching exactly - Grant type: Authorization Code
- Scopes:
openid email profile
Okta exposes two authorization-server shapes:
| Server | Metadata URL |
|---|---|
| Org | https://<your-okta-domain>/.well-known/openid-configuration |
Custom (including default) | https://<your-okta-domain>/oauth2/<server-id>/.well-known/openid-configuration |
Use the org authorization server for ordinary Okta sign-in. Choose a custom authorization server only when you need its customized claims or access policies, and make sure that server has an access policy covering the Dreadnode application. The generic connector accepts either discovery URL.
Dreadnode matches returning users by email address. The sub claim is retained
with the identity data and is checked when ID-token claims are supplemented
from the userinfo endpoint, but it is not used for account lookup. Changing a
user’s Okta email can therefore create a separate Dreadnode account.
OAuth-created accounts are treated as email-confirmed even when Okta omits
email_verified. Restrict the Okta application’s assignment and authorization
policy to users whose email addresses your organization trusts.
GitHub and Google
Section titled “GitHub and Google”GitHub and Google use the same secret-backed pattern:
dreadnode-api: config: oauth: github: clientId: <github-client-id> existingSecret: dreadnode-github-oauth clientSecretKey: clientSecret google: clientId: <google-client-id> existingSecret: dreadnode-google-oauth clientSecretKey: clientSecretCreate one Secret for each configured provider:
kubectl -n "$NAMESPACE" create secret generic dreadnode-github-oauth \ --from-literal=clientSecret='<github-client-secret>'
kubectl -n "$NAMESPACE" create secret generic dreadnode-google-oauth \ --from-literal=clientSecret='<google-client-secret>'Open Config → Authentication & Email, enable GitHub login or Google login, then enter the client ID and client secret for each provider.
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: github_oauth_enabled: value: "1" github_client_id: value: '<github-client-id>' github_client_secret: valuePlaintext: '<github-client-secret>' google_oauth_enabled: value: "1" google_client_id: value: '<google-client-id>' google_client_secret: valuePlaintext: '<google-client-secret>'Remove the provider you do not use. The Embedded Cluster secrets are protected in stored configuration and written to Kubernetes Secrets without a cluster-shell step.
Register these callback URLs with each provider:
- GitHub:
https://<your-domain>/auth/github/callback - Google:
https://<your-domain>/auth/google/callback
Both providers reach the public GitHub and Google endpoints, so neither works on an airgapped install. To use Google Workspace as your enterprise identity provider, prefer OpenID Connect instead, which centralizes sign-in at your own tenant. Dreadnode does not currently map identity-provider groups to platform or organization roles.
Signup policy
Section titled “Signup policy”Raise the minimum password length or restrict new accounts to email patterns:
dreadnode-api: config: auth: minPasswordLength: 12 emailRegexes: - '^.*@example\.com$'Open Config → Authentication & Email, enable Set a custom password policy, then set
Minimum Password Length. Put dreadnode-api.config.auth.emailRegexes under Advanced Helm
Values when you also need an email allow-list.
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: signup_policy_customize: value: "1" min_password_length: value: "12" advanced_helm_values: value: | dreadnode-api: config: auth: emailRegexes: - '^.*@example\.com$'An empty emailRegexes list allows any email address. Omitting minPasswordLength uses the API
default of 8.