NanoIDP
Test real OAuth2/OIDC, SAML 2.0 and MCP authorization flows locally,
without running a production IAM stack.
Design principles, non-goals and direction live in VISION.md.
Need a real OAuth2/OIDC or SAML counterpart for an integration test, a demo or an agent, without standing up Keycloak or provisioning a cloud tenant?
NanoIDP is a test identity provider: a real, spec-honest OAuth2/OIDC and
SAML 2.0 provider built for testing, which you install with pip,
configure with two YAML files and throw away when the test is done. It is
not a mock: it implements the protocols instead of imitating their
answers, and what it advertises is what it implements, so your client is
tested against the specification and not against a mock's guesses. It is
not a production IdP either: it never serves real users.
Quick Start
pip install nanoidp
python -m nanoidp init # create ./config (users, settings, keys)
python -m nanoidp # serve on http://localhost:8000
Get a first token:
curl -X POST 'http://localhost:8000/token' \
-u 'demo-client:demo-secret' \
-d 'grant_type=client_credentials'
The admin UI runs at http://localhost:8000. Prefer Docker?
docker run --rm -p 8000:8000 \
-v $(pwd)/config:/app/config \
ghcr.io/cdelmonte-zg/nanoidp:latest
From here: the Quickstart walks through users, clients and the Authorization Code + PKCE flow; Requesting tokens has a copy-paste request for every grant; Install covers the wizard, custom config paths and docker-compose.
What you can test against it
- OAuth2 / OIDC: Authorization Code with PKCE, Client Credentials,
Refresh Token with rotation, Device Authorization (RFC 8628) and the
Password grant for legacy clients; introspection (RFC 7662), revocation
(RFC 7009) and RP-initiated logout; per-client scopes and audiences,
claims mapping and authority prefixes; an opt-in
oauth21profile that enforces draft OAuth 2.1 strictness. - Clients that were not declared in advance: public clients with
mandatory PKCE, resource indicators (RFC 8707),
issin the authorization response (RFC 9207) and authorization server metadata (RFC 8414); opt-in dynamic client registration (RFC 7591, with the read and delete of RFC 7592) and opt-in client ID metadata documents, where theclient_idis anhttpsURL the server fetches under an explicit host allowlist. - SAML 2.0: SSO and AttributeQuery with signed assertions, and opt-in verification of signed AuthnRequests.
- Login experience: a passwordless persona login for demos, two-step
login, and a declarative TOTP second factor for testing a client against
an MFA login (asked on
/authorize,/login, SAML SSO and the device page). - Agents and MCP: an MCP server that lets an agent create users and clients, mint tokens and read the audit log, with a read-only mode; MCP tools and the HTTP API expose the same capabilities.
- Disposable test identities: a CI job creates users and clients on a
running instance over
/api/runtime, uses them in every flow and removes them, without touching the YAML files; one that should stay is promoted into the configuration explicitly. - Running it: two schema-versioned YAML files with validation, security profiles, an audit log, hooks and plugins for wiring the deploy in, a Docker image and a Helm chart.
Every item above has its reference page in the documentation below.
Documentation
The full documentation lives at https://cdelmonte-zg.github.io/nanoidp/:
- Requesting tokens: curl examples for every grant, introspection, revocation
- Disposable test identities: users and clients for one CI run, over
/api/runtime - Dynamic client registration: RFC 7591/7592 for a client that was handed only a server URL
- Client ID metadata documents: a
client_idthat is a URL, and what the server will and will not fetch - MCP workflow: drive NanoIDP from Claude Code or any MCP host
- Security guide: profiles, key management, MCP hardening
- Configuration:
users.yaml,settings.yaml, logging - Endpoints: OAuth2/OIDC, SAML, REST API
- Tokens and claims: token structure and
audsemantics - SAML options: bindings, strict mode, signing, canonicalization
- MCP server: all tools and Claude Code/Desktop setup
Security
NanoIDP is a development/testing tool and must NOT be used in
production. Defaults favor convenience (plaintext passwords in config,
permissive CORS, open redirects); hardening is opt-in via the
stricter-dev (runtime) and oauth21 (draft OAuth 2.1 protocol
strictness) profiles and explicit settings. The
Security guide
draws the line precisely.
Development
pip install -e ".[dev]"
pytest
See CONTRIBUTING.md for the development setup, the end-to-end test agent, code quality tooling, and the release process.
Adopters
Organizations using NanoIDP in their development or testing workflows:
Listing means NanoIDP is in use there. It does not imply sponsorship or endorsement. If you use it and would like to be listed, open an issue or a pull request against this section.
License
MIT License. See LICENSE for details.
❤️ Support NanoIDP
NanoIDP is maintained as an open-source project.
If it helps you test OAuth2, OpenID Connect, or SAML flows, you can support its development here:
- 💖 GitHub Sponsors: https://github.com/sponsors/cdelmonte-zg
- ☕ Buy Me a Coffee: https://buymeacoffee.com/nanoidp
Metadata
Release files for nanoidp 3.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nanoidp-3.4.0.tar.gz | 409.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nanoidp-3.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 876.1 kB
Release files / nanoidp-3.4.0.tar.gz
| Download URL | nanoidp-3.4.0.tar.gz |
|---|---|
| Size | 409.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e032318ecf04e8888ed20a1636b095325b94173d72a96e1aec28101ac55329da
|
|
BLAKE2b-256 checksum How to use checksums |
f9fdd516a82b9c7d6e863a9f17948c1716ca5177e344cde3633ba48f535d2981
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency logRelease files / nanoidp-3.4.0-py3-none-any.whl
| Download URL | nanoidp-3.4.0-py3-none-any.whl |
|---|---|
| Size | 466.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3c2fdef99da819d460a2927a8ef65cc96cf6a3db726a7a0aa9ae8c9fee09cef6
|
|
BLAKE2b-256 checksum How to use checksums |
ee68453d39287aae67f03e4a8ed4cdf2751e24d0b78119d3afddc3fec06eae90
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency log