NetStacksNetStacks

Authentication (LDAP/OIDC)

TeamsEnterprise

Configure external authentication providers including LDAP/Active Directory, OIDC/OAuth2 SSO, and SSH certificate-based auth for NetStacks Controller.

Overview

NetStacks Controller supports multiple authentication sources so that organizations can integrate with their existing identity infrastructure. Users can authenticate through any of the following methods:

  • Local Authentication — Username and password stored directly in the Controller database. Passwords are hashed with bcrypt. Ideal for standalone deployments, service accounts, and initial setup.
  • LDAP / Active Directory — Authenticate against an LDAP directory server using bind operations. Supports TLS/STARTTLS, custom user filters, attribute mapping, and automatic user provisioning on first login.
  • OIDC / OAuth2 (SSO) — Authenticate via OpenID Connect with any compliant provider (Okta, Azure AD, Google Workspace, Keycloak, Auth0). Uses the authorization code flow with PKCE for security.
  • SSH Certificate Authentication — Issue short-lived SSH certificates through the built-in Certificate Authority for zero-standing-privilege device access. Certificates include identity binding and configurable TTLs.
Multiple sources can coexist

You can enable local auth, LDAP, and OIDC simultaneously. Each user'sauth_source field determines which provider handles their login. The login page shows options for all enabled authentication sources.

How It Works

Local Authentication Flow

The user submits a username and password to POST /api/auth/login. The Controller looks up the user by username, verifies the password against the stored bcrypt hash using constant-time comparison, and issues a JWT access token (short-lived) plus a refresh token (stored in the database). Login attempts are rate-limited per IP address to prevent brute-force attacks.

LDAP Authentication Flow

  1. User submits username and password to POST /api/auth/ldap.
  2. The Controller binds to the LDAP server using the configured service account (bind DN and password).
  3. It searches for the user using the configured base DN and user filter (e.g., (&(objectClass=user)(sAMAccountName={username}))).
  4. If found, the user's DN is extracted and a second bind is attempted with the user's credentials.
  5. On successful bind, user attributes (username, email, display name) are mapped from LDAP attributes using the configured attribute mapping.
  6. If auto_create_users is enabled and the user does not exist in NetStacks, a new user record is created with auth_source: ldap.
  7. A JWT token pair is issued just like local authentication.

OIDC Authentication Flow

  1. User clicks Sign in with SSO on the login page.
  2. The Controller generates a PKCE code challenge, CSRF token, and nonce, then redirects the user to the identity provider's authorization endpoint.
  3. The user authenticates at the IdP (Okta, Azure AD, etc.) and is redirected back to /api/auth/oidc/callback with an authorization code.
  4. The Controller exchanges the code for tokens at the provider's token endpoint, validates the ID token signature, and extracts claims (sub, email, name).
  5. User attributes are mapped from OIDC claims using the configured claim mapping.
  6. If the user does not exist in NetStacks, they are automatically created with auth_source: oidc.
  7. A JWT token pair is issued and the user is redirected to the application.

SSH Certificate Authentication

The Controller includes a built-in SSH Certificate Authority (CA). When a user connects to a device, the Controller signs a short-lived SSH certificate with the user's identity embedded as a certificate principal. The certificate TTL is configurable — typically 8 hours for interactive sessions and 1 hour for automated tasks. This eliminates the need for standing SSH keys on managed devices.

Zero standing privilege

With SSH certificate auth, no permanent SSH keys exist on devices. Certificates expire automatically, and access is tied to the user's Controller session. If a user is disabled, they can no longer obtain new certificates.

Step-by-Step Guide

