A weaponized Single Sign-On (SSO) Identity Provider (IdP) for security testing of OIDC and SAML 2.0 Service Providers, also supporting SCIM protocol.
Why maSSO?
- Operates as a fully spec-compliant OIDC IdP and SAML 2.0 IdP that target SPs trust
- Includes an optional SCIM client for testing, also supports pulling users from target Service Providers
- Lets you set each endpoint independently to pass-through, mock, intercept, or intercept-before-sign mode from a local dashboard
- OIDC & SAML signing intercepts: For OIDC, capture the upstream-issued
id_token, edit the JSON, and re-sign with maSSO's RSA key. For SAML, capture unsigned assertion XML, edit it in the structured form and raw XML panes, then sign the edited version - Supports Cloudflare Quick Tunnels (
--cloudflared) for zero-config public exposure
Built on zitadel/oidc (OIDC IdP) and mcguinness/node-samlp (SAML IdP).
No local Go or Node.js is required. Use Docker Compose with the oidc or saml profile, map the IdP and (localhost-only) dashboard ports. Cloudflare Quick Tunnel in the container is opt-in (MASSO_CLOUDFLARED=1), like ./masso --cloudflared locally. All commands, environment variable tables, volume layout, and how the entrypoint passes through flags are in USE_AS_DOCKER.md.
Prerequisites
| Requirement | Notes |
|---|---|
| Go | 1.25 or later |
| Node.js | 18+ (SAML mode only; saml-engine dependencies) |
| cloudflared | Optional for local go build / ./masso --cloudflared - install from Cloudflare. For in-container cloudflared, see USE_AS_DOCKER.md. |
Install cloudflared when you need it:
- Docs (all platforms): Install cloudflared (pick your OS; includes Linux
.deb/.rpmand direct binaries). - macOS (Homebrew):
brew install cloudflared - Verify:
cloudflared --version
Then run maSSO with e.g. ./masso oidc --cloudflared (see Tunneling in ADVANCED_USAGE.md for Quick Tunnel and manual issuer).
git clone https://github.com/doyensec/maSSO
cd masso
go build -o masso .
cd saml-engine && npm install && cd .../masso <oidc|saml> [flags]The IdP and dashboard run on separate ports. Only the IdP port (--port) should be exposed to the internet. The dashboard (--dash-port) must remain local.
# OIDC - point at a real SP callback
./masso oidc --redirect-uri https://app.example.com/auth/callback
# SAML - run against a real SP
./masso saml --acs https://app.example.com/saml/acs --audience https://app.example.com
# OIDC with Cloudflare tunnel (auto-detect public URL)
./masso oidc --cloudflared
# SAML with Cloudflare tunnel
./masso saml --cloudflared --acs https://sp.com/acs --audience https://sp.com
# OIDC with a manually-managed tunnel
./masso oidc --issuer https://my-tunnel.example.com/./masso oidc [flags]| Flag | Default | Description |
|---|---|---|
--port |
8081 |
IdP listen port (expose via tunnel) |
--dash-port |
8082 |
Dashboard port (keep local) |
--issuer |
http://localhost:<port>/ |
Public issuer URL - required for remote SPs |
--client-id |
web |
OIDC Client ID |
--client-secret |
secret |
OIDC Client Secret |
--redirect-uri |
http://localhost:9999/callback |
SP callback URL - exact, glob, or re: regex (see below) |
--any-redirect |
false |
Allow any callback URL (*) without shell-escaping * |
--db |
data.db |
SQLite database path |
--cloudflared |
false |
Auto-tunnel via Cloudflare and use its URL as issuer |
Configure your SP with:
| Field | Value |
|---|---|
| Discovery URL | <issuer>.well-known/openid-configuration |
| Client ID | web (or --client-id) |
| Client Secret | secret (or --client-secret) |
| Scopes | openid profile email |
| Grant Type | authorization_code |
| Token Auth Method | client_secret_basic |
| Syntax | Mode | Example |
|---|---|---|
| Plain string | Exact | https://app.example.com/callback |
Contains * or ? |
Glob (doublestar) | https://app.example.com/* |
re: prefix |
Go regex | re:https://app\.example\.com/(callback|auth/cb) |
Always quote glob and regex values to prevent shell expansion. Use
--any-redirectinstead of--redirect-uri '*'when you need a catch-all.
Persisted client config: --client-id, --client-secret, --redirect-uri, and --any-redirect are written back to SQLite on each run, so a tunnel run and a follow-up run stay consistent without deleting data.db.
./masso saml [flags]| Flag | Default | Description |
|---|---|---|
--port |
8081 |
IdP listen port (expose via tunnel) |
--dash-port |
8082 |
Dashboard port (keep local) |
--issuer |
http://localhost:<port>/ |
Public issuer URL |
--acs |
(empty) | SP ACS URL - dynamic from AuthnRequest if omitted |
--audience |
(empty) | SP Entity ID / Audience |
--node-port |
7070 |
Internal port for the Node.js SAML engine |
--db |
data.db |
SQLite database path |
--cloudflared |
false |
Auto-tunnel via Cloudflare and use its URL as issuer |
Configure your SP with:
| Field | Value |
|---|---|
| IdP Metadata URL | <issuer>metadata |
| IdP SSO URL | <issuer>saml/sso |
| IdP Entity ID | <issuer> |
| IdP Certificate | saml-engine/idp-public-cert.pem |
| NameID Format | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress |
| Binding | urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST |
maSSO acts as a SCIM client to push users to or pull users from a target SP.
./masso [oidc|saml] --scim-url https://sp.example.com/scim/v2 [flags]| Flag | Default | Description |
|---|---|---|
--scim-url |
(empty) | Target SP SCIM base URL (enables SCIM tab in dashboard) |
--scim-token |
(empty) | API token |
--scim-token-type |
Bearer |
Auth scheme: Bearer, Basic, or custom header name |
--scim-tls-skip-verify |
false |
Skip TLS verification for SCIM requests |
ADVANCED_USAGE.md - extra details on tunneling/issuer, interception modes, and endpoint tables.
USE_AS_DOCKER.md - Docker and Docker Compose (profiles, ports, environment variables, in-container Quick Tunnel).
maSSO thrives on community contributions. Whether you are a developer, researcher, or bug hunter, your feedback and pull requests help improve the project for everyone. Please use the GitHub issue tracker for reports and discussion.
This project is developed with support from Doyensec.

