Skip to content

Commit

Permalink
Merge pull request #16 from icebreakerone/preprod
Browse files Browse the repository at this point in the history
New PAR endpoints and integration with Ory Hydra
  • Loading branch information
kipparker authored Apr 17, 2024
2 parents d135b46 + 55c5caa commit 0b53158
Show file tree
Hide file tree
Showing 28 changed files with 1,300 additions and 698 deletions.
6 changes: 5 additions & 1 deletion .github/templates/deploy/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ inputs:
env:
description: 'The environment to deploy to'
required: true
service_name:
description: 'Application to deploy'
required: true



runs:
Expand All @@ -19,5 +23,5 @@ runs:
- run: |
cd ${{ inputs.folder }}
copilot --version
copilot deploy --env ${{ inputs.env }}
copilot deploy --env ${{ inputs.env }} --name ${{ inputs.service_name }}
shell: bash
7 changes: 7 additions & 0 deletions .github/workflows/deploy_authentication.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,10 @@ jobs:
with:
folder: authentication
env: prod
service_name: backend
- name: Deploy Redis
uses: ./.github/templates/deploy/
with:
folder: authentication
env: prod
service_name: redis
7 changes: 7 additions & 0 deletions .github/workflows/deploy_authentication_dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,10 @@ jobs:
with:
folder: authentication
env: dev
service_name: backend
- name: Deploy Redis
uses: ./.github/templates/deploy/
with:
folder: authentication
env: dev
service_name: redis
1 change: 1 addition & 0 deletions .github/workflows/deploy_resource.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ jobs:
with:
folder: resource
env: prod
service_name: perseus-resource
1 change: 1 addition & 0 deletions .github/workflows/deploy_resource_dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ jobs:
with:
folder: resource
env: dev
service_name: perseus-resource
88 changes: 75 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Perseus demo energy provider