Setting Up LDAP Authentication

  1. Navigate to Admin → Authentication (or Admin → Settings → Authentication).
  2. Click Add LDAP Source or enable the LDAP section.
  3. Enter the Server URL using LDAPS for encrypted connections:
    ldaps://ldap.dc1.example.net:636
  4. Set the Bind DN (service account) and Bind Password:
    cn=netstacks-svc,ou=services,dc=example,dc=net
  5. Configure the User Search Base:
    ou=netops,dc=example,dc=net
  6. Set the User Filter to locate users by their login name:
    (&(objectClass=user)(sAMAccountName={username}))
  7. Configure Attribute Mapping to map LDAP attributes to NetStacks user fields:
    • Username: sAMAccountName
    • Email: mail
    • Display Name: displayName
    • DN: distinguishedName
  8. Optionally enable STARTTLS if your server requires it (for ldap:// connections, not needed with ldaps://).
  9. Set Connection Timeout (default: 10 seconds).
  10. Enable Auto-create users to automatically provision users on first LDAP login.
  11. Click Test Connection to verify the service account can bind and query the directory.
  12. Click Save and Enable the LDAP source.
Use LDAPS or STARTTLS in production

Never use unencrypted LDAP (ldap:// without STARTTLS) in production. Credentials are transmitted in plaintext during bind operations. Useldaps:// (port 636) or enable STARTTLS for ldap://(port 389).

Setting Up OIDC / SSO Authentication

  1. Navigate to Admin → Authentication.
  2. Click Add OIDC Source or enable the OIDC section.
  3. Enter the Provider URL (discovery endpoint base):
    https://idp.example.net
    The Controller automatically fetches /.well-known/openid-configuration from this URL.
  4. Enter the Client ID and Client Secret from your identity provider's application registration.
  5. Set the Redirect URI in your IdP to match your Controller's callback URL:
    https://netstacks.dc1.example.net/api/auth/oidc/callback
  6. Configure Scopes (default: openid profile email).
  7. Configure Claim Mapping to map OIDC claims to NetStacks user fields:
    • Subject: sub (unique user identifier)
    • Email: email
    • Display Name: name
    • Username: preferred_username (or email as fallback)
  8. Click Test to verify discovery and client configuration.
  9. Click Save and Enable the OIDC source.
Supported OIDC providers

NetStacks works with any OpenID Connect compliant provider, including Okta, Azure AD (Entra ID), Google Workspace, Keycloak, Auth0, OneLogin, and Ping Identity. The Controller uses standard OIDC discovery, so no provider-specific configuration is needed.

Setting Up SSH Certificate Authentication

  1. Navigate to Admin → Settings → SSH CA (requires ssh_ca.* permission).
  2. Click Generate CA Key to create a new Certificate Authority key pair, or Import an existing CA private key.
  3. Configure certificate parameters including default principals, extensions, and validity periods.
  4. Set validity periods: recommended 8 hours for interactive sessions, 1 hour for automated/scripted access.
  5. Export the CA public key and deploy it to managed devices as a trusted user CA in /etc/ssh/sshd_config:
deploy-ca-key.shbash
# On each managed device, add to /etc/ssh/sshd_config:
TrustedUserCAKeys /etc/ssh/netstacks_ca.pub

# Then restart sshd:
systemctl restart sshd
Protect the CA private key

The CA private key is stored encrypted in the Controller's database. Never export or share it. If compromised, an attacker could issue certificates for any user identity. Rotate the CA key and redeploy the public key to all devices if you suspect a compromise.

Code Examples

LDAP Configuration via Settings API

configure-ldap.shbash
# Enable LDAP authentication
curl -X PUT https://netstacks.dc1.example.net/api/admin/settings/auth.ldap.enabled \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value": true}'

# Set LDAP server URL
curl -X PUT https://netstacks.dc1.example.net/api/admin/settings/auth.ldap.server_url \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value": "ldaps://ldap.dc1.example.net:636"}'

# Set bind credentials
curl -X PUT https://netstacks.dc1.example.net/api/admin/settings/auth.ldap.bind_dn \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value": "cn=netstacks-svc,ou=services,dc=example,dc=net"}'

# Set user search base and filter
curl -X PUT https://netstacks.dc1.example.net/api/admin/settings/auth.ldap.base_dn \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value": "ou=netops,dc=example,dc=net"}'

curl -X PUT https://netstacks.dc1.example.net/api/admin/settings/auth.ldap.user_filter \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value": "(&(objectClass=user)(sAMAccountName={username}))"}'

LDAP Attribute Mapping

ldap-attribute-mapping.shbash
curl -X PUT https://netstacks.dc1.example.net/api/admin/settings/auth.ldap.attribute_mapping \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "value": {
      "username": "sAMAccountName",
      "email": "mail",
      "name": "displayName",
      "dn": "distinguishedName"
    }
  }'

Test LDAP Connection

test-ldap-bind.shbash
# Test the LDAP bind with ldapsearch (useful for debugging):
ldapsearch -H ldaps://ldap.dc1.example.net:636 \
  -D "cn=netstacks-svc,ou=services,dc=example,dc=net" \
  -W \
  -b "ou=netops,dc=example,dc=net" \
  "(&(objectClass=user)(sAMAccountName=jsmith))" \
  sAMAccountName mail displayName

OIDC Discovery Verification

verify-oidc-discovery.shbash
# Verify your OIDC provider's discovery endpoint:
curl -s https://idp.example.net/.well-known/openid-configuration | jq '{
  issuer,
  authorization_endpoint,
  token_endpoint,
  userinfo_endpoint,
  scopes_supported
}'

Expected response:

oidc-discovery-response.jsonjson
{
  "issuer": "https://idp.example.net",
  "authorization_endpoint": "https://idp.example.net/oauth2/authorize",
  "token_endpoint": "https://idp.example.net/oauth2/token",
  "userinfo_endpoint": "https://idp.example.net/oauth2/userinfo",
  "scopes_supported": ["openid", "profile", "email", "groups"]
}

OIDC Configuration via Settings API

configure-oidc.shbash
# Enable OIDC and set provider details
curl -X PUT https://netstacks.dc1.example.net/api/admin/settings/auth.oidc.enabled \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value": true}'

curl -X PUT https://netstacks.dc1.example.net/api/admin/settings/auth.oidc.provider_url \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value": "https://idp.example.net"}'

curl -X PUT https://netstacks.dc1.example.net/api/admin/settings/auth.oidc.client_id \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value": "netstacks-controller"}'

Authenticate via LDAP (Login API)

ldap-login.shbash
curl -X POST https://netstacks.dc1.example.net/api/auth/ldap \
  -H "Content-Type: application/json" \
  -d '{
    "username": "jsmith",
    "password": "LdapP@ssw0rd"
  }'

