Open-source project
CZ-NIC/pyoidc avatar
CZ-NIC/pyoidc

pyoidc and a full OpenID Connect implementation you can read

A complete OpenID Connect implementation in Python

748 stars262 forksPythonNOASSERTION

At a glance

What is it?
pyoidc is a complete Python implementation of OpenID Connect, and as a side effect a complete OAuth 2.0 implementation, distributed as the `oic` package and hosted by CZ-NIC and started by Roland Hedberg. Its own documentation admits the docs and the bundled examples are largely broken, so the interesting question is when a specification-complete library beats a maintained framework.
Who is it for?
pyoidc fits a team that needs to read, extend or test the OpenID Connect specification itself, that wants a provider implementation it can inspect line by line, or that is building something the mainstream frameworks do not cover.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 88 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Complete means complete, and that is the point

pyoidc describes itself as a complete implementation of OpenID Connect as specified in the OpenID Connect Core specification, and adds the consequence in the same breath: as a side effect, a complete implementation of OAuth 2.0 too.

That is a different ambition from the one the popular frameworks have. A framework built for production gives you a working provider, a client, a token endpoint and a set of defaults that let a developer get a login page working in an afternoon. It covers the parts of the specification that are commonly used and quietly leaves the rest.

pyoidc takes the opposite position. It implements the specification, including the parts nobody uses, and that is exactly what makes it valuable for a particular kind of work: reading it tells you what the specification actually says, and running it lets you test a client or a provider against a behaviour that is not shaped by what a maintainer decided to prioritise.

The provenance is visible in the metadata. The setup.py carries a copyright line for Umea Universitet, Sweden, from 2013, and the author is Roland Hedberg with the email at catalogix.se. The repository now lives under CZ-NIC, the Czech network information centre, and the acknowledgements credit Vladislav Mladenov and Christian Mainka, both at the Horst Görtz Institute for IT-Security at Ruhr-University Bochum, for helping make the implementation more secure. That is worth noting for a security-critical library: the security review came from a security research group rather than from a general purpose web developer.

The package name on PyPI is `oic`, and the import name is `oic`, not `pyoidc`. That trips people up and is worth checking in your requirements file before you start.

The package layout mirrors the protocol, not your application

The setup.py lists the packages explicitly, and the list is the clearest description of the library's shape.

There is `oic` at the top, then `oic/oauth2` and `oic/oic`, which are the OAuth 2.0 side and the OpenID Connect side. Then `oic/utils` with three subpackages: `oic/utils/authn` for authentication backends, `oic/utils/userinfo` for the userinfo side, and `oic/utils/rp` for the relying party, which is the client.

And there is `oic/extension`, which is the part a project extending the protocol should look at first.

The distribution is a `src/` layout with `package_dir` pointing at it, and the package ships a `py.typed` marker, so the type information is included in the wheel rather than left as a separate stub package.

There is also a console script, `oic-client-management`, which points at `oic.utils.client_management:run`. A command line tool for managing client registrations is the kind of thing that tells you what the library is for: this is infrastructure for running an identity provider and for automating the parts of it that touch a database.

The top level directories reinforce the picture. There are `oauth_example/` and `oidc_example/` as separate example trees, a `doc/` directory for the Sphinx documentation, `docker/` for container setups, `script/`, a `runOpRp.sh` script at the root, `tests/`, `tox.ini`, `mypy.ini`, and an `appveyor.yml` for Windows continuous integration.

The examples largely do not work, and the project says so

This is the part of the repository that any evaluation has to take at face value, because the maintainers wrote it plainly.

The documentation section says the documentation is graciously hosted by Read the Docs, but that it has been largely left unmaintained and that there are various issues, and that the maintainers are trying to remedy this lately with some new momentum, with an invitation to submit pull requests to improve it.

The Examples section is blunter. The current examples included in this repository are unmaintained and there are many issues. The project is in the process of creating a working canonical example implementation, however, until that time, the current examples largely do not work. The maintainers ask for pull requests that may bring these examples back into a working condition.

So the honest summary is that the library is complete and the demonstrations of it are not. That is an unusual position for a project to be in, and it is worth understanding the reasons.

There is a section headed Maintainers Needed, which says the maintainers are looking for help and are working on the project on a best effort basis, while still maintaining a good flow of reviewing each other's pull requests and driving discussions about what should be done. Three maintainers are named by handle, and the section exists at all because the project is short of hands.

For a security protocol library, that combination is the main risk. The specification work is done and stable, but the parts a new user actually touches, the examples and the documentation, are the parts that are behind. If you are evaluating this for a production deployment, the code being complete is a necessary condition and not a sufficient one.

Development setup is pipenv and make, with a Windows variant

The contributor workflow is documented and simple, and it is pipenv based.

You fork the repository, clone your copy, and install pipenv. Then you run:

bash
    $ make install

And to run the tests:

bash
    $ make test

The Makefile shows what those targets do. The install target runs `pipenv install --dev -e .[develop,testing,docs,quality,ldap_authn,examples]`, so the extras are the unit of selection, and the test target runs `pipenv run pytest $(TESTDIR)` against the `tests` directory. The Makefile also carries targets for building the Sphinx documentation with `sphinx-build` and an autobuild variant, an `isort` target, a `blacken` formatting target, and a `bandit` target that runs simple security checkers over `src/`, `oauth_example/` and `oidc_example/`. The documentation build uses `-W`, which turns Sphinx warnings into errors.

The readme notes that this does not affect your system level Python installation, and points at the issue tracker, marking easy issues as newcomer-friendly.

