https://github.com/solarssk/ssf-transmitter
Standalone OpenID Shared Signals Framework transmitter for self-hosted Authentik deployments.
https://github.com/solarssk/ssf-transmitter
authentik caep docker fastapi openid risc security-events self-hosted shared-signals-framework ssf
Last synced: about 7 hours ago
JSON representation
Standalone OpenID Shared Signals Framework transmitter for self-hosted Authentik deployments.
- Host: GitHub
- URL: https://github.com/solarssk/ssf-transmitter
- Owner: solarssk
- License: mit
- Created: 2026-05-27T19:55:42.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-06-20T09:46:16.000Z (11 days ago)
- Last Synced: 2026-06-20T11:23:59.958Z (11 days ago)
- Topics: authentik, caep, docker, fastapi, openid, risc, security-events, self-hosted, shared-signals-framework, ssf
- Language: Python
- Homepage: https://github.com/solarssk/ssf-transmitter
- Size: 523 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
# SSF Transmitter
[](https://github.com/solarssk/ssf-transmitter/actions/workflows/ci.yml)
Standalone service that sits next to Authentik and forwards user security events (logout, password change) to receivers implementing the [OpenID Shared Signals Framework](https://openid.net/specs/openid-sharedsignals-framework-1_0.html). One container supports one active SSF stream — registering a new stream replaces the existing one. Multi-stream support (fan-out to multiple receivers) is planned for v1.1. Primary receiver: Apple Business Manager CAEP.
Events are signed as RS256 JWTs (Security Event Tokens) and pushed over HTTPS. No admin panel — all configuration is environment variables.
**Current release:** [v0.5.10 — Stream recovery hardening](https://github.com/solarssk/ssf-transmitter/releases/tag/v0.5.10)
## Features
- SSF discovery and JWKS endpoints
- Stream management API (create / read / update / delete)
- Authentik webhook receiver with Bearer or HMAC-SHA256 authentication
- CAEP event mapping for logout and password change
- RS256-signed SET push delivery with SSRF and DNS rebinding protection
- Receiver hostname allowlist, in-app rate limiting, HTTP security headers (v0.5.9+)
- Fernet encryption for receiver tokens at rest (v0.5.9+)
- PII masking in logs by default
- Apple Business Manager SCIM user sync (optional)
- Startup preflight checks with ✅/⚠️/❌ output per item
- Multi-architecture Docker image (`linux/amd64`, `linux/arm64`)
## Quick start
1. Copy [`.env.example`](.env.example) to `stack.env` and set:
- `SSF_ISSUER`, `SSF_BASE_URL` (`SSF_ISSUER` should normally be the same URL as `SSF_BASE_URL`)
- `SSF_MANAGEMENT_TOKEN`, `SSF_WEBHOOK_TOKEN`
- `SSF_FORWARDED_ALLOW_IPS` (your reverse proxy subnet if behind NPM/Caddy)
2. Add the service to Docker Compose — see [docs/Deployment.md](docs/Deployment.md) or [Synology guide](docs/synology-authentik-compose.md)
3. Register the stream with your receiver using the SSF Config URL below
A **stream** is the receiver configuration stored in SQLite: receiver URL, bearer token, requested events, and current status. If Apple Business Manager is already connected, you already have a stream.
## Upgrading
**Already running with Apple Business Manager?** See [docs/Upgrading.md](docs/Upgrading.md#v0510--stream-recovery-hardening-from-058-or-earlier):
- Bump image to `0.5.10`
- Set `SSF_FORWARDED_ALLOW_IPS` behind reverse proxy
- Keep `SSF_WEBHOOK_AUTH_MODE=hmac` explicitly if your Authentik webhook still uses legacy HMAC
- Do **not** add `SSF_TOKEN_ENCRYPTION_KEY` unless re-registering the stream
## Public endpoints
| Endpoint | URL |
|---|---|
| Service root | `https://idp.example.com/shared-signals/` |
| SSF Config | `https://idp.example.com/shared-signals/.well-known/ssf-configuration` |
| JWKS | `https://idp.example.com/shared-signals/jwks.json` |
| Stream management | `https://idp.example.com/shared-signals/ssf/streams` |
| Status | `https://idp.example.com/shared-signals/ssf/status` |
`/docs` and `/openapi.json` are off by default — set `SSF_ENABLE_OPENAPI=true` only in dev or a trusted LAN.
Replace `idp.example.com` with your IdP hostname and `/shared-signals` with your `SSF_ROOT_PATH`.
## Documentation
| Topic | Location |
|---|---|
| **Documentation index** | [docs/README.md](docs/README.md) |
| Deployment | [docs/Deployment.md](docs/Deployment.md) |
| Synology + Authentik | [docs/synology-authentik-compose.md](docs/synology-authentik-compose.md) |
| Environment variables | [docs/Configuration.md](docs/Configuration.md) |
| Upgrading (v0.5.9+) | [docs/Upgrading.md](docs/Upgrading.md) |
| Event mapping | [docs/Event-Mapping.md](docs/Event-Mapping.md) |
| Keys and rotation | [docs/Key-Management.md](docs/Key-Management.md) |
| Apple SCIM sync | [docs/Apple-SCIM-Sync.md](docs/Apple-SCIM-Sync.md) |
| Security checklist | [docs/Security-Notes.md](docs/Security-Notes.md) |
| Troubleshooting | [docs/Troubleshooting.md](docs/Troubleshooting.md) |
| API reference | [docs/API.md](docs/API.md) |
| Threat model | [SECURITY.md](SECURITY.md) |
| Changelog | [CHANGELOG.md](CHANGELOG.md) |
Wiki pages mirror `docs/` — sync from the repo when updating [GitHub Wiki](https://github.com/solarssk/ssf-transmitter/wiki).
## Apple SCIM group filtering
Set `APPLE_SCIM_GROUP_ID` to an Authentik group UUID to sync only members of a dedicated Apple group. See [docs/Apple-SCIM-Sync.md](docs/Apple-SCIM-Sync.md).
## Development
Requires **Python 3.14** (see `.python-version`; matches CI and the Docker image).
```bash
python3.14 -m venv .venv && . .venv/bin/activate
pip install -r requirements-dev.txt
ruff check .
pytest
```
GitHub Actions runs linting, tests, dependency checks, and a Docker image build on every push and pull request.