Response:

auth-response.jsonjson
{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "refresh_token": "rt_a1b2c3d4e5f6...",
  "token_type": "Bearer",
  "expires_in": 900
}

Questions & Answers

How do I set up LDAP authentication?
Navigate to Admin → Authentication and enable the LDAP section. Provide your LDAP server URL (use ldaps:// for TLS), bind DN and password for the service account, user search base DN, and a user filter template. Configure attribute mapping to map LDAP fields to NetStacks user fields. Test the connection to verify the service account can bind, then save and enable. See the step-by-step guide above for detailed instructions.
What OIDC providers are supported?
NetStacks supports any OpenID Connect compliant provider, including Okta, Azure AD (Microsoft Entra ID), Google Workspace, Keycloak, Auth0, OneLogin, and Ping Identity. The Controller uses standard OIDC discovery (/.well-known/openid-configuration), so any provider that implements the OpenID Connect specification will work without provider-specific configuration.
Can I use multiple authentication sources simultaneously?
Yes. Local authentication, LDAP, and OIDC can all be enabled at the same time. Each user's auth_source field determines which provider handles their login. The login page displays options for all enabled sources. Users are locked to their auth source — an LDAP user cannot log in with a local password and vice versa.
How does LDAP group mapping work?
Currently, LDAP authentication focuses on user authentication and attribute mapping. Users authenticated via LDAP are created in NetStacks and can be assigned roles manually by an admin or through the API. LDAP group-to-role mapping can be configured through attribute mapping to pull group membership from LDAP and map it to NetStacks roles during user provisioning.
What certificate validity periods should I use?
For interactive terminal sessions, 8 hours is a good default — it covers a full work shift without requiring re-authentication. For automated tasks and scripts, use 1 hour or less to minimize the window of exposure if a certificate is compromised. For highly sensitive environments, consider validity periods as short as 15–30 minutes with automatic renewal.
How do I migrate from local auth to SSO?
First, configure and test your OIDC or LDAP provider. Then, for each user, update their auth_source to match the new provider. Users with matching usernames or email addresses are linked to the existing account on their first SSO login. For a phased migration, enable SSO alongside local auth so users can transition gradually. Once all users have migrated, you can disable local auth for non-service accounts.

Troubleshooting

LDAP Connection Refused

  • Verify the server URL is correct, including protocol and port (e.g., ldaps://ldap.dc1.example.net:636).
  • Check that the LDAP server is reachable from the Controller host. Test with: nc -zv ldap.dc1.example.net 636
  • If using TLS, ensure the LDAP server's certificate is trusted by the Controller. Self-signed certificates may require the skip_cert_verify option (not recommended for production).
  • Check firewall rules between the Controller and LDAP server. Port 636 (LDAPS) or 389 (LDAP+STARTTLS) must be open.
  • Review the Controller logs for LDAP connection failed or Service account bind failed messages.

OIDC Redirect Loop

  • Verify the callback URL registered in your IdP matches exactly: https://netstacks.dc1.example.net/api/auth/oidc/callback
  • Check that the client ID and client secret are correct and have not been rotated in the IdP without updating NetStacks.
  • Ensure the Controller's external URL is correct (the URL that users access, not the internal hostname).
  • Verify CSRF token and state validation are passing — check the Controller logs for OIDC state mismatch errors.

SSH Certificate Expired or Rejected

  • Check the certificate validity period. If set too short (e.g., 5 minutes), the certificate may expire before the session is established on slow connections.
  • Verify the CA public key is correctly deployed to the target device in /etc/ssh/sshd_config as TrustedUserCAKeys.
  • Ensure the certificate principal matches a user that the target device accepts. Check AuthorizedPrincipalsFile if configured.
  • Verify system clocks are synchronized. Time skew between the Controller and target devices can cause certificate validation failures.

LDAP User Filter Not Matching

  • Test the filter directly with ldapsearch to confirm it returns the expected user entry.
  • Ensure the {username} placeholder is present in the filter — the Controller replaces it with the login username.
  • Check the base DN scope. If users are in a different OU than the configured base DN, they will not be found.
  • For Active Directory, use sAMAccountName (not uid) as the username attribute in the filter.

OIDC Claims Missing or Wrong

  • Verify the scopes include profile and email — some providers require explicit scope requests to return these claims.
  • Check the claim mapping configuration. Different providers use different claim names (e.g., preferred_username vs upn).
  • Use the OIDC discovery endpoint to see which claims your provider supports: curl https://idp.example.net/.well-known/openid-configuration
  • User Management — Create and manage user accounts, including setting the authentication source for each user.
  • Roles & Permissions — Define the permission sets that determine what authenticated users can access.
  • SSH Certificates — Configure certificate parameters, TTLs, and principals for SSH certificate-based auth.
  • Credential Vault — Manage the encrypted vault that stores credentials used alongside authentication.
  • API Authentication — Understand JWT token flows, refresh mechanisms, and bearer authentication for API access.
  • Audit Logs — Review authentication events including logins, failures, and provider configuration changes.