Skip to content
This repository was archived by the owner on Jun 23, 2023. It is now read-only.

Commit 341dcd7

Browse files
authored
Merge pull request #79 from IdentityPython/develop
Plenty of changes
2 parents 1f1291a + 86e15d8 commit 341dcd7

File tree

170 files changed

+25927
-1212
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

170 files changed

+25927
-1212
lines changed

.github/workflows/python-app.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# This workflow will install Python dependencies, run tests and lint with a single version of Python
2+
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
3+
4+
name: oidc-op
5+
6+
on:
7+
push:
8+
branches: [ master, develop ]
9+
pull_request:
10+
branches: [ master, develop ]
11+
12+
jobs:
13+
build:
14+
15+
runs-on: ubuntu-latest
16+
17+
strategy:
18+
fail-fast: false
19+
matrix:
20+
python-version:
21+
- '3.7'
22+
- '3.8'
23+
- '3.9'
24+
25+
steps:
26+
- uses: actions/checkout@v2
27+
- name: Set up Python ${{ matrix.python-version }}
28+
uses: actions/setup-python@v2
29+
with:
30+
python-version: ${{ matrix.python-version }}
31+
- name: Install dependencies
32+
run: |
33+
python -m pip install --upgrade pip
34+
if [ -f requirements-dev.txt ]; then pip install -r requirements-dev.txt; fi
35+
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
36+
python setup.py install
37+
- name: Lint with flake8
38+
run: |
39+
# stop the build if there are Python syntax errors or undefined names
40+
flake8 src/oidcop --count --select=E9,F63,F7,F82 --show-source --statistics
41+
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
42+
flake8 src/oidcop --max-line-length 120 --count --exit-zero --statistics
43+
44+
- name: Test with pytest
45+
run: |
46+
pytest --cov=oidcop tests/
47+
- name: Bandit Security Scan
48+
run: |
49+
bandit --skip B105,B106,B107 -r src/oidcop/
50+
#- name: Upload coverage to Codecov
51+
#uses: codecov/codecov-action@v1
52+
#with:
53+
#token: ${{ secrets.CODECOV_TOKEN }}
54+
#file: example/coverage.xml
55+
#flags: unittests
56+
#env_vars: OS,PYTHON
57+
#name: codecov-umbrella
58+
#fail_ci_if_error: true
59+
#path_to_write_report: ./codecov_report.txt

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
django_op/db.sqlite3
2-
templates
31
static/
42
private/
53
conf.yaml
@@ -117,3 +115,5 @@ venv.bak/
117115
src/oidcendpoint.egg-info/
118116

119117
.iframes/
118+
tests/pairwise.salt
119+
tests/public.salt

.isort.cfg

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[settings]
2+
force_single_line = 1
3+
known_first_party = oidcop
4+
known_third_party = cryptojwt, oidcmsg
5+
known_future_library = future,past
6+
default_section = THIRDPARTY
7+
line_length = 100

.readthedocs.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# .readthedocs.yml
2+
# Read the Docs configuration file
3+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
4+
5+
# Required
6+
version: 2
7+
8+
# Build documentation in the docs/ directory with Sphinx
9+
sphinx:
10+
configuration: docs/source/conf.py
11+
12+
# Build documentation with MkDocs
13+
#mkdocs:
14+
# configuration: mkdocs.yml
15+
16+
# Optionally build your docs in additional formats such as PDF and ePub
17+
formats: all
18+
19+
# Optionally set the version of Python and requirements required to build your docs
20+
python:
21+
version: 3.8
22+
install:
23+
- requirements: requirements-docs.txt

README.md

Lines changed: 24 additions & 218 deletions
Original file line numberDiff line numberDiff line change
@@ -1,233 +1,39 @@
11
# oidc-op
2-
Examples of a OIDC OPs with CherryPy, Flask and Django.
3-
**NOT** something you should even image running in a production environment.
42

