Signal K Server supports OpenID Connect (OIDC) authentication. This enables Single Sign-On (SSO) with identity providers (IdPs) running on your local network (Keycloak, Authentik, Authelia) or cloud services (Auth0, Okta, and others).
OIDC authentication provides:
OIDC works alongside local authentication. You can have both local users and OIDC users simultaneously.
In your identity provider, create a new OIDC/OAuth2 client application:
signalk-serverhttps://your-signalk-server:3000/signalk/v1/auth/oidc/callbackNote the Client ID and Client Secret for the next step.
OIDC can be configured via environment variables or the Admin UI.
export SIGNALK_OIDC_ENABLED=true
export SIGNALK_OIDC_ISSUER=https://auth.example.com
export SIGNALK_OIDC_CLIENT_ID=signalk-server
export SIGNALK_OIDC_CLIENT_SECRET=your-client-secret
| Variable | Required | Default | Description |
|---|---|---|---|
SIGNALK_OIDC_ENABLED |
Yes | false |
Enable OIDC authentication |
SIGNALK_OIDC_ISSUER |
Yes | - | OIDC provider URL (e.g., https://auth.example.com) |
SIGNALK_OIDC_CLIENT_ID |
Yes | - | Client ID registered with the provider |
SIGNALK_OIDC_CLIENT_SECRET |
Yes | - | Client secret from the provider |
SIGNALK_OIDC_SCOPE |
No | openid email profile |
OAuth scopes to request (add groups for permission mapping) |
SIGNALK_OIDC_DEFAULT_PERMISSION |
No | readonly |
Default permission for new users |
SIGNALK_OIDC_AUTO_CREATE_USERS |
No | true |
Auto-create users on first login |
SIGNALK_OIDC_ADMIN_GROUPS |
No | - | Comma-separated groups that grant admin |
SIGNALK_OIDC_READWRITE_GROUPS |
No | - | Comma-separated groups that grant readwrite |
SIGNALK_OIDC_GROUPS_ATTRIBUTE |
No | groups |
ID token claim containing groups |
SIGNALK_OIDC_PROVIDER_NAME |
No | SSO Login |
Button text on login page |
SIGNALK_OIDC_AUTO_LOGIN |
No | false |
Auto-redirect to OIDC provider |
SIGNALK_OIDC_REDIRECT_URI |
No | Auto-detected | Override the callback URL |
OIDC can also be configured in security.json:
{
"oidc": {
"enabled": true,
"issuer": "https://auth.example.com",
"clientId": "signalk-server",
"clientSecret": "your-client-secret",
"scope": "openid email profile groups",
"defaultPermission": "readonly",
"autoCreateUsers": true,
"adminGroups": ["admins", "sk-admin"],
"readwriteGroups": ["users"],
"groupsAttribute": "groups",
"providerName": "Corporate SSO",
"autoLogin": false
}
}
Note: Environment variables take precedence over security.json settings.
Signal K maps OIDC groups to permission levels in this priority order:
adminGroupsreadwriteGroupsdefaultPermission (default: readonly)# Users in "admins" or "signalk-admins" get admin access
SIGNALK_OIDC_ADMIN_GROUPS=admins,signalk-admins
# Users in "crew" or "operators" get read/write access
SIGNALK_OIDC_READWRITE_GROUPS=crew,operators
# Everyone else gets read-only access
SIGNALK_OIDC_DEFAULT_PERMISSION=readonly
By default, Signal K looks for groups in the groups claim of the ID token. Some providers use different claim names:
| Provider | Groups Claim |
|---|---|
| Keycloak | groups (requires mapper) |
| Authentik | groups |
| Auth0 | Custom (requires rule) |
| Okta | groups |
| Azure AD | groups |
| AWS Cognito | cognito:groups |
Configure the claim name:
SIGNALK_OIDC_GROUPS_ATTRIBUTE=cognito:groups
Create a new client in your realm:
signalk-serveropenid-connectconfidentialhttps://your-server:3000/signalk/v1/auth/oidc/callbackAdd a groups mapper:
groupsGroup MembershipgroupsONConfigure Signal K:
SIGNALK_OIDC_ENABLED=true
SIGNALK_OIDC_ISSUER=https://keycloak.example.com/realms/your-realm
SIGNALK_OIDC_CLIENT_ID=signalk-server
SIGNALK_OIDC_CLIENT_SECRET=<from Keycloak>
SIGNALK_OIDC_ADMIN_GROUPS=admins
Create a new OAuth2/OIDC Provider:
Signal K ServerConfidentialhttps://your-server:3000/signalk/v1/auth/oidc/callbackopenid email profile groupsCreate an Application linked to the provider
Configure Signal K:
SIGNALK_OIDC_ENABLED=true
SIGNALK_OIDC_ISSUER=https://authentik.example.com/application/o/signalk/
SIGNALK_OIDC_CLIENT_ID=<from Authentik>
SIGNALK_OIDC_CLIENT_SECRET=<from Authentik>
SIGNALK_OIDC_SCOPE=openid email profile groups
SIGNALK_OIDC_ADMIN_GROUPS=authentik Admins
Authelia is a popular open-source authentication server.
Add a client configuration to your Authelia configuration.yml:
identity_providers:
oidc:
clients:
- client_id: signalk
client_name: Signal K Server
client_secret: '$pbkdf2-sha512$310000$...' # Use authelia hash-password
public: false
authorization_policy: two_factor # or 'one_factor'
redirect_uris:
- https://your-signalk-server:3000/signalk/v1/auth/oidc/callback
scopes:
- openid
- email
- profile
- groups
userinfo_signed_response_alg: none
token_endpoint_auth_method: client_secret_post
Generate the client secret hash:
authelia crypto hash generate pbkdf2 --variant sha512
Configure Signal K:
SIGNALK_OIDC_ENABLED=true
SIGNALK_OIDC_ISSUER=https://auth.your-domain.com
SIGNALK_OIDC_CLIENT_ID=signalk
SIGNALK_OIDC_CLIENT_SECRET=your-unhashed-secret
SIGNALK_OIDC_SCOPE=openid email profile groups
SIGNALK_OIDC_DEFAULT_PERMISSION=readonly
For RP-initiated logout, add to Authelia's config:
identity_providers:
oidc:
cors:
allowed_origins_from_client_redirect_uris: true
Create a new Regular Web Application:
https://your-server:3000/signalk/v1/auth/oidc/callbackAdd a custom rule to include groups (Actions > Flows > Login):
exports.onExecutePostLogin = async (event, api) => {
const namespace = 'https://signalk.org'
if (event.authorization) {
api.idToken.setCustomClaim(
`${namespace}/groups`,
event.authorization.roles
)
}
}
Configure Signal K:
SIGNALK_OIDC_ENABLED=true
SIGNALK_OIDC_ISSUER=https://your-tenant.auth0.com/
SIGNALK_OIDC_CLIENT_ID=<from Auth0>
SIGNALK_OIDC_CLIENT_SECRET=<from Auth0>
SIGNALK_OIDC_GROUPS_ATTRIBUTE=https://signalk.org/groups
Any OIDC-compliant provider should work. Ensure:
The Issuer URL should have a discovery document at:
{issuer}/.well-known/openid-configuration
When SIGNALK_OIDC_AUTO_LOGIN=true, Signal K automatically redirects unauthenticated users to the OIDC provider instead of showing the login page.
This is useful when:
Note: Local login remains available at /admin/#/login?local=true
Signal K uses PKCE for all OIDC flows, providing protection against authorization code interception attacks. This is automatic and requires no configuration.
A cryptographically random state parameter prevents CSRF attacks during the OAuth flow. The state is stored in an encrypted, HTTP-only cookie.
ID tokens are validated by:
For production use, always run Signal K behind HTTPS. OIDC cookies are marked as Secure when accessed over HTTPS.
Cause: Signal K cannot reach the OIDC provider's discovery endpoint.
Solutions:
curl {issuer}/.well-known/openid-configurationCause: The callback URL doesn't match what's registered with the provider.
Solutions:
https://your-server:3000/signalk/v1/auth/oidc/callbackhttp://localhost:3000/... as wellCause: Groups aren't being mapped correctly.
Solutions:
groupsAttribute matches your provider's claim nameadminGroupsCause: The OIDC flow state was lost or expired.
Solutions:
Cause: The callback is failing silently.
Solutions:
GET /signalk/v1/auth/oidc/login
Initiates the OIDC login flow. Redirects to the identity provider.
Query parameters:
returnTo (optional): URL to redirect after successful loginGET /signalk/v1/auth/oidc/callback
Handles the OIDC callback from the identity provider. Not called directly by users.
GET /skServer/loginStatus
Returns the current authentication status including OIDC configuration:
{
"status": "loggedIn",
"username": "oidc-user@example.com",
"userLevel": "admin",
"oidcEnabled": true,
"oidcAutoLogin": false,
"oidcLoginUrl": "/signalk/v1/auth/oidc/login",
"oidcProviderName": "Corporate SSO"
}
GET /skServer/security/oidc
PUT /skServer/security/oidc
POST /skServer/security/oidc/test
Admin-only endpoints for managing OIDC configuration. See the OpenAPI documentation for details.