This repository contains a proof-of-concept implementation of https://tools.ietf.org/html/draft-sakimura-oidc-extension-nonweb-01.
The implementation of a provider with support for non-web access tokens can
be found in src/op
. It has the following features:
- Support for "auth scope values" (request with scope value starting with "auth_" will in long-lived access tokens).
- The end user can name access tokens as part of the authentication flow.
- An authenticated user can revoke access tokens (see below).
- Support for dynamic registration and provider configuration information.
- Install dependencies: pip install -r src/op/requirements.txt
- Configure the provider:
- Copy the file
src/op/op/config.py.example
tosrc/op/op/config.py
- Update the base url and paths to SSL certs, encryption/signing keys, etc.
- Start the provider: python op.py -p config
A list of all valid access tokens can be viewed at the endpoint /my_tokens
of the provider. From that page each individual access token can be revoked.
The implementation of a relying party (RP) can be found in
src/service_provider
. This RP registers with the provider dynamically and uses
the "Authorization Code Flow" and makes a token request to obtain the access
token.
- Install dependencies: pip install -r src/service_provider/requirements.txt
- Configure the client:
- Copy the file
src/service_provider/conf.py.example
tosrc/service_provider/conf.py
- Update the paths to SSL certs and the port if necessary.
- Update the
"srv_discovery_url"
of the"non-web-op"
inCLIENTS
to point to the base url of the OpenID Connect Provider described above. - Start the service_provider python service_provider.py conf
A PAM module to verify an access token can be found in src/pam_module
.
It sends (using libcurl
) the access token to the RP
(described above) for authorization.
In this section it is described how to set up the PAM module
apt-get install libpam0g-dev libcurl4-openssl-dev
gcc -fPIC -fno-stack-protector -c pam_oidc_authz.c
mkdir /lib/security
ld -x --shared -o /lib/security/pam_oidc_authz.so pam_oidc_authz.o `curl-config --libs`
The login server (located in src/test_application_login_service
) can be used to
simulate a login service which should be put in front of the RP to ensure only
authorized users can fetch an access token.
For simplicity this login service does NOT authenticate users, it allows any user to select any username before entering the RP.
To start the login server, run the python script
src/test_application_login_service/login_server.py
.
The script requires one parameter: the base url to the RP. The login service will use a HTTP GET request in order to send the username of the user to the RP.
It is possible to specify which port the login server should use, by using the
flag -p
(if it is not specified it defaults to port 80).
Example:
python login_server.py -p 8000 https://localhost:8666/
A small application for testing the flow can be found in src/test_app
.
Add the following to the file /etc/pam.d/test_app
:
auth requisite pam_oidc_authz.so <service provider A.T.V endpoint> <verify_ssl {0, 1}>
account sufficient pam_permit.so
: This should be the url to the access token verification endpoint e.g. https://localhost:8666/verify_access_token
How to use the test application in order test the PAM module.
gcc -o test_app test_app.c -lpam -lpam_misc
./test_app <username> <path to file containing access token>
The OP, RP and login server can be automatically started in a Docker container. See the Dockerfile, with an example Docker Compose file https://github.com/its-dirg/docker/tree/master/non-web-oidc.
After building the image, start a Docker container:
docker run -p 8080:8080 -p 8090:8090 -p 9000:9000 -e HOST_IP=<host IP> <image_name>
The exposed ports are 8080 for the OP, 8090 for the RP and 9000 for the
example login server. And the environment variable HOST_IP
must be the IP
address for the host computer (outside Docker).
To test the flow and get an access token, browse to http://:9000 and follow the guide below from step 4.
- Start the provider.
- Start the RP.
- Start the login server and browse to it.
- Enter a username and submit.
- Click the blue button "Start" at the RP to use the default non-web provider.
- Login at the provider using any of user-password pairs defined in
PASSWD
insrc/op/op/conf.py
, e.g. user "upper" with password "crust". - Enter a new nickname for the access token, e.g. "test1".
- Copy the displayed access token to clipboard.
- Paste the access token in a file.
- Run the test application passing the username selected in step 4. and filename created in step 9.
- If the access token is valid, the test application will print "Authenticated" as the last line of output.
- Try revoking the token by browsing to the
/my_tokens
endpoint at the provider. - Run the test application again with the same access token in the file.
- If the token was properly revoked the test application will print "Not Authenticated"