Emulates authentication and resource api endpoints for the Perseus demo.
Emulates authentication and resource api endpoints for the Perseus demo. Authentication is built on top of [Ory Hydra](https://www.ory.sh).

## Authentication API

The authentication app is in the [authentication](authentication) directory. It provides endpoints for authenticating and identifying users, and for handling and passing on requests from the client API to the FAPI API.
The authentication app is in the [authentication](authentication) directory. It provides endpoints for authenticating and identifying users, and for handling and passing on requests from the client API to the FAPI API. It uses a

Authentication API documentation is available at https://perseus-demo-authentication.ib1.org/api-docs.

Expand Down Expand Up @@ -33,6 +33,10 @@ cd scripts

You will need to create a "certs" directory in the root of the project, and move the generated certificates into it.

### Using client certificates

Most of the endpoints require a client certificate to be presented. As the directory service is not yet available, the contents of the certificate will not be checked with an external, so any valid certificate will be acceptable. The certificate **is** used to confirm identity, so the same one must be presented in all requests.

## Running the local docker environment

The included docker compose file will bring up both APIs. It uses nginx to proxy requests to uvicorn, with nginx configuration to pass through client certificates to the backend, using the same header as used by AWS ALB (`x-amzn-mtls-clientcert`).
Expand All @@ -43,31 +47,89 @@ docker-compose up

The environment variables in the docker compose file point to the FAPI api running on localhost port 8020 (http://host.docker.internal:8020). As the FAPI api is not running in the docker environment, you may need to change these environment variables to match your local environment. It will also work with the live FAPI api by changing these values to "https://perseus-demo-fapi.ib1.org".

## Pushed Authorization Request (PAR)

As PAR is not available on the Ory Hydra service that this demo is based on, a PAR endpoint has been implemented in this example service. It is expected that production ipmlementations may use the PAR endpoint of their Fapi provider.

In this simple implementation, the request is stored in a redis instance, using a token that matches Fapi requirements as the key.

## Testing the API with client.py

client.py will execute a series of requests to the API demonstrating the steps from initial PAR (pushed authorization request) to introspecting the token presented to the resource API. The steps are
client.py can be used to test authorisation code flow, introspection, id_token decoding and retrieving data from the resource URL.

Four commands are available, and are run using:

```bash
python -W ignore client.py [auth|introspect|id-token|resource]
```

nb. The optional `-W ignore` switch suppresses multiple warnings about the self-signed certificates.

### Auth

- Create a push authorization request, and store the ticket value
- Authenticate the user
- Ask for user's consent
- With the users identity and the ticket, retrieve the authorization code
- Exchange the authorization code for an access token
- Introspect the access token
- Use the access token to access the resource API
Running `client.py auth` will perform the initial steps in the authorisation code flow, outputting a URL that will open the UI to log in and confirm consent. The PKCE code verifier will also be in the output, which will be needed after the redirect

```bash
python -W ignore client.py
python -W ignore client.py auth
```

The `-W ignore` switch suppresses multiple warnings about the self-signed certificates.
Example output:

```bash
Code verifier: c6P-FfD0ayLslzCUESCsay8QHEg71O0SnKLeHPkOSyOZ6KubKPRaclM4u5veKcqI7MNqZX_xAUt4CUwIwm4JD99EacbtjAABbyY1i972umU9Ong9HFjtJq84y5mljGFy
https://vigorous-heyrovsky-1trvv0ikx9.projects.oryapis.com/oauth2/auth?client_id=f67916ce-de33-4e2f-a8e3-cbd5f6459c30&response_type=code&redirect_uri=http://127.0.0.1:3000/callback&scope=profile+offline_access&state=9mpb2gDwhp2fLTa_MwJGM21R7FjOQCJq&code_challenge=cksXMlSWrcflDTJoyrpiWX0u2VRV6C--pzetmBIo6LQ&code_challenge_method=S256
```

By default the client will use the local docker environment and expects a local instance of the FAPI api to be running on localhost:8020. Testing against the deployed API can be achieved by setting the `AUTHENTICATION_API` and `RESOURCE_API` environment variables, and optionally the FAPI_API environment variable.

```bash
FAPI_API=https://perseus-demo-fapi.ib1.org AUTHENTICATION_API="https://perseus-demo-authentication.ib1.org" RESOURCE_API=https://perseus-demo-energy.ib1.org python -W ignore client.py
```

A successful run will complete with outputting data from the resource API.
Opening the redirect url will present you with the default Ory Hydra log in/ sign up screen, followed by a consent screen:

![Consent screen](docs/consent.png)

Granting consent will redirect to our demo client application, with the authorisation code appended to the url. The authorisation code can be exchanged for an access token by adding the code_verifier value to the form and submitting:

![Redirect](docs/exchange.png)

### Introspection

To show the response of the introspection endpoint, run:

```bash
python -W ignore client.py introspect --token <token>
```

with token being the `token` value obtained from authorisation code flow

### Client side id_token decoding

To show the response of client side id_token decoding, run:

```bash
python -W ignore client.py id-token --token <token>
```

with token being the `id_token` value obtained from authorisation code flow

## Ory Hydra

Please contact IB1 for the Client ID and secret if you would like to test against our demo Ory account. Alternatively you can set up a free developer account and create an Oauth2 client with your own details. The client should have:

- Authentication method set to None
- Grant types Authorisation Code and Refresh Token
- Response types Code and ID Token
- Access Token Type jwt
- Scopes profile and offline_access
- Redirect urls to match your production and/or development and local redirect URLs

![Authentication Method None](docs/authentication-method-none.png)

![Grant Types and Response Types](docs/supported-flows.png)

![Scopes and redirecs](docs/scope-redirects.png)

## FAPI Flow

Expand Down
5 changes: 5 additions & 0 deletions authentication/Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ python-multipart = "*"
httpx = "*"
bcrypt = "*"
cryptography = "*"
redis = "*"
pkce = "*"
boto3 = "*"
pytest-coverage = "*"

[dev-packages]
black = "*"
Expand All @@ -23,6 +27,7 @@ types-requests = "*"
pytest = "*"
responses = "*"
pytest-mock = "*"
click = "*"

[requires]
python_version = "3.12"
Loading

0 comments on commit 0b53158

Please sign in to comment.