Integrations¶
Overview¶
Integrations allow JustIAM to react to identity events in real time. When a trigger event fires (e.g. a user is created), JustIAM evaluates optional filter conditions and then executes one or more actions such as calling a webhook, posting a Slack message, writing a log entry, or triggering a scheduled task.
Concepts¶
| Concept | Description |
|---|---|
| Trigger | One or more event types that activate the integration |
| Condition | Optional filter applied to the event payload — all conditions must match |
| Action | What to do when the integration fires (HTTP, Slack, Log, Trigger Task) |
| Delivery | A record of one execution attempt with status and response |
Supported event types¶
| Event | Description |
|---|---|
user.created |
A new user account was created |
user.updated |
A user's profile was changed |
user.deleted |
A user account was deleted |
user.activated |
A user account was re-activated |
user.deactivated |
A user account was deactivated |
group.created |
A group was created |
group.updated |
A group was updated |
group.deleted |
A group was deleted |
group.member_added |
A user was added to a group |
group.member_removed |
A user was removed from a group |
application.created |
An application was created |
application.updated |
An application was updated |
application.deleted |
An application was deleted |
app_mapping.created |
An app mapping entry was created |
app_mapping.updated |
An app mapping entry was updated |
app_mapping.deleted |
An app mapping entry was deleted |
login.success |
A successful login occurred |
login.failed |
A failed login attempt occurred |
mfa.enrolled |
A user enrolled a new MFA method |
mfa.unenrolled |
A user removed an MFA method |
access_request.submitted |
An access request was submitted |
access_request.approved |
An access request was approved |
access_request.denied |
An access request was denied |
access_request.expired |
An access request expired |
access_request.revoked |
An approved access grant was revoked |
access_request.escalated |
An access request was escalated |
proxy.session_ended |
A user signed out of a proxy-protected application |
event_action.delivery_failed |
A delivery exhausted all retry attempts (terminal failure) — see Failure notifications |
task.run_failed |
A scheduled task or custom script finished with an error — see Failure notifications |
Actions¶
HTTP¶
Sends an HTTP request to a URL.
| Field | Description |
|---|---|
method |
HTTP method (GET, POST, PUT, PATCH, DELETE) |
url |
Target URL (supports Go template variables) |
headers |
Key/value map of request headers |
body |
Request body (supports Go template variables) |
timeout_secs |
Request timeout in seconds (default 10) |
max_retries |
Number of retry attempts on failure (0 = no retries) |
auth.type |
Authentication: none, bearer, or basic |
auth.token |
Bearer token (when auth.type is bearer) |
auth.username |
Username (when auth.type is basic) |
auth.password |
Password (when auth.type is basic) |
Slack¶
Posts a message to a Slack channel via an Incoming Webhook.
| Field | Description |
|---|---|
webhook_url |
Slack Incoming Webhook URL |
message |
Message text (supports Go template variables) |
Log¶
Appends an entry to the server log (useful for debugging).
| Field | Description |
|---|---|
message |
Message text (supports Go template variables) |
level |
Log level: info (default), warn, error |
Trigger Task¶
Immediately runs a scheduled task (script or built-in) when the integration fires.
| Field | Description |
|---|---|
task_id |
UUID of the scheduled task to run (required) |
Template variables¶
All body, message, and url fields support Go template syntax. Available variables:
| Variable | Description |
|---|---|
{{.EventType}} |
The event type that fired (e.g. user.created) |
{{.ActorID}} |
UUID of the user who triggered the event |
{{.ActorEmail}} |
Email of the user who triggered the event |
{{.IPAddress}} |
IP address of the request |
{{.FiredAt}} |
RFC3339 timestamp of the event |
{{.Data.user_id}} |
UUID of the affected user |
{{.Data.user_email}} |
Email of the affected user |
{{.Data.user_name}} |
Username of the affected user |
{{.Data.group_id}} |
UUID of the affected group |
{{.Data.group_name}} |
Name of the affected group |
{{.Data.app_id}} |
UUID of the affected application |
{{.Data.app_name}} |
Name of the affected application |
{{.Data.resource_type}} |
Type of the affected resource |
Conditions¶
Conditions are optional filters. All conditions must match for the integration to fire.
| Operator | Description |
|---|---|
eq |
Field equals value |
neq |
Field does not equal value |
contains |
Field contains value (string) |
starts_with |
Field starts with value |
ends_with |
Field ends with value |
is_true |
Field is truthy |
is_false |
Field is falsy |
Example: Only fire when a user in @example.com is created:
Delivery history¶
Every time an integration fires a delivery record is created. You can view delivery history from the Integrations page in the admin UI or via the API:
Delivery statuses:
| Status | Description |
|---|---|
pending |
Queued, not yet attempted |
running |
Currently being processed |
success |
Completed successfully |
failed |
All attempts exhausted |
Failed deliveries can be manually retried from the delivery list or via:
Failure notifications¶
Both event_action.delivery_failed and task.run_failed fire automatically when something goes wrong. You can add field conditions to scope notifications to specific integrations or tasks — every payload field is available as a condition.
event_action.delivery_failed¶
Fires when an integration delivery exhausts all retry attempts (terminal failure).
Payload fields (usable as field conditions or template variables):
| Field | Description |
|---|---|
integration_id |
UUID of the failing integration |
integration_name |
Name of the failing integration |
event_type |
The original event that triggered the failed delivery |
delivery_id |
UUID of the failed delivery row |
attempt_count |
Number of attempts made |
error |
Last response / error message |
Useful field conditions:
| Goal | Field | Operator | Value |
|---|---|---|---|
| Only for a specific integration | integration_name |
eq |
LDAP Sync |
| Only for login-related failures | event_type |
starts_with |
login. |
| Only after many attempts | attempt_count |
eq |
5 |
| Only when error matches a pattern | error |
contains |
timeout |
Example Slack message template:
Integration failed: *{{.integration_name}}*
Original event: {{.event_type}}
Delivery: {{.delivery_id}} ({{.attempt_count}} attempts)
Error: {{.error}}
task.run_failed¶
Fires when a scheduled task or custom script finishes with status = error. This covers both built-in tasks and user-defined scripts.
Payload fields (usable as field conditions or template variables):
| Field | Description |
|---|---|
task_id |
UUID of the failed task |
task_name |
Name of the failed task |
task_type |
Type: script, github_team_sync, etc. |
triggered_by |
How it was triggered: cron, manual, integration:<name> |
output |
Captured output / error text |
run_id |
UUID of the specific task run record |
Useful field conditions:
| Goal | Field | Operator | Value |
|---|---|---|---|
| Only for a specific task | task_name |
eq |
User Sync |
| Only for script tasks | task_type |
eq |
script |
| Only for cron-triggered failures | triggered_by |
eq |
cron |
| Only when error contains a keyword | output |
contains |
permission denied |
Example Slack message template:
Task failed: *{{.task_name}}* (type: {{.task_type}})
Triggered by: {{.triggered_by}}
Output: {{.output}}
Loop protection¶
Both failure events have structural loop protection — no configuration needed:
event_action.delivery_failed: If a failure-notification integration itself fails (e.g. Slack is down), its delivery will NOT re-fireevent_action.delivery_failed.task.run_failed: If a task was triggered by atask.run_failednotification (i.e. it is the failure handler and it too failed), it will NOT re-dispatchtask.run_failed.
In both cases the failure is silently logged and recorded in delivery/run history — recoverable manually via retry.
proxy.session_ended¶
Fires when a user signs out of a proxy-protected application (the proxy binary calls the session-end endpoint during sign-out).
Payload fields (usable as field conditions or template variables):
| Field | Description |
|---|---|
hostname |
FQDN of the proxy-protected application, e.g. app.example.com |
provider_id |
UUID of the proxy provider configuration |
user_email |
Email address of the user who signed out |
user_sub |
OIDC sub claim (user UUID in JustIAM) |
Useful field conditions:
| Goal | Field | Operator | Value |
|---|---|---|---|
| Only for a specific app | hostname |
eq |
app.example.com |
| Only for a specific provider | provider_id |
eq |
<uuid> |
| Only for a specific email domain | user_email |
ends_with |
@contractor.example.com |
Example: deactivate contractor accounts on sign-out
- Create a Script task using
proxy_session_ended.gofromyaegi/scripts/. - Set task config key
deactivate_on_session_end = "true"and optionallyallowed_email_domain = "contractor.example.com". - Create an Integration: trigger
proxy.session_ended→ action Trigger Task → select the task above.
Example Slack template:
Creating an integration (UI)¶
- Navigate to Integrations in the sidebar.
- Click New Integration.
- Fill in a name and optional description.
- Select one or more Triggers.
- Optionally add Conditions to filter events.
- Add one or more Actions (HTTP, Slack, Log, or Trigger Task).
- Click Save.
API¶
| Method | Path | Description |
|---|---|---|
GET |
/integrations |
List integrations (paginated) |
POST |
/integrations |
Create an integration |
GET |
/integrations/{id} |
Get a single integration |
PUT |
/integrations/{id} |
Update an integration |
DELETE |
/integrations/{id} |
Delete an integration |
GET |
/integrations/event-types |
List all supported event types |
GET |
/integrations/{id}/deliveries |
List delivery history |
POST |
/integrations/{id}/deliveries/{deliveryId}/retry |
Retry a failed delivery |
All endpoints require admin privileges (Authorization: Bearer <token>).
Script examples for event-triggered tasks¶
When using the trigger_task action type, you can run scripts in response to events. See Script Examples for ready-to-use scripts:
- Access request event logger — log all access request lifecycle events
- Proxy session ended handler — react to proxy session termination
- User created → directory sync — sync new users to an external directory
- Login failed → Slack alert — send Slack notifications on login failures
- User created → auto-assign groups — auto-assign groups by email domain