3+
This project is a Python implementation of an **OIDC Provider** on top of [jwtconnect.io](https://jwtconnect.io/) that shows to you how to 'build' an OP using the classes and functions provided by oidc-op.
54

6-
### Introduction
5+
If you want to add or replace functionality the official documentation should be able to tell you how.
6+
If you are just going to build a standard OP you only have to understand how to write your configuration file.
7+
In `example/` folder you'll find some complete examples based on flask and django.
78

8-
This project are here to show you how to 'build' an OP using the
9-
classes and functions provided by oidcendpoint.
9+
Idpy OIDC-op implements the following standards:
1010

11-
If you are just going to build a standard OP you only have to write the
12-
configuration file. If you want to add or replace functionality this document
13-
should be able to tell you how.
11+
* [OpenID Connect Core 1.0 incorporating errata set 1](https://openid.net/specs/openid-connect-core-1_0.html)
12+
* [Web Finger](https://openid.net/specs/openid-connect-discovery-1_0.html#IssuerDiscovery)
13+
* [OpenID Connect Discovery 1.0 incorporating errata set 1](https://openid.net/specs/openid-connect-discovery-1_0.html)
14+
* [OpenID Connect Dynamic Client Registration 1.0 incorporating errata set 1](https://openid.net/specs/openid-connect-registration-1_0.html)
15+
* [OpenID Connect Session Management 1.0](https://openid.net/specs/openid-connect-session-1_0.html)
16+
* [OpenID Connect Back-Channel Logout 1.0](https://openid.net/specs/openid-connect-backchannel-1_0.html)
17+
* [OpenID Connect Front-Channel Logout 1.0](https://openid.net/specs/openid-connect-frontchannel-1_0.html)
18+
* [OAuth2 Token introspection](https://tools.ietf.org/html/rfc7662)
1419

15-
Setting up an OP means making a number if decisions. Like, should the OP support:
20+
It also comes with the following `add_on` modules.
1621

17-
- [Web Finger](https://openid.net/specs/openid-connect-discovery-1_0.html#IssuerDiscovery)
18-
- [dynamic discovery](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig)
19-
- [dynamic client registration](https://openid.net/specs/openid-connect-registration-1_0.html)
22+
* Custom scopes, that extends [OIDC standard ScopeClaims](https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims)
23+
* [Proof Key for Code Exchange by OAuth Public Clients (PKCE)](https://tools.ietf.org/html/rfc7636)
24+
* [OAuth2 RAR](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-rar)
25+
* [OAuth2 DPoP](https://tools.ietf.org/id/draft-fett-oauth-dpop-04.html)
2026

21-
All these are services you can access at endpoints. The total set of endpoints
22-
that this package supports are
27+
The entire project code is open sourced and therefore licensed under the [Apache 2.0](https://en.wikipedia.org/wiki/Apache_License)
2328

24-
- webfinger
25-
- provider_info
26-
- registration
27-
- authorization
28-
- token
29-
- refresh_token
30-
- userinfo
31-
- end_session
29+
For any futher information please read the [Official Documentation](#TODO).
3230

3331

34-
### Configuration directives
32+
# Contribute
3533

34+
[Join in](https://idpy.org/contribute/).
3635

37-
_issuer_
3836

39-
The issuer ID of the OP, unique value.
37+
# Authors
4038

41-
_capabilities_
42-
43-
This covers most of the basic functionality of the OP. The key words are the
44-
same as defined in
45-
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata .
46-
A couple of things are defined else where. Like the endpoints, issuer id,
47-
jwks_uri and the authentication methods at the token endpoint.
48-
49-
An example:
50-
51-
response_types_supported:
52-
- code
53-
- token
54-
- id_token
55-
- "code token"
56-
- "code id_token"
57-
- "id_token token"
58-
- "code id_token token"
59-
- none
60-
response_modes_supported:
61-
- query
62-
- fragment
63-
- form_post
64-
subject_types_supported:
65-
- public
66-
- pairwise
67-
grant_types_supported:
68-
- authorization_code
69-
- implicit
70-
- urn:ietf:params:oauth:grant-type:jwt-bearer
71-
- refresh_token
72-
claim_types_supported:
73-
- normal
74-
- aggregated
75-
- distributed
76-
77-
claims_parameter_supported: True
78-
request_parameter_supported: True
79-
request_uri_parameter_supported: True
80-
frontchannel_logout_supported: True
81-
frontchannel_logout_session_supported: True
82-
backchannel_logout_supported: True
83-
backchannel_logout_session_supported: True
84-
check_session_iframe: https://127.0.0.1:5000/check_session_iframe
85-
86-
87-
_id_token_
88-
89-
Defines which class that handles creating an ID Token and possibly also
90-
arguments used when initiating that class.
91-
92-
An example:
93-
94-
id_token:
95-
class: oidcendpoint.id_token.IDToken
96-
kwargs:
97-
default_claims:
98-
email:
99-
essential: True
100-
email_verified:
101-
essential: True
102-
103-
104-
### OIDC Provider example setup
105-
106-
Create an environment
107-
````
108-
virtualenv -ppython3 env
109-
source env/bin/activate
110-
````
111-
112-
##### Install oidc-op
113-
````
114-
pip install git+https://github.com/rohe/oidc-op.git
115-
116-
# get the usage examples
117-
git clone https://github.com/rohe/oidc-op.git
118-
````
119-
120-
##### Configure a Django OP
121-
122-
See
123-
124-
https://github.com/peppelinux/django-oidc-op
125-
126-
##### Configure a Flask OP
127-
128-
````
129-
pip install flask
130-
cd oidc-op/
131-
132-
# configuration: create a private folder
133-
cp -R flask_op/private .
134-
135-
# copy required files
136-
cp flask_op/passwd.json private/
137-
cp flask_op/conf.yaml private/
138-
cp -R flask_op/templates .
139-
140-
# create a JWK for cookie signing
141-
jwkgen --kty=SYM --kid cookie > private/cookie_sign_jwk.json
142-
````
143-
144-
##### About JWK Set (JWKS) files
145-
see: https://cryptojwt.readthedocs.io/en/latest/keyhandling.html
146-
147-
You can use `cryptojwt.key_jar.init_key_jar` to create JWKS file.
148-
An easy way can be to configure the auto creation of JWKS files directly in your conf.yaml file.
149-
Using `read_only: False` in `OIDC_KEYS` it will create the path within the JWKS files.
150-
Change it to `True` if you don't want to overwrite them on each execution.
151-
152-
````
153-
# in conf.yaml
154-
#
155-
OIDC_KEYS:
156-
'private_path': './private/jwks.json'
157-
'key_defs': *keydef
158-
'public_path': './static/jwks.json'
159-
# this will create the jwks files if they absent
160-
'read_only': False
161-
````
162-
163-
In the JWTConnect-Python-CryptoJWT distribution there is also a script you can use to construct a JWK.
164-
165-
You can for instance do:
166-
````
167-
$ jwkgen --kty=RSA
168-
{
169-
"d": "b9ucfay9vxDvz_nRZMVSUR9eRvHNMo0tc8Bl7tWkwxTis7LBXxmbMH1yzLs8omUil_u2a-Z_6VlKENxacuejYYcOhs6bfaU3iOqJbGi2p4t2i1oxjuF-cX6BZ5aHB5Wfb1uTXXobHokjcjVVDmBr_fNYBEPtZsVYqyN9sR9KE_ZLHEPks3IER09aX9G3wiB_PgcxQDRAl72qucsBz9_W9KS-TVWs-qCEqtXLmx9AAN6P8SjUcHAzEb0ZCJAYCkVu34wgNjxVaGyYN1qMA-1iOOVz--wtMyBwc5atSDBDgUApxFyj_DHSeBl81IHedcPjS9azxqFhumP7oJJyfecfSQ",
170-
"e": "AQAB",
171-
"kid": "cHZQbWRrMzRZak53U1pfSUNjY0dKd2xXaXRKenktdUduUjVBVTl3VE5ndw",
172-
"kty": "RSA",
173-
"n": "73XCXV2iiubSCEaFe26OpVnsBFlXwXh_yDCDyBqFgAFi5WdZTpRMJZoK0nn_vv2MvrXqFnw6IfXkwdsRGlMsNldVy36003gKa584CNksxfenwJZcF-huASUrSJEFr-3c0fMT_pLyAc7yf3rNCdRegzbBXSvIGKQpaeIjIFYftAPd9tjGA_SuYWVQDsSh3MeGbB4wt0lArAyFZ4f5o7SSxSDRCUF3ng3CB_QKUAaDHHgXrcNG_gPpgqQZjsDJ0VwMXjFKxQmskbH-dfsQ05znQsYn3pjcd_TEZ-Yu765_L5uxUrkEy_KnQXe1iqaQHcnfBWKXt18NAuBfgmKsv8gnxQ",
174-
"p": "_RPgbiQcFu8Ekp-tC-Kschpag9iaLc9aDqrxE6GWuThEdExGngP_p1I7Qd7gXHHTMXLp1c4gH2cKx4AkfQyKny2RJGtV2onQButUU5r0gwnlqqycIA2Dc9JiH85PX2Z889TKJUlVETfYbezHbKhdsazjjsXCQ6p9JfkmgfBQOXM",
175-
"q": "8jmgnadtwjMt96iOaoL51irPRXONO82tLM2AAZAK5Obsj23bZ9LFiw2Joh5oCSFdoUcRhbbIhCIv2aT4T_XKnDGnddrkxpF5Xgu0-hPNYnJx5m4kuzerot4j79Tx6qO-bshaaGz50MHs1vHSeFaDVN4fvh_hDWpV1BCNI0PKK-c"
176-
}
177-
SHA-256: pvPmdk34YjNwSZ_ICccGJwlWitJzy-uGnR5AU9wTNgw
178-
````
179-
180-
181-
##### Run the server
182-
````
183-
python -m flask_op.server private/conf.yaml
184-
````
185-
186-
Then open your browser to `https://127.0.0.1:5000/.well-known/openid-configuration` to get the OpenID Provider Configuration resource.
187-
188-
189-
##### Install OidcRP and configure flask-rp
190-
191-
It uses `JWTConnect-Python-OidcRP` as Relaing Party for tests, see [related page](https://github.com/openid/JWTConnect-Python-OidcRP).
192-
You can run a working instance of `JWTConnect-Python-OidcRP.flask_rp` with:
193-
194-
````
195-
pip install git+https://github.com/openid/JWTConnect-Python-OidcRP.git
196-
197-
# get entire project to have examples files
198-
git clone https://github.com/openid/JWTConnect-Python-OidcRP.git
199-
cd JWTConnect-Python-OidcRP
200-
201-
# run it as it come
202-
python3 -m flask_rp.wsgi flask_rp/conf.yaml
203-
204-
# if you use django_op
205-
RP_LOGFILE_NAME="./flrp.django.log" python3 -m flask_rp.wsgi django_op/example/data/oidc_rp/conf.django.yaml
206-
````
207-
208-
Now you can connect to `https://127.0.0.1:8090/` to see the RP landing page and select your authentication endpoint.
209-
210-
211-
### Authentication examples
212-
213-
![RP](doc/images/1.png)
214-
215-
Get to the RP landing page to choose your authentication endpoint. The first option aims to use _Provider Discovery_.
216-
217-
----------------------------------
218-
219-
![OP Auth](doc/images/2.png)
220-
221-
AS/OP accepted our authentication request and prompt to us the login form. Read passwd.json file to get credentials.
222-
223-
----------------------------------
224-
225-
![Access](doc/images/3.png)
226-
227-
The identity representation with the information fetched from the user info endpoint.
228-
229-
----------------------------------
230-
231-
![Logout](doc/images/4.png)
232-
233-
We can even test the single logout
39+
- Roland Hedberg

chpy/private/jwks.json

Lines changed: 0 additions & 32 deletions
This file was deleted.

chpy/static/jwks.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)