signalk-server
Version:
An implementation of a [Signal K](http://signalk.org) server for boats.
654 lines (653 loc) • 27.5 kB
JSON
{
"openapi": "3.0.0",
"info": {
"version": "1.0.0",
"title": "Signal K Security API",
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
}
},
"externalDocs": {
"url": "http://signalk.org/specification/",
"description": "Signal K specification."
},
"servers": [
{
"url": "/signalk/v1"
}
],
"tags": [
{
"name": "authentication",
"description": "User authentication"
},
{
"name": "access",
"description": "Device access"
},
{
"name": "oidc",
"description": "OpenID Connect (OIDC) configuration"
}
],
"components": {
"schemas": {
"IsoTime": {
"type": "string",
"pattern": "^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2}(?:\\.\\d*)?)((-(\\d{2}):(\\d{2})|Z)?)$",
"example": "2022-04-22T05:02:56.484Z"
},
"RequestState": {
"type": "string",
"enum": ["PENDING", "FAILED", "COMPLETED"]
},
"OIDCPermission": {
"type": "string",
"enum": ["readonly", "readwrite", "admin"],
"description": "Signal K permission level"
},
"OIDCConfigResponse": {
"type": "object",
"description": "OIDC configuration (secrets redacted)",
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether OIDC authentication is enabled"
},
"issuer": {
"type": "string",
"description": "OIDC provider issuer URL",
"example": "https://auth.example.com"
},
"clientId": {
"type": "string",
"description": "OAuth client ID"
},
"clientSecret": {
"type": "string",
"description": "Always empty (redacted for security)"
},
"clientSecretSet": {
"type": "boolean",
"description": "Whether a client secret has been configured"
},
"redirectUri": {
"type": "string",
"description": "OAuth redirect URI (optional, auto-generated if not set)"
},
"scope": {
"type": "string",
"description": "OAuth scopes to request",
"example": "openid email profile"
},
"defaultPermission": {
"$ref": "#/components/schemas/OIDCPermission"
},
"autoCreateUsers": {
"type": "boolean",
"description": "Automatically create users on first OIDC login"
},
"adminGroups": {
"type": "array",
"items": { "type": "string" },
"description": "Groups that grant admin permission",
"example": ["admins", "sk-admin"]
},
"readwriteGroups": {
"type": "array",
"items": { "type": "string" },
"description": "Groups that grant read/write permission",
"example": ["users", "operators"]
},
"groupsAttribute": {
"type": "string",
"description": "ID token claim containing user groups",
"example": "groups"
},
"providerName": {
"type": "string",
"description": "Display name shown on login button",
"example": "SSO Login"
},
"autoLogin": {
"type": "boolean",
"description": "Automatically redirect to OIDC provider when not authenticated"
},
"envOverrides": {
"type": "object",
"description": "Fields that are overridden by environment variables",
"additionalProperties": { "type": "boolean" }
}
}
},
"OIDCConfigRequest": {
"type": "object",
"description": "OIDC configuration update request",
"properties": {
"enabled": {
"type": "boolean"
},
"issuer": {
"type": "string",
"example": "https://auth.example.com"
},
"clientId": {
"type": "string"
},
"clientSecret": {
"type": "string",
"description": "Leave empty to keep existing secret"
},
"scope": {
"type": "string",
"example": "openid email profile"
},
"defaultPermission": {
"$ref": "#/components/schemas/OIDCPermission"
},
"autoCreateUsers": {
"type": "boolean"
},
"adminGroups": {
"oneOf": [
{ "type": "string", "description": "Comma-separated list" },
{ "type": "array", "items": { "type": "string" } }
]
},
"readwriteGroups": {
"oneOf": [
{ "type": "string", "description": "Comma-separated list" },
{ "type": "array", "items": { "type": "string" } }
]
},
"groupsAttribute": {
"type": "string"
},
"providerName": {
"type": "string"
},
"autoLogin": {
"type": "boolean"
}
}
},
"OIDCTestRequest": {
"type": "object",
"required": ["issuer"],
"properties": {
"issuer": {
"type": "string",
"description": "OIDC provider issuer URL to test",
"example": "https://auth.example.com"
}
}
},
"OIDCTestResponse": {
"type": "object",
"description": "OIDC connection test result",
"properties": {
"success": {
"type": "boolean"
},
"issuer": {
"type": "string",
"description": "Issuer from discovery document"
},
"authorization_endpoint": {
"type": "string",
"description": "OAuth authorization endpoint"
},
"token_endpoint": {
"type": "string",
"description": "OAuth token endpoint"
},
"userinfo_endpoint": {
"type": "string",
"description": "OIDC userinfo endpoint"
},
"jwks_uri": {
"type": "string",
"description": "JSON Web Key Set URI"
}
}
}
},
"responses": {
"200Ok": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": ["COMPLETED"]
},
"statusCode": {
"type": "number",
"enum": [200]
}
},
"required": ["state", "statusCode"]
}
}
}
},
"ErrorResponse": {
"description": "Failed operation",
"content": {
"application/json": {
"schema": {
"type": "object",
"description": "Request error response",
"properties": {
"state": {
"type": "string",
"enum": ["FAILED"]
},
"statusCode": {
"type": "number",
"enum": [404]
},
"message": {
"type": "string"
}
},
"required": ["state", "statusCode", "message"]
}
}
}
},
"AccessRequestResponse": {
"description": "Request status",
"content": {
"application/json": {
"schema": {
"description": "Request response",
"type": "object",
"required": ["state"],
"properties": {
"state": {
"$ref": "#/components/schemas/RequestState",
"default": "PENDING",
"example": "PENDING",
"description": "Status of request."
},
"href": {
"type": "string",
"example": "/signalk/v1/requests/358b5f32-76bf-4b33-8b23-10a330827185",
"description": "Path where the status of the request can be checked."
}
}
}
}
}
},
"RequestStatusResponse": {
"description": "Request status",
"content": {
"application/json": {
"schema": {
"description": "Request response",
"type": "object",
"required": ["state"],
"properties": {
"state": {
"$ref": "#/components/schemas/RequestState",
"example": "COMPLETED",
"default": "COMPLETED",
"description": "Status of request."
},
"statusCode": {
"type": "number",
"example": 200,
"description": "Response status code."
},
"ip": {
"type": "string",
"example": "192.168.1.77",
"description": "IP address of the original access request."
},
"accessRequest": {
"type": "object",
"required": ["permission", "token"],
"description": "Access request result.",
"properties": {
"permission": {
"enum": ["DENIED", "APPROVED"],
"example": "APPROVED"
},
"token": {
"type": "string",
"description": "Authentication token to be supplied with future requests."
},
"expirationTime": {
"$ref": "#/components/schemas/IsoTime",
"description": "Token expiration time."
}
}
}
}
}
}
}
}
},
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
},
"cookieAuth": {
"type": "apiKey",
"in": "cookie",
"name": "JAUTHENTICATION"
}
}
},
"paths": {
"/access/requests": {
"post": {
"tags": ["access"],
"summary": "Create a device access request.",
"description": "Endpoint to create (device) access requests. The response contains the href to poll for the status of the request.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["clientId", "description"],
"properties": {
"clientId": {
"type": "string",
"description": "Client identifier.",
"example": "1234-45653-343453"
},
"description": {
"type": "string",
"description": "Description of device.",
"example": "humidity sensor"
}
}
}
}
}
},
"responses": {
"200": {
"$ref": "#/components/responses/AccessRequestResponse"
},
"default": {
"$ref": "#/components/responses/ErrorResponse"
}
}
}
},
"/requests/{id}": {
"parameters": [
{
"name": "id",
"in": "path",
"description": "request id",
"required": true,
"schema": {
"type": "string"
}
}
],
"get": {
"tags": ["access"],
"summary": "Check device access status.",
"description": "Returns the status of the supplied request id.",
"responses": {
"200": {
"$ref": "#/components/responses/RequestStatusResponse"
},
"default": {
"$ref": "#/components/responses/ErrorResponse"
}
}
}
},
"/auth/login": {
"post": {
"tags": ["authentication"],
"summary": "Authenticate user.",
"description": "Authenticate to server using username and password.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["username", "password"],
"properties": {
"username": {
"type": "string",
"description": "User to authenticate"
},
"password": {
"type": "string",
"description": "Password for supplied username."
}
}
}
}
}
},
"responses": {
"200": {
"description": "Successful Authentication response.",
"content": {
"application/json": {
"schema": {
"description": "Login success result",
"type": "object",
"required": ["token"],
"properties": {
"token": {
"type": "string",
"description": "Authentication token to be supplied with future requests."
},
"timeToLive": {
"type": "number",
"description": "Token validity time (seconds)."
}
}
}
}
}
},
"default": {
"$ref": "#/components/responses/ErrorResponse"
}
}
}
},
"/auth/logout": {
"put": {
"tags": ["authentication"],
"summary": "Log out user.",
"description": "Log out the user with the token supplied in the request header.",
"security": ["cookieAuth", "bearerAuth"],
"responses": {
"200": {
"$ref": "#/components/responses/200Ok"
},
"default": {
"$ref": "#/components/responses/ErrorResponse"
}
}
}
},
"/security/oidc": {
"get": {
"tags": ["oidc"],
"summary": "Get OIDC configuration.",
"description": "Returns the current OIDC configuration with secrets redacted. Includes indicators for fields overridden by environment variables.",
"security": [{ "cookieAuth": [] }, { "bearerAuth": [] }],
"responses": {
"200": {
"description": "OIDC configuration",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OIDCConfigResponse"
}
}
}
},
"401": {
"description": "Unauthorized - admin access required",
"content": {
"application/json": {
"schema": {
"type": "string",
"example": "Security config not allowed"
}
}
}
}
}
},
"put": {
"tags": ["oidc"],
"summary": "Update OIDC configuration.",
"description": "Updates the OIDC configuration. Fields set via environment variables cannot be overridden. Leave clientSecret empty to preserve the existing secret.",
"security": [{ "cookieAuth": [] }, { "bearerAuth": [] }],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OIDCConfigRequest"
}
}
}
},
"responses": {
"200": {
"description": "Configuration saved successfully",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "OIDC configuration saved"
}
}
}
}
}
},
"400": {
"description": "Invalid configuration",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Invalid issuer URL"
}
}
}
}
}
},
"401": {
"description": "Unauthorized - admin access required"
},
"500": {
"description": "Failed to save configuration",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Unable to save OIDC configuration"
}
}
}
}
}
}
}
}
},
"/security/oidc/test": {
"post": {
"tags": ["oidc"],
"summary": "Test OIDC connection.",
"description": "Tests connectivity to an OIDC provider by fetching its discovery document. Returns the provider's endpoints if successful.",
"security": [{ "cookieAuth": [] }, { "bearerAuth": [] }],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OIDCTestRequest"
}
}
}
},
"responses": {
"200": {
"description": "Connection successful",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OIDCTestResponse"
}
}
}
},
"400": {
"description": "Invalid request",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Issuer URL is required"
}
}
}
}
}
},
"401": {
"description": "Unauthorized - admin access required"
},
"502": {
"description": "Failed to connect to OIDC provider",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Failed to fetch OIDC discovery document"
}
}
}
}
}
}
}
}
}
}
}