|
1 | 1 | # 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. |
4 | 2 |
|
| 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. |
5 | 4 |
|
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. |
7 | 8 |
|
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: |
10 | 10 |
|
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) |
14 | 19 |
|
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. |
16 | 21 |
|
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) |
20 | 26 |
|
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) |
23 | 28 |
|
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). |
32 | 30 |
|
33 | 31 |
|
34 | | -### Configuration directives |
| 32 | +# Contribute |
35 | 33 |
|
| 34 | +[Join in](https://idpy.org/contribute/). |
36 | 35 |
|
37 | | -_issuer_ |
38 | 36 |
|
39 | | -The issuer ID of the OP, unique value. |
| 37 | +# Authors |
40 | 38 |
|
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 | | - |
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 | | - |
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 | | - |
226 | | - |
227 | | -The identity representation with the information fetched from the user info endpoint. |
228 | | - |
229 | | ----------------------------------- |
230 | | - |
231 | | - |
232 | | - |
233 | | -We can even test the single logout |
| 39 | +- Roland Hedberg |
0 commit comments