Skip to content

Commit 4a9800b

Browse files
committed
Added configuration and oidc sections
1 parent fd5a641 commit 4a9800b

File tree

1 file changed

+141
-6
lines changed

1 file changed

+141
-6
lines changed

README.md

Lines changed: 141 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Features:
1313
* Pluggable APIs and multiple API versions
1414
* Database schema migration using Flask-Migrate
1515
* API body serialisation using Flask-Marshmallow
16+
* OIDC Authentication using Flask-OIDC
1617
* No TLS, because this is intended to run behind a reverse proxy
1718
* Healthz
1819

@@ -28,11 +29,12 @@ You have the choice of running this
2829

2930
To run this directly:
3031

31-
```
32+
```shell
3233
$ pip install -r requirements.txt
3334
$ python ./setup.py install
3435
$ mrmat-python-api-flask -h
3536
usage: mrmat-python-api-flask [-h] [-d] [--host HOST] [--port PORT] [--instance-path INSTANCE_PATH] [--db DB]
37+
--oidc-secrets OIDC_SECRETS
3638

3739
mrmat-python-api-flask - 0.0.2
3840

@@ -44,9 +46,14 @@ optional arguments:
4446
--instance-path INSTANCE_PATH
4547
Fully qualified path to instance directory
4648
--db DB Database URI
49+
--oidc-secrets OIDC_SECRETS
50+
Path to file containing OIDC registration
51+
```
4752

53+
```shell
4854
$ mrmat-python-api-flask
49-
[2021-05-09 16:29:49,966] INFO: Creating new instance path at /opt/dyn/python/mrmat-python-api-flask/var/mrmat_python_api_flask-instance
55+
[2021-06-06 15:30:18,005] INFO: Using instance path at /opt/dyn/python/mrmat-python-api-flask/var/mrmat_python_api_flask-instance
56+
[2021-06-06 15:30:18,005] WARNING: Running without any authentication/authorisation
5057
* Serving Flask app "mrmat_python_api_flask" (lazy loading)
5158
* Environment: production
5259
WARNING: This is a development server. Do not use it in a production deployment.
@@ -57,12 +64,10 @@ INFO [werkzeug] * Running on http://localhost:8080/ (Press CTRL+C to quit)
5764
<Ctrl-C>
5865
```
5966

60-
The instance directory defaults to `var/instance/` but can be overridden to be a fully qualified path via the
67+
The instance directory defaults to `var/instance/` but you can override that to be a fully qualified path via the
6168
`--instance-path` option. Any database supported by SQLAlchemy can be provided by the `--db` option. The database is
6269
a SQLite database within the instance directory by default.
6370

64-
When running in the CLI, the database is created and migrated to the latest revision.
65-
6671
### To run as a WSGI app
6772

6873
To run as a WSGI app, execute the following. When running as a WSGI app, the database is not created and migrated
@@ -81,7 +86,7 @@ $ python ./setup.py sdist
8186
$ docker build -t mrmat-python-api-flask:0.0.1 -f var/docker/Dockerfile .
8287
...
8388
$ docker run --rm mrmat-python-api-flask:0.0.1
84-
...
89+
```
8590