Windows gets its own instructions, because the default path does not work there. The reason given is the lack of GNU Make on Windows, and in addition one of the dependencies for `ldap_authn` is not available as a prebuilt wheel from PyPI. The Windows route is pipenv directly:

bash
   pipenv install --dev -e .[develop,testing,docs,quality]

followed by:

bash
   pipenv run pytest tests

Note the smaller extras list on Windows, since `ldap_authn` is the extra that cannot be installed there.

The packaging metadata itself is current. The build system is setuptools with `setuptools.build_meta`, and the linting configuration uses ruff with a target version of `py39` and a line length of 120, with the Google docstring convention, a max complexity of 15, and per-file ignores for the test directory.

The release cadence is where the risk sits

The release history is the fact that should shape a decision more than anything else in the repository.

The three most recent releases are 1.7.0 on 2024-04-25, 1.6.1 on 2023-07-03, and 1.6.0 on 2023-05-15. The 1.6.1 release is titled Pydantic fix, which tells you that the gap between 1.6.0 and 1.6.1 was a dependency compatibility problem rather than a feature.

The last push to the master branch was on 2026-07-27, and the repository is not archived. So there is activity on the branch and no new release to go with it. A user installing from PyPI gets 1.7.0, which is more than two years old as of the dates in this repository's history, while a user tracking master gets whatever is on the branch.

The package metadata records the development status as `Development Status :: 4 - Beta`, with the classifier for Python 3.9 and the ruff target version set to py39 to match. So the project itself calls this a beta, and it has been calling itself a beta across its whole published life.

The change log is the recommended place to see what changed, and the readme asks readers to check CHANGELOG.md to review the latest changes. For a protocol library, a long gap between releases means a long gap in someone else having reported a security problem against a version you are running.

The practical picture: this is a mature codebase whose release process has slowed, with maintainers openly looking for help. That is a very different risk profile from a framework with a monthly release cadence, and it is a fine profile if you want to read and extend a protocol implementation, and a poor one if you want a service with a support commitment.

Against a maintained framework, the difference is spec coverage versus support

The realistic alternative is one of the mainstream OpenID Connect frameworks in Python, and the difference in approach is a straight trade between specification coverage and ongoing support.

A maintained framework wins on everything operational. It has working documentation, working examples, a release every few weeks, a community large enough that a broken edge case is likely to have been hit already, and a migration path when the ecosystem moves. If you are building a login for an application, that is what you want, and the specification details you would be missing are details you will never need.

pyoidc wins on a different axis. It implements the full specification, so if you need an OAuth 2.0 flow or an OpenID Connect feature that the mainstream library does not expose, or if you need to know exactly what the specification requires in a particular corner, the code is here and it is readable. It is also a client library with a relying party package, and it ships a client management tool, so it can be used from the other end of the flow.

There is a third use case that neither of the two serves as well: testing. If you are building a provider or a client and want to test it against an independent implementation rather than against the same library you use in production, a second implementation of the specification is valuable precisely because it was written independently.

The cost of choosing pyoidc is that you inherit its documentation debt and its example debt. The specification coverage you are buying is real, but it arrives with the understanding that the parts meant to demonstrate it are currently broken and that the project is looking for maintainers.

So the decision comes down to whether the specification details are the point of your project. If they are, pyoidc is hard to beat, because the mainstream frameworks will not cover the corner you care about. If they are not, the framework is the better answer and the gap in coverage will not matter to you.

Editorial conclusion

pyoidc fits a team that needs to read, extend or test the OpenID Connect specification itself, that wants a provider implementation it can inspect line by line, or that is building something the mainstream frameworks do not cover. It is the wrong choice for a production service where time to first working login matters more than insight into the protocol, because the bundled examples are described as largely not working and the documentation is described as largely unmaintained. Before you plan around it, verify three things: which OAuth 2.0 and OpenID Connect profiles your deployment needs are actually implemented in the version you install, since the last published release is 1.7.0 from 2024-04-25, how you will handle the examples yourself, since the project says a canonical working example is in progress, and whether the licence recorded in the package metadata, Apache-2.0, matches the LICENSE.txt file the repository ships.

Frequently asked questions

What is pyoidc and what does it implement?

It is a complete Python implementation of OpenID Connect as specified in the OpenID Connect Core specification, and as a side effect a complete implementation of OAuth 2.0 too. The package is distributed on PyPI as `oic` and the import name is `oic`.

Are the pyoidc examples and documentation usable?

The project states plainly that the documentation has been largely left unmaintained and that the current examples largely do not work, while a canonical working example implementation is in progress. The maintainers invite pull requests to improve both.

How do I set up pyoidc for development?

Fork and clone the repository, install pipenv, then run `make install`, which installs the development extras with pipenv, and `make test`, which runs pytest against the tests directory. On Windows, where GNU Make and a prebuilt wheel for `ldap_authn` are missing, use `pipenv install --dev -e .[develop,testing,docs,quality]` and `pipenv run pytest tests`.

What is the latest pyoidc release?

The most recent published release is 1.7.0 from 2024-04-25, preceded by 1.6.1 from 2023-07-03, titled Pydantic fix, and 1.6.0 from 2023-05-15. The package metadata records the development status as Beta.

What licence is pyoidc released under?

The package metadata in setup.py records the licence as Apache-2.0 and points at the LICENSE.txt file shipped in the repository. Note that GitHub itself classifies the repository licence as Other, a custom licence it cannot classify, pointing at the LICENSE file.

Official sources

  1. CZ-NIC/pyoidc on GitHub
  2. Issues
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cz-nic-pyoidc.svg)](https://hysenlabs.com/projects/cz-nic-pyoidc)

Was this useful?