Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c18f23f
add saml support (tested with okta saml)
willesq Dec 12, 2025
d6e813c
update example
willesq Dec 12, 2025
3c17a1d
split out callback funcs
willesq Dec 12, 2025
c0ca99f
add saml tests
willesq Dec 12, 2025
442853b
update doc
willesq Dec 12, 2025
0d9e65a
add diff from hugh
willesq Dec 12, 2025
15f0614
update tests
willesq Dec 12, 2025
fb8b27d
Fix: Add missing go.sum entries for test module
willesq Dec 12, 2025
f444814
Address Copilot review comments for SAML PR
willesq Dec 12, 2025
215e737
fix import
willesq Dec 12, 2025
e75fc0f
update swagger docs
willesq Dec 12, 2025
eefb998
Address additional Copilot review comments for SAML PR
willesq Dec 12, 2025
2a6c182
update saml example
willesq Dec 12, 2025
b8300b2
Merge branch 'refs/heads/main' into saml-support
willesq Dec 15, 2025
32e042b
address cursor comment
willesq Dec 15, 2025
53d4142
Add core security infrastructure for SAML authentication
willesq Dec 15, 2025
6e0502f
Fix critical SAML authentication vulnerabilities
willesq Dec 15, 2025
067371a
Prevent session fixation and add CSRF protection to auth callbacks
willesq Dec 15, 2025
5780dcc
Add security components to Server struct
willesq Dec 15, 2025
f31c206
Fix circular import dependency in SAML provider
willesq Dec 15, 2025
ac21745
Initialize SAML security components and middleware
willesq Dec 15, 2025
659aa43
Fix SAML config parsing - add missing allow_idp_initiated and session…
willesq Dec 15, 2025
0bd13f1
Replace custom security implementations with battle-tested packages
willesq Dec 15, 2025
cb9db5e
csrf middleware integration tests
willesq Dec 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/configuration/providers/saml/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ openssl req -new -x509 -key saml.key -out saml.cert -days 365 \

1. **Register Service Provider**: Add your agent as a Service Provider in your IdP
2. **Configure Entity ID**: Use your chosen entity ID (e.g., `https://your-app.example.com/saml/metadata`)
3. **Set Assertion Consumer Service**: Configure ACS URL (e.g., `https://your-app.example.com/saml/acs`)
3. **Set Assertion Consumer Service**: Configure ACS URL (e.g., `https://your-app.example.com/api/v1/auth/callback/{provider-name}`), replacing `{provider-name}` with the key you use for this provider (e.g., `company-saml`)
4. **Upload Certificate**: Upload your public certificate to the IdP

## Example Configurations
Expand Down
222 changes: 193 additions & 29 deletions docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ const docTemplate = `{
"tags": [
"auth"
],
"summary": "Authentication callback",
"summary": "OAuth2 authentication callback",
"parameters": [
{
"type": "string",
Expand Down Expand Up @@ -137,6 +137,53 @@ const docTemplate = `{
}
}
}
},
"post": {
"description": "Handle the SAML POST callback from the provider",
"consumes": [
"application/x-www-form-urlencoded"
],
"produces": [
"application/json"
],
"tags": [
"auth"
],
"summary": "SAML authentication callback",
"parameters": [
{
"type": "string",
"description": "Provider name",
"name": "provider",
"in": "path",
"required": true
},
{
"type": "string",
"description": "SAML RelayState (SP-initiated)",
"name": "RelayState",
"in": "formData"
},
{
"type": "string",
"description": "SAML Response",
"name": "SAMLResponse",
"in": "formData",
"required": true
}
],
"responses": {
"200": {
"description": "Authentication successful"
},
"400": {
"description": "Bad request",
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
},
"/auth/logout": {
Expand Down Expand Up @@ -1149,7 +1196,7 @@ const docTemplate = `{
],
"responses": {
"200": {
"description": "Provider roles",
"description": "Provider identities",
"schema": {
"$ref": "#/definitions/models.ProviderIdentitiesResponse"
}
Expand Down Expand Up @@ -2026,6 +2073,14 @@ const docTemplate = `{
}
]
},
"thand": {
"description": "This is ONLY if the agent is running in server mode\nand you want to use https://www.thand.io hosted services",
"allOf": [
{
"$ref": "#/definitions/github_com_thand-io_agent_internal_models.ThandConfig"
}
]
},
"workflows": {
"description": "These are workflows to run for role associated workflows",
"allOf": [
Expand Down Expand Up @@ -2352,10 +2407,6 @@ const docTemplate = `{
"github_com_thand-io_agent_internal_models.LoginConfig": {
"type": "object",
"properties": {
"api_key": {
"description": "API key for authenticating with the login server",
"type": "string"
},
"base": {
"description": "Base path for login endpoint e.g. /",
"type": "string",
Expand Down Expand Up @@ -2449,6 +2500,9 @@ const docTemplate = `{
"$ref": "#/definitions/github_com_thand-io_agent_internal_models.Role"
}
]
},
"version": {
"$ref": "#/definitions/version.Version"
}
}
},
Expand Down Expand Up @@ -2476,6 +2530,23 @@ const docTemplate = `{
}
}
},
"github_com_thand-io_agent_internal_models.Resources": {
"type": "object",
"properties": {
"allow": {
"type": "array",
"items": {
"type": "string"
}
},
"deny": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"github_com_thand-io_agent_internal_models.Role": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -2531,7 +2602,7 @@ const docTemplate = `{
"description": "resource access rules, apis, files, systems etc",
"allOf": [
{
"$ref": "#/definitions/models.Resources"
"$ref": "#/definitions/github_com_thand-io_agent_internal_models.Resources"
}
]
},
Expand All @@ -2543,6 +2614,9 @@ const docTemplate = `{
}
]
},
"version": {
"$ref": "#/definitions/version.Version"
},
"workflows": {
"description": "The workflows to execute",
"type": "array",
Expand Down Expand Up @@ -2580,6 +2654,9 @@ const docTemplate = `{
"properties": {
"cors": {
"$ref": "#/definitions/github_com_thand-io_agent_internal_models.CORSConfig"
},
"saml": {
"$ref": "#/definitions/models.SAMLSecurityConfig"
}
}
},
Expand Down Expand Up @@ -2624,6 +2701,13 @@ const docTemplate = `{
"requests_per_minute": {
"type": "integer"
},
"saml_burst": {
"type": "integer"
},
"saml_rate_limit": {
"description": "SAML-specific rate limiting",
"type": "number"
},
"write_timeout": {
"$ref": "#/definitions/time.Duration"
}
Expand Down Expand Up @@ -2674,6 +2758,29 @@ const docTemplate = `{
}
}
},
"github_com_thand-io_agent_internal_models.ThandConfig": {
"type": "object",
"properties": {
"api_key": {
"description": "The API key for authenticating with Thand.io",
"type": "string"
},
"base": {
"description": "Base path for login endpoint e.g. /",
"type": "string",
"default": "/"
},
"endpoint": {
"type": "string",
"default": "https://app.thand.io/"
},
"sync": {
"description": "Whether to enable synchronization with Thand.io",
"type": "boolean",
"default": true
}
}
},
"github_com_thand-io_agent_internal_models.User": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -2724,6 +2831,9 @@ const docTemplate = `{
"name": {
"type": "string"
},
"version": {
"$ref": "#/definitions/version.Version"
},
"workflow": {
"$ref": "#/definitions/model.Workflow"
}
Expand Down Expand Up @@ -2757,7 +2867,7 @@ const docTemplate = `{
"identities": {
"type": "array",
"items": {
"type": "string"
"$ref": "#/definitions/github_com_thand-io_agent_internal_models.Identity"
}
},
"input": {
Expand Down Expand Up @@ -3754,7 +3864,21 @@ const docTemplate = `{
"identities": {
"type": "array",
"items": {
"$ref": "#/definitions/github_com_thand-io_agent_internal_models.Identity"
"type": "object",
"properties": {
"_id": {
"type": "string"
},
"_reason": {
"type": "string"
},
"_score": {
"type": "number"
},
"_source": {
"$ref": "#/definitions/github_com_thand-io_agent_internal_models.Identity"
}
}
}
},
"provider": {
Expand All @@ -3771,6 +3895,9 @@ const docTemplate = `{
"description": {
"type": "string"
},
"id": {
"type": "string"
},
"name": {
"type": "string"
},
Expand All @@ -3785,7 +3912,21 @@ const docTemplate = `{
"permissions": {
"type": "array",
"items": {
"$ref": "#/definitions/models.ProviderPermission"
"type": "object",
"properties": {
"_id": {
"type": "string"
},
"_reason": {
"type": "string"
},
"_score": {
"type": "number"
},
"_source": {
"$ref": "#/definitions/models.ProviderPermission"
}
}
}
},
"provider": {
Expand All @@ -3805,6 +3946,9 @@ const docTemplate = `{
"enabled": {
"type": "boolean"
},
"id": {
"type": "string"
},
"name": {
"type": "string"
},
Expand Down Expand Up @@ -3840,7 +3984,21 @@ const docTemplate = `{
"roles": {
"type": "array",
"items": {
"$ref": "#/definitions/models.ProviderRole"
"type": "object",
"properties": {
"_id": {
"type": "string"
},
"_reason": {
"type": "string"
},
"_score": {
"type": "number"
},
"_source": {
"$ref": "#/definitions/models.ProviderRole"
}
}
}
},
"version": {
Expand All @@ -3862,23 +4020,6 @@ const docTemplate = `{
}
}
},
"models.Resources": {
"type": "object",
"properties": {
"allow": {
"type": "array",
"items": {
"type": "string"
}
},
"deny": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"models.RoleResponse": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -3934,7 +4075,7 @@ const docTemplate = `{
"description": "resource access rules, apis, files, systems etc",
"allOf": [
{
"$ref": "#/definitions/models.Resources"
"$ref": "#/definitions/github_com_thand-io_agent_internal_models.Resources"
}
]
},
Expand All @@ -3946,6 +4087,9 @@ const docTemplate = `{
}
]
},
"version": {
"$ref": "#/definitions/version.Version"
},
"workflows": {
"description": "The workflows to execute",
"type": "array",
Expand All @@ -3969,6 +4113,23 @@ const docTemplate = `{
}
}
},
"models.SAMLSecurityConfig": {
"type": "object",
"properties": {
"assertion_cache_cleanup": {
"$ref": "#/definitions/time.Duration"
},
"assertion_cache_ttl": {
"$ref": "#/definitions/time.Duration"
},
"csrf_enabled": {
"type": "boolean"
},
"session_duration": {
"$ref": "#/definitions/time.Duration"
}
}
},
"models.ServiceConfig": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -4105,6 +4266,9 @@ const docTemplate = `{
"Minute",
"Hour"
]
},
"version.Version": {
"type": "object"
}
},
"securityDefinitions": {
Expand Down
Loading
Loading