8691
>You may be tempted by Alpine, but most of the Python wheels do not work for it. Go for slim-buster instead
8792
@@ -102,3 +107,133 @@ $ python ./setup.py install
102107
$ python -m flake8
103108
$ python -m pytest
104109
```
110+
111+
Tests for authenticated APIs will be skipped until the testsuite is configured with OIDC secrets.
112+
113+
## Clients
114+
115+
A client for the (currently) the authenticated Greeting API v3 is installed along with the API server.
116+
117+
```shell
118+
$ mrmat-python-api-flask-client -h
119+
usage: mrmat-python-api-flask-client [-h] [-q] [-d] [--config CONFIG] [--client-id CLIENT_ID] [--client-secret CLIENT_SECRET] [--discovery-url DISCOVERY_URL]
120+
121+
mrmat-python-api-flask-client - 0.0.2
122+
123+
optional arguments:
124+
-h, --help show this help message and exit
125+
-q, --quiet Silent Operation
126+
-d, --debug Debug
127+
128+
File Configuration:
129+
Configure the client via a config file
130+
131+
--config CONFIG, -c CONFIG
132+
Path to the configuration file for the flask client
133+
134+
Manual Configuration:
135+
Configure the client manually
136+
137+
--client-id CLIENT_ID
138+
The client_id of this CLI itself (not yours!)
139+
--client-secret CLIENT_SECRET
140+
The client_secret of the CLI itself. Not required for AAD, required for Keycloak
141+
--discovery-url DISCOVERY_URL
142+
Discovery of endpoints in the authentication platform
143+
```
144+
145+
>The client requires configuration with OIDC secrets and currently implements the Device code flow
146+
147+
## Configuration
148+
149+
You can provide configuration by pointing to a JSON file via the FLASK_CONFIG environment variable. The file is expected
150+
to be in the following format:
151+
152+
```json
153+
{
154+
"web": {
155+
"client_id": OIDC client_id of the API server itself
156+
"client_secret": OIDC client_secret of the API server itself
157+
"auth_uri": OIDC Authorization endpoint
158+
"token_uri": OIDC Token endpoint
159+
"userinfo_uri": OIDC UserInfo endpoint
160+
"redirect_uris": OIDC redirect URI
161+
"issuer": OIDC Issuer
162+
"token_introspection_uri": OIDC Introspection URI
163+
},
164+
"OIDC_CLIENT_SECRETS": Can be an external file
165+
}
166+
```
167+
168+
You can externalise `web` into a separate file which you may generate via [Flask-OIDCs oidc-register](https://flask-oidc.readthedocs.io/en/latest/).
169+
If you wish to save yourself an external file, `OIDC_CLIENT_SECRETS` should point to the same file it is declared in
170+
(i.e. the same file that FLASK_CONFIG points to) but `web` must be the first entry due to some unfortunate assumptions
171+
made in Flask-OIDC.
172+
173+
The same or a separate configuration file can be used to configure the testsuite so it includes auth/z/n tests. An
174+
additional dictionary is required to configure the client side:
175+
176+
```json
177+
{
178+
"web": {
179+
"client_id": OIDC client_id of the API server itself
180+
"client_secret": OIDC client_secret of the API server itself
181+
"auth_uri": OIDC Authorization endpoint
182+
"token_uri": OIDC Token endpoint
183+
"userinfo_uri": OIDC UserInfo endpoint
184+
"redirect_uris": OIDC redirect URI
185+
"issuer": OIDC Issuer
186+
"token_introspection_uri": OIDC Introspection URI
187+
},
188+
"client": {
189+
"client_id": OIDC client_id for the API test client
190+
"client_secret": OIDC client_secret for the API test client
191+
"preferred_name": OIDC expected name to test for. The test looks for the preferred_name assertion, which
192+
may not match the client_id.
193+
},
194+
"OIDC_CLIENT_SECRETS": Can be an external file
195+
}
196+
```
197+
198+
The client may also be configured via a configuration file, which should have the following format:
199+
200+
```json
201+
{
202+
"client_id": OIDC client_id of the client script (not whoever ultimately authenticates)
203+
"client_secret": OIDC client_secret of the client script (not whoever ultimately authenticates)
204+
This is required when using Keycloak, which is unfortunate because for instance,
205+
Microsofts AAD doesn't need it and it would make the client app far more distributable
206+
"discovery_url": OIDC discovery URL
207+
}
208+
```
209+
210+
## OIDC
211+
212+
The API has currently been tested with [Keycloak](https://www.keycloak.org). If your Keycloak instance is behind a
213+
self-signed CA then you must point the `HTTPLIB2_CA_CERTS` environment variable to that CA certificate before executing
214+
either the client or the server, otherwise the validation of the tokens will fail in mysterious ways. Only a stack trace
215+
will tell you that communication with the introspection endpoint failed due to missing CA trust.
216+
217+
Configure the following clients as needed:
218+
219+
### API Server
220+
221+
* Suggested client_id: mrmat-python-api-flask
222+
* Access Type: confidential
223+
* Flow: Authorization Code Flow (Keycloak: "Standard Flow")
224+
225+
### API Client
226+
227+
* Suggested client_id: mrmat-python-api-flask-client
228+
* Access Type: confidential (but if it wasn't Keycloak, should be public)
229+
* Flow: Device Authorization Grant
230+
231+
Keycloaks default polling interval during the device authorization flow is set to a rather long 600s. I strongly
232+
suggest to reduce that to 5s in the realm settings.
233+
234+
### Test Client
235+
236+
* Suggested client_id: mrmat-python-api-flask-test
237+
* Access Type: confidential
238+
* Flow: Client Credentials Grant (Keycloak: "Service Accounts Enabled")
239+

0 commit comments

Comments
 (0)