# OpenID Whisperer - Identity Service
OpenID Compliant Identity Service
[![codecov](https://codecov.io/gh/robertbetts/openid-whisperer/branch/main/graph/badge.svg?token=DVSBZY794D)](https://codecov.io/gh/robertbetts/openid-whisperer)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![CodeFactor](https://www.codefactor.io/repository/github/robertbetts/openid-whisperer/badge/main)](https://www.codefactor.io/repository/github/robertbetts/openid-whisperer/overview/main)
Sometimes you want to stand up an application fast, and you don't want to compromise on its design or access control.
Openid-Whisperer provides a quick and efficient set of solutions where applications have a requirement for OpenID 1.0
or Oauth 2.0 authentication and access control.
1. OpenID Identity Service run either standalone or as Docker container
2. Python OpenID class library
3. Flask OpenID blueprint
4. Customised or mock end user information claims
5. Sandbox for learning and experimenting
There are numerous opensource projects that offer specifications, patterns and solutions around OpenID
authentication and authorisation. This project aims to take a lightweight approach with as complete functional flow and
api coverage as possible. Some of the references that have been useful to this effort are:
* https://openid.net/developers/specs/
* https://auth0.com/docs/
* https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/overview/ad-fs-openid-connect-oauth-flows-scenarios
* https://github.com/AzureAD/microsoft-authentication-library-for-python
## History
This project started life as a mock for Microsoft ADFS, it has since evolved into a lightweight, compliant,
OpenID version 1 service and covers most of the common authentication flows required when running or testing against
an OpenID type service provider.
Important to note is that although a compliant OpenID API, with authentication flows and tokens issued, it still
designed as a protocol mock or authentication flow validator. By default there is no internal repository of
protected resources of end user credentials.
Any values input for client_id, client_secret, username, password, scope, resource are assumed to be valid.
* UserName@domain and non-empty password credentials entered assumed to be correct.
* client_id, resource and scope profiles/permissions are also assumed to exist and to be valid.
## User Information Claim Extensions:
This is a relatively new feature to further support testing of resource permissions and end user claims. The
base extension echoes back the input information gathered from the client/resource owner together with the
credentials of the end user and generates a set of user claims. The claims follow the published OpenID
specification.
There is an extended Faker based implementation which for any input username, randomly generates a fake
end user profile. This profile is cached against the input username and is used to populate the token claim
information. An example of the Faker extension can be seen implemented in the API Service code example
`example_src/openid_examples/mock_openid_service.py`
A typical further customisation to the user information extension, is dropping in a set of predefined users and scopes.
This is very helpful when building and testing and OpenID protect API where different users have
different roles and access to different API resources.
## Example code for various OpenID use cases
### `example_src/openid_examples/`
* `mock_openid_service.py`: A custom implementation of Openid-Whisperer
* `mock_api_server.py`: An example Web/API service, with resources protected through OpenID
* `mock_api_end_user.py`: An example where a client app access an API Service
* `mock_openid_client_lib.py`: A lightweight OpenID protocol library used by the examples
* `mock_shared_config.py`: A common config class for synchronising configuration across the examples
When the example code is run from the project_root folder, the configuration loads default environment
variables from `.env_TEST`
### `example_src/msal_flows`
The MSAL library is used as an alternative method for verifying OpenID protocol compliance, more
specifically the complaince of ADFS or that of Azure.
The following flow examples run through successfully:
* `acquire_token_on_behalf_of_example.py`
* `confidential_client_certificate_sample.py`
* `device_code_flow.py`
* `username_and_password_example.py`
* `interactive_sample.py`
* `migrate_rt.py` This example has API compatibility, however there is no functional implementation.
To run these examples, you may have to alter the configuration parameters to suite you environment
and by default an instance of Openid-Whisperer and OpenID Web/API protected service.
## Development
Active development is on Python 3.11 on both Windows 10 and macOS 13.4. Testing is run using PyTest against these
environments as well as under Ubuntu 22.04 through GitHub Actions.
## Environment Setup
1. Install Python, this project is developed with CPython ^3.11
2. Upgrade pip
```commandline
python -m pip --upgrade pip
```
3. Install Poetry, this is the package manager for this project. Currently, using 1.5.1
```
python -m pip install poetry
```
4. Clone the Repository
```commandline
git clone https://github.com/robertbetts/openid-whisperer.git
```
5. Setup project
```commandline
cd openid-whisperer
poetry install
poetry update
```
6. Setup environment variables, default `.env` and `.env_${ENVIRONMENT:-TEST}`
```
API_HOST=${INTERNAL_HOST:-localhost}
API_PORT=${API_PORT:-5700}
API_HOST_GW=${GATEWAY_HOST:-localhost}
API_PORT_GW=${API_PORT_GW:-8100}
ID_SERVICE_PORT=${ID_SERVICE_PORT:-5000}
ID_SERVICE_HOST=${INTERNAL_HOST:-localhost}
ID_SERVICE_BIND=${ID_SERVICE_BIND:-0.0.0.0}
ID_SERVICE_PORT_GW=${ID_SERVICE_PORT_GW:-8100}
ID_SERVICE_HOST_GW=${GATEWAY_HOST:-localhost}
CA_CERT_FILENAME=${CA_CERT_FILENAME:-certs/ca_cert.pem}
ORG_KEY_FILENAME=${ORG_KEY_FILENAME:-certs/key.pem}
ORG_CERT_FILENAME=${ORG_CERT_FILENAME:-certs/cert.pem}
NO_PROXY=${NO_PROXY:-127.0.0.1,localhost},${GATEWAY_HOST:-localhost},${INTERNAL_HOST:-localhost}
VALIDATE_CERTS=${VALIDATE_CERTS:-False}
```
## Running the Code
### Pytest unit tests
Code test coverage objective is 100%. there are currently no unit tests for the module mocking_examples
```
poetry run coverage run -m pytest && poetry run coverage report -m
```
### Running Openid-Whisperer
Run OpenID Whisperer (from project root)
```
poetry run python -m openid_whisperer.main
```
Run within a Docker Container
```
docker build -t opendid-whisperer:0.1.8 .
docker run --name=openid-whisperer -p5005:5005 -eID_SERVICE_PORT_GW=5005 opendid-whisperer:0.1.8
```
Raw data
{
"_id": null,
"home_page": "https://github.com/robertbetts/openid-whisperer",
"name": "openid-whisperer",
"maintainer": "Robert Betts",
"docs_url": null,
"requires_python": ">=3.10,<4.0",
"maintainer_email": "betts_robert@yahoo.com",
"keywords": "python,mock,api,oauth2,openid",
"author": "Robert Betts",
"author_email": "betts_robert@yahoo.com",
"download_url": "https://files.pythonhosted.org/packages/ae/88/2bbc3a17753ee5cf80703290dd4f90608ec86593eab260e1c208a87f6b10/openid_whisperer-0.1.10.tar.gz",
"platform": null,
"description": "# OpenID Whisperer - Identity Service\nOpenID Compliant Identity Service\n\n[![codecov](https://codecov.io/gh/robertbetts/openid-whisperer/branch/main/graph/badge.svg?token=DVSBZY794D)](https://codecov.io/gh/robertbetts/openid-whisperer)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![CodeFactor](https://www.codefactor.io/repository/github/robertbetts/openid-whisperer/badge/main)](https://www.codefactor.io/repository/github/robertbetts/openid-whisperer/overview/main)\n\nSometimes you want to stand up an application fast, and you don't want to compromise on its design or access control.\nOpenid-Whisperer provides a quick and efficient set of solutions where applications have a requirement for OpenID 1.0\nor Oauth 2.0 authentication and access control.\n\n1. OpenID Identity Service run either standalone or as Docker container\n2. Python OpenID class library\n3. Flask OpenID blueprint\n4. Customised or mock end user information claims \n5. Sandbox for learning and experimenting\n\nThere are numerous opensource projects that offer specifications, patterns and solutions around OpenID\nauthentication and authorisation. This project aims to take a lightweight approach with as complete functional flow and\napi coverage as possible. Some of the references that have been useful to this effort are:\n\n* https://openid.net/developers/specs/\n* https://auth0.com/docs/\n* https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/overview/ad-fs-openid-connect-oauth-flows-scenarios\n* https://github.com/AzureAD/microsoft-authentication-library-for-python\n\n## History\nThis project started life as a mock for Microsoft ADFS, it has since evolved into a lightweight, compliant,\nOpenID version 1 service and covers most of the common authentication flows required when running or testing against \nan OpenID type service provider. \n\nImportant to note is that although a compliant OpenID API, with authentication flows and tokens issued, it still \ndesigned as a protocol mock or authentication flow validator. By default there is no internal repository of \nprotected resources of end user credentials. \n\nAny values input for client_id, client_secret, username, password, scope, resource are assumed to be valid.\n* UserName@domain and non-empty password credentials entered assumed to be correct.\n* client_id, resource and scope profiles/permissions are also assumed to exist and to be valid.\n\n## User Information Claim Extensions:\nThis is a relatively new feature to further support testing of resource permissions and end user claims. The \nbase extension echoes back the input information gathered from the client/resource owner together with the \ncredentials of the end user and generates a set of user claims. The claims follow the published OpenID\nspecification. \n\nThere is an extended Faker based implementation which for any input username, randomly generates a fake \nend user profile. This profile is cached against the input username and is used to populate the token claim \ninformation. An example of the Faker extension can be seen implemented in the API Service code example \n`example_src/openid_examples/mock_openid_service.py`\n\nA typical further customisation to the user information extension, is dropping in a set of predefined users and scopes. \nThis is very helpful when building and testing and OpenID protect API where different users have \ndifferent roles and access to different API resources.\n\n## Example code for various OpenID use cases\n\n### `example_src/openid_examples/`\n* `mock_openid_service.py`: A custom implementation of Openid-Whisperer\n* `mock_api_server.py`: An example Web/API service, with resources protected through OpenID\n* `mock_api_end_user.py`: An example where a client app access an API Service\n* `mock_openid_client_lib.py`: A lightweight OpenID protocol library used by the examples\n* `mock_shared_config.py`: A common config class for synchronising configuration across the examples\n\nWhen the example code is run from the project_root folder, the configuration loads default environment\nvariables from `.env_TEST`\n\n### `example_src/msal_flows`\nThe MSAL library is used as an alternative method for verifying OpenID protocol compliance, more\nspecifically the complaince of ADFS or that of Azure.\nThe following flow examples run through successfully:\n* `acquire_token_on_behalf_of_example.py`\n* `confidential_client_certificate_sample.py`\n* `device_code_flow.py`\n* `username_and_password_example.py`\n* `interactive_sample.py`\n* `migrate_rt.py` This example has API compatibility, however there is no functional implementation.\n\nTo run these examples, you may have to alter the configuration parameters to suite you environment\nand by default an instance of Openid-Whisperer and OpenID Web/API protected service.\n\n## Development\nActive development is on Python 3.11 on both Windows 10 and macOS 13.4. Testing is run using PyTest against these \nenvironments as well as under Ubuntu 22.04 through GitHub Actions.\n\n## Environment Setup\n1. Install Python, this project is developed with CPython ^3.11\n2. Upgrade pip\n```commandline\npython -m pip --upgrade pip\n```\n3. Install Poetry, this is the package manager for this project. Currently, using 1.5.1\n```\npython -m pip install poetry\n```\n4. Clone the Repository\n```commandline\ngit clone https://github.com/robertbetts/openid-whisperer.git\n```\n5. Setup project\n```commandline\ncd openid-whisperer\npoetry install\npoetry update\n```\n6. Setup environment variables, default `.env` and `.env_${ENVIRONMENT:-TEST}`\n```\nAPI_HOST=${INTERNAL_HOST:-localhost}\nAPI_PORT=${API_PORT:-5700}\nAPI_HOST_GW=${GATEWAY_HOST:-localhost}\nAPI_PORT_GW=${API_PORT_GW:-8100}\n\nID_SERVICE_PORT=${ID_SERVICE_PORT:-5000}\nID_SERVICE_HOST=${INTERNAL_HOST:-localhost}\nID_SERVICE_BIND=${ID_SERVICE_BIND:-0.0.0.0}\nID_SERVICE_PORT_GW=${ID_SERVICE_PORT_GW:-8100}\nID_SERVICE_HOST_GW=${GATEWAY_HOST:-localhost}\n\nCA_CERT_FILENAME=${CA_CERT_FILENAME:-certs/ca_cert.pem}\nORG_KEY_FILENAME=${ORG_KEY_FILENAME:-certs/key.pem}\nORG_CERT_FILENAME=${ORG_CERT_FILENAME:-certs/cert.pem}\n\nNO_PROXY=${NO_PROXY:-127.0.0.1,localhost},${GATEWAY_HOST:-localhost},${INTERNAL_HOST:-localhost}\nVALIDATE_CERTS=${VALIDATE_CERTS:-False}\n```\n\n## Running the Code\n### Pytest unit tests\nCode test coverage objective is 100%. there are currently no unit tests for the module mocking_examples\n```\npoetry run coverage run -m pytest && poetry run coverage report -m\n```\n\n### Running Openid-Whisperer\nRun OpenID Whisperer (from project root)\n```\npoetry run python -m openid_whisperer.main \n```\n\nRun within a Docker Container\n```\ndocker build -t opendid-whisperer:0.1.8 .\ndocker run --name=openid-whisperer -p5005:5005 -eID_SERVICE_PORT_GW=5005 opendid-whisperer:0.1.8\n```",
"bugtrack_url": null,
"license": "MIT",
"summary": "OpenID 1.0 Mock Identity Service",
"version": "0.1.10",
"project_urls": {
"Homepage": "https://github.com/robertbetts/openid-whisperer",
"Repository": "https://github.com/robertbetts/openid-whisperer"
},
"split_keywords": [
"python",
"mock",
"api",
"oauth2",
"openid"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "9caa203bec6498291ae8472847cf342c9f9926b75112e062b99da30636e541bf",
"md5": "f3cc763606e91987e9517920adb912a9",
"sha256": "94fb90c99e5ae567d2873dd694cf3b4310dad9006a2efd53fbc4180c4ac14e5b"
},
"downloads": -1,
"filename": "openid_whisperer-0.1.10-py3-none-any.whl",
"has_sig": false,
"md5_digest": "f3cc763606e91987e9517920adb912a9",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10,<4.0",
"size": 53414,
"upload_time": "2023-08-01T23:23:38",
"upload_time_iso_8601": "2023-08-01T23:23:38.645842Z",
"url": "https://files.pythonhosted.org/packages/9c/aa/203bec6498291ae8472847cf342c9f9926b75112e062b99da30636e541bf/openid_whisperer-0.1.10-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ae882bbc3a17753ee5cf80703290dd4f90608ec86593eab260e1c208a87f6b10",
"md5": "e6eb1023fa18ee94bf35f97decfe3ab3",
"sha256": "8afacab258f7ca7e4c4e1a107f9274e712c0e66a533b2b4f24b633141916c004"
},
"downloads": -1,
"filename": "openid_whisperer-0.1.10.tar.gz",
"has_sig": false,
"md5_digest": "e6eb1023fa18ee94bf35f97decfe3ab3",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10,<4.0",
"size": 47984,
"upload_time": "2023-08-01T23:23:39",
"upload_time_iso_8601": "2023-08-01T23:23:39.969633Z",
"url": "https://files.pythonhosted.org/packages/ae/88/2bbc3a17753ee5cf80703290dd4f90608ec86593eab260e1c208a87f6b10/openid_whisperer-0.1.10.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-08-01 23:23:39",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "robertbetts",
"github_project": "openid-whisperer",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "openid-whisperer"
}