Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic bridge endpoint #34

Merged
merged 104 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from 103 commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
b048558
Basic Implementation of Policy Constraints
jfelixh Mar 15, 2024
76df29d
Basic Implementation of Policy Constraints
jfelixh Mar 15, 2024
d1f13f9
Merge branch 'feature_policy_conditions' of https://github.com/GAIA-X…
jfelixh Mar 15, 2024
aca8efe
Build fix
jfelixh Mar 15, 2024
768e9d5
Add new API endpoints for authentication response and test requests
ilaydacansinkoc Apr 18, 2024
f4d23d5
revert: delete unused API endpoints for authentication response and t…
ilaydacansinkoc Jun 9, 2024
48de0dc
OIDC Discovery Fix
jfelixh Jun 10, 2024
3a7a298
Changed default token
jfelixh Jun 10, 2024
0a5deba
Changed default token
jfelixh Jun 10, 2024
22d6cd1
Update extractClaims.test.js
jfelixh Jun 10, 2024
2f4cc92
Update extractClaims.test.js
jfelixh Jun 10, 2024
7971ea4
Merge branch 'feature_policy_conditions' of https://github.com/GAIA-X…
jfelixh Jun 10, 2024
465ae3c
Adopted absolute imports
jfelixh Jun 10, 2024
9325e78
Adopted absolute imports
jfelixh Jun 10, 2024
016eed3
Merge branch 'feature_policy_conditions' of https://github.com/GAIA-X…
jfelixh Jun 10, 2024
bc6ac56
Merge branch 'feature_policy_conditions' of https://github.com/GAIA-X…
jfelixh Jun 10, 2024
e870782
Merge branch 'feature_policy_conditions' of https://github.com/GAIA-X…
jfelixh Jun 11, 2024
aa0ac0f
Fix missing styles source
jfelixh Jun 11, 2024
7287aa6
Readme disclaimer
jfelixh Jun 11, 2024
a7d8579
Less Hydra logs
jfelixh Jun 11, 2024
aa12eb9
Logging improvements with pino
jfelixh Jun 11, 2024
dd5eea3
Text fixes
jfelixh Jun 11, 2024
a8b1d02
Text fixes
jfelixh Jun 11, 2024
46e4a7f
Merge branch 'feature_policy_conditions' of https://github.com/GAIA-X…
jfelixh Jun 11, 2024
1acabb3
add initial dynamic enpoint logic
ilaydacansinkoc Apr 18, 2024
db3d302
fix: move files to dynamic folder
ilaydacansinkoc Apr 18, 2024
ad208dc
enable parametric policy from sp
ilaydacansinkoc Apr 27, 2024
39307f5
fix: define types for input descriptor and presentation definition
ilaydacansinkoc May 1, 2024
5838a46
add verifiable id descriptor
ilaydacansinkoc May 1, 2024
a874fdd
add logic to parametrically use input descriptor for each incr auth
ilaydacansinkoc May 1, 2024
1eeb8ea
update redirect URIs in test_client.sh
ilaydacansinkoc May 1, 2024
502eabf
refactor, create getToken and getMetadata to reuse it in both methods
ilaydacansinkoc May 1, 2024
8e38b37
separete get and post method
ilaydacansinkoc May 1, 2024
4d6cddf
use async/await for execute function
ilaydacansinkoc May 1, 2024
31afb38
chore: flatten credFit array in extractClaims.ts
ilaydacansinkoc May 17, 2024
e13df54
fix: use async await to read file
ilaydacansinkoc May 20, 2024
7b801d1
chore: update OIDC_CLIENT_ID in .env file with client ID from test_cl…
ilaydacansinkoc May 27, 2024
1cf1a09
chore: Update middleware to protect additional paths and use API key …
ilaydacansinkoc Jun 6, 2024
a56d660
chore: Update test_client.sh to use OIDC_CLIENT_ID from .env file
ilaydacansinkoc Jun 6, 2024
d753b23
OIDC Discovery Fix
jfelixh Jun 10, 2024
f9fa302
Changed default token
jfelixh Jun 10, 2024
4184e4e
Changed default token
jfelixh Jun 10, 2024
64f7c7a
Adopted absolute imports
jfelixh Jun 10, 2024
777d90d
Fix missing styles source
jfelixh Jun 11, 2024
600e244
Readme disclaimer
jfelixh Jun 11, 2024
da2deb4
Less Hydra logs
jfelixh Jun 11, 2024
069d8dd
Logging improvements with pino
jfelixh Jun 11, 2024
4830bca
Text fixes
jfelixh Jun 11, 2024
77cd474
Text fixes
jfelixh Jun 11, 2024
3a34b2d
chore: Update dependencies and improve logging
ilaydacansinkoc Jun 11, 2024
41a9c18
revert: delete unused API endpoints for authentication response and t…
ilaydacansinkoc Jun 9, 2024
1dc3cdb
Changed default token
jfelixh Jun 10, 2024
ee00bf5
Adopted absolute imports
jfelixh Jun 10, 2024
5947bce
Adopted absolute imports
jfelixh Jun 10, 2024
26f7282
Fix missing styles source
jfelixh Jun 11, 2024
65b9fc4
Less Hydra logs
jfelixh Jun 11, 2024
a8451bd
Logging improvements with pino
jfelixh Jun 11, 2024
aa73910
Text fixes
jfelixh Jun 11, 2024
4b08dcb
Text fixes
jfelixh Jun 11, 2024
d8b544d
test for dmo
ilaydacansinkoc Jun 11, 2024
3b4ddd0
update to logger.debug, use lib for common piece of code in endpoints
ilaydacansinkoc Jun 11, 2024
d00fbde
Changed default token
jfelixh Jun 10, 2024
1a41415
Changed default token
jfelixh Jun 10, 2024
adfa398
Adopted absolute imports
jfelixh Jun 10, 2024
a41e499
Adopted absolute imports
jfelixh Jun 10, 2024
38c6b2c
Fix missing styles source
jfelixh Jun 11, 2024
1eff760
Logging improvements with pino
jfelixh Jun 11, 2024
0dcd032
Text fixes
jfelixh Jun 11, 2024
0338cd8
Merge branch 'feature_policy_conditions' into dynamic_bridge_endpoint
ilaydacansinkoc Jun 11, 2024
842b6e3
refactor extractClaims.ts
ilaydacansinkoc Jul 7, 2024
6121998
Merge branch 'main' into dynamic_bridge_endpoint
ilaydacansinkoc Jul 8, 2024
9d1e32d
refactor clientMetadata endpoint
ilaydacansinkoc Jul 8, 2024
9566fac
update package-lock.json via npm i
ilaydacansinkoc Jul 8, 2024
2831eb9
use async await to get the loginPolicy
ilaydacansinkoc Jul 8, 2024
f00f9b2
adjust unit tests for multi VC VP and constraints check
ilaydacansinkoc Jul 11, 2024
019d6af
remove old tests that are not needed anymore
ilaydacansinkoc Jul 24, 2024
35fbc11
add a policy with complex constraints
ilaydacansinkoc Jul 24, 2024
cd5cadc
instead of redis.set or get use redisGet and redisSet
ilaydacansinkoc Jul 24, 2024
216e3d4
introduce policy type to order credentials in a presentation
ilaydacansinkoc Jul 24, 2024
41d87d4
add test data and test for triple VC
ilaydacansinkoc Jul 25, 2024
6c8fa50
edit README.md for dynamic_bridge_endpoint approach
ilaydacansinkoc Jul 25, 2024
3eabc09
fix failing test
ilaydacansinkoc Jul 25, 2024
846329c
add swagger for dynamic api endpoint documentation
ilaydacansinkoc Jul 28, 2024
f2115b6
refactor readme.md
ilaydacansinkoc Jul 28, 2024
946be1b
use VC type instead of credential subject type
ilaydacansinkoc Jul 29, 2024
fcfa844
chore: Await extraction of user claims in presentCredential API
ilaydacansinkoc Aug 11, 2024
3d323a5
fix minimal test script
jfelixh Aug 23, 2024
3b3bd20
package maintenance
jfelixh Aug 23, 2024
fa9045e
Fix license headers
jfelixh Aug 23, 2024
8c575f1
Fix more license headers
jfelixh Aug 23, 2024
68cb0b6
Add http logging middleware
jfelixh Aug 23, 2024
7d79109
Logger cleanup
jfelixh Aug 26, 2024
5a71101
First API test
jfelixh Aug 26, 2024
dffdcdc
Version bump
jfelixh Aug 30, 2024
c39c3e6
Fixed test env loading
jfelixh Aug 30, 2024
7772c5e
Fixed unit test
jfelixh Oct 25, 2024
e45c7d1
Reverted login policy loading to be more efficient
jfelixh Oct 25, 2024
06b3bb7
Added helper to check loaded policy syntax
jfelixh Oct 25, 2024
69237bc
Rewrote and fixed policy validation and claim extraction
jfelixh Oct 25, 2024
2514284
Cleaned README
jfelixh Oct 25, 2024
e2c5125
Cleaner loading of policy
jfelixh Oct 26, 2024
a4a8265
Simplified incremental authentication API flow
jfelixh Oct 26, 2024
f5facfb
Slight test improvement for presentCredential API
jfelixh Oct 26, 2024
9e27db5
Amended README regarding mobile only
jfelixh Oct 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 178 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ You operate a service and want to allow your users to sign in using Verifiable
Credentials from a mobile wallet. But building that takes considerable time and
expertise.

Additionally, you may need an easy solution to dynamically request additional
Verifiable Credentials from a user during a session (i.e., "incremental
authorization"). That would once again require a completely custom solution.

### The Solution

A service provider can run this dockerized bridge software that acts as a normal
Expand All @@ -38,7 +42,7 @@ Verifiable Credentials. When setting up the bridge software, you can configure
what Verifiable Credentials are accepted and how the data within is put into
`id_token` or `access_token`.

As a contribution to Gaia-X infrastructure, the ultimate goal here is to enable
As a contribution to Gaia-X infrastructure, the main goal here is to enable
users to use their Gaia-X Participant Credentials to access systems while making
integration simpler through the use of established SSO protocols. The bridge can
also be configured to use other Verifiable Credentials.
Expand Down Expand Up @@ -147,6 +151,69 @@ sequenceDiagram
Client->>Browser: Provide access to protected service
```

## Incremental Authorization Flow

Independent of an OIDC session, a service provider can request additional VCs
from a user. For example, this can be used to incrementally authorize a user to
interact with more parts of a service. An example is that users of a mobility
platform could, at any point in time, unlock the car sharing aspect by
presenting an additional driver's license VC.

From a technical perspective, the service provider backend initiates the request
by sending a login policy to a specific endpoint to create a temporary new
authorization endpoint within the bridge. This has the advantage of reusing the
bridge's existing verification and powerful policy system. A high-level flow
looks like this:

```mermaid
sequenceDiagram
autonumber
actor User
participant Wallet
participant B as SSI-to-OIDC Bridge
participant SP as Service Provider

SP ->> B: POST /api/dynamic/createTempAuthorization
B-->>SP: Return UUID, qrCodeString

SP->>User: Send Auth. page containing QR code

SP->>B: GET /api/dynamic/getAuthResponse
User->>Wallet: Scan QR code
Wallet->>B: GET /api/dynamic/presentCredentialById
B-->>Wallet: Return metadata
Wallet-->>User: Prompt user

User ->>Wallet: Select VC(s)
Wallet->>B: POST /api/dynamic/presentCredentialById
B-->>Wallet: Success

B-->>SP: Return Auth Response
```

### API Documentation

This documentation provides all the necessary information to interact with the
dynamic API endpoints used for incremental authorization. The API is documented
using Swagger, which provides a user-friendly interface to explore and test the
API.

<!-- prettier-ignore -->
> [!NOTE]
> To access the Swagger documentation, run the bridge in development mode and
> navigate to `http://localhost:5002/api-docs`.

To authenticate requests to the dynamic API in Swagger, an API secret must first
be set in the `.env` file in the `vclogin` folder with the key name
`INCR_AUTH_API_SECRET`.

<!-- prettier-ignore -->
> [!NOTE]
> To authenticate requests to the dynamic API in Swagger, first click on
> the "Authorize" button in the top right corner of the Swagger UI. Then, enter
> the API key in the "Value" field with the format `INCR_AUTH_API_SECRET <api_key>`
> and click on the "Authorize" button.

## Running a Local Deployment

A local deployment is a great way to test the bridge and to use it for
Expand Down Expand Up @@ -175,10 +242,13 @@ proper domain has to be set up.
`/vclogin/.env` with key `PEX_DESCRIPTOR_OVERRIDE` if direct control over
what wallets are asked for is desired (example for quick testing:
`./__tests__/testdata/pex/descriptorEmailFromAltme.json`)
6. at this point, it needs to be ensured that the container for the vclogin
6. OPTIONAL: to be able to use or test incremental authorization, set an API key
in the `.env` file in the `vclogin` folder with the key
`INCR_AUTH_API_SECRET`.
7. at this point, it needs to be ensured that the container for the vclogin
service is freshly built with the new env file:
`docker compose down && docker compose build`
7. `$ docker compose up`
8. `$ docker compose up`

To validate the running bridge with a simple OIDC client:

Expand Down Expand Up @@ -246,6 +316,7 @@ PEX_DESCRIPTOR_OVERRIDE=./__tests__/testdata/pex/descriptorAnything.json
HYDRA_ADMIN_URL=http://localhost:5001
REDIS_HOST=localhost
REDIS_PORT=6379
API_KEY=<api-key>
```

_Note: The PEX_DESCRIPTOR_OVERRIDE is optional and provides a way to override
Expand All @@ -261,7 +332,7 @@ refer to the end of the previous section.

## Running Tests

This repository includes unit tests with `jest` and end-to-end tests with
This repository includes unit tests with `vitest` and end-to-end tests with
`playwright`. You may run them as follows:

```bash
Expand All @@ -278,7 +349,7 @@ credential, while forwarding all subject fields to the `id_token`:
```JSON
[
{
"credentialID": "credential1",
"credentialID": "1",
"patterns": [
{
"issuer": "*",
Expand Down Expand Up @@ -323,7 +394,7 @@ use of this could look like this:
```json
[
{
"credentialId": "one",
"credentialId": "1",
"patterns": [
{
"issuer": "did:web:app.altme.io:issuer",
Expand Down Expand Up @@ -384,9 +455,109 @@ logical operators that can combine multiple constraints:
- _or_ Takes two constraint objects `a` and `b`.
- _not_ Takes one constraint object `a`

### Multiple Expected Credentials

The bridge supports multiple expected credentials in a policy file. This allows
for more complex scenarios where multiple credentials are needed to perform
authorization. An example of such a policy file is:

```json
[
{
"credentialId": "cred_email",
"type": "EmailPass",
"patterns": [
{
"issuer": "did:web:app.altme.io:issuer",
"claims": [
{
"claimPath": "$.credentialSubject.email"
}
]
}
]
},
{
"credentialId": "cred_id",
"type": "VerifiableId",
"patterns": [
{
"issuer": "did:web:app.altme.io:issuer",
"claims": [
{
"claimPath": "$.credentialSubject.id"
}
]
}
]
}
]
```

<!-- prettier-ignore -->
> [!IMPORTANT]
> Each `credentialId` should be unique across all expected credentials in a policy,
> and should only consist of alphanumeric characters and underscores. Similarly,
> claim values should never be given colliding `newPath` values to avoid overwriting
> token data.

<!-- prettier-ignore -->
> [!NOTE]
> The expected credentials are matched to the submitted VCs solely on the basis of
> required fields and constraints. If very similar VCs are required by a policy,
> it should have constraints that make the matching unambiguous. Otherwise,
> extracted claims may be switched up.

When having multiple expected credentials, it is possible to define constraints
for each as defined in [Constraints](#constraints). This is especially powerful
since it is possible to refer to other expected credentials:

```json
[
{
"credentialId": "1",
"type": "EmailPass",
"patterns": [
{
"issuer": "did:web:app.altme.io:issuer",
"claims": [
{
"claimPath": "$.credentialSubject.email"
}
],
"constraint": {
"op": "equalsDID",
"a": "$VP.proof.verificationMethod",
"b": "$1.credentialSubject.id"
}
}
]
},
{
"credentialId": "2",
"type": "VerifiableId",
"patterns": [
{
"issuer": "did:web:app.altme.io:issuer",
"claims": [
{
"claimPath": "$.credentialSubject.id"
}
],
"constraint": {
"op": "equals",
"a": "$2.credentialSubject.id",
"b": "$1.credentialSubject.id"
}
}
]
}
]
```

## Token Introspection

Look into the access token like this:
Look into the Ory Hydra access token like this:

```bash
$ docker run --rm -it \
Expand Down Expand Up @@ -420,6 +591,5 @@ service in `compose.yaml`:

- [OpenID Connect Core](https://openid.net/specs/openid-connect-core-1_0.html)
- [OpenID for Verifiable Presentations](https://openid.net/specs/openid-4-verifiable-presentations-1_0-ID2.html)
- [Self-Issued OpenID Provider v2](https://openid.net/specs/openid-connect-self-issued-v2-1_0.html)
- [Verifiable Credentials Data Model v1.1](https://www.w3.org/TR/vc-data-model/)
- [DIF Presentation Definition](https://identity.foundation/presentation-exchange/spec/v2.0.0/#presentation-definition)
50 changes: 25 additions & 25 deletions test_client.sh
jfelixh marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
#!/bin/bash
client=$(docker run --rm -it \
--network ory-hydra-net \
oryd/hydra:v2.2.0 \
create client --skip-tls-verify \
--name testclient \
--secret some-secret \
--grant-type authorization_code \
--response-type token,code,id_token \
--scope openid \
--redirect-uri http://localhost:9010/callback \
-e http://hydra:4445 \
--format json )
--network ory-hydra-net \
oryd/hydra:v2.2.0 \
create client --skip-tls-verify \
--name testclient \
--secret some-secret \
--grant-type authorization_code \
--response-type token,code,id_token \
--scope openid \
--redirect-uri "http://localhost:9010/callback" \
-e http://hydra:4445 \
--format json)

echo $client
echo "$client"

client_id=$(echo $client | jq -r '.client_id')
client_id=$(echo "$client" | jq -r ".client_id")

docker run --rm -it \
--network ory-hydra-net \
-p 9010:9010 \
oryd/hydra:v2.2.0 \
perform authorization-code --skip-tls-verify \
--port 9010 \
--client-id $client_id \
--client-secret some-secret \
--redirect http://localhost:9010/callback \
--scope openid \
--auth-url http://localhost:5004/oauth2/auth \
--token-url http://hydra:4444/oauth2/token \
-e http://hydra:4444
--network ory-hydra-net \
-p 9010:9010 \
oryd/hydra:v2.2.0 \
perform authorization-code --skip-tls-verify \
--port 9010 \
--client-id "$client_id" \
--client-secret some-secret \
--redirect "http://localhost:9010/callback" \
--scope openid \
--auth-url http://localhost:5004/oauth2/auth \
--token-url http://hydra:4444/oauth2/token \
-e http://hydra:4444
2 changes: 2 additions & 0 deletions vclogin/.env.test
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
LOGIN_POLICY=./__tests__/testdata/policies/acceptAnything.json
DID_KEY_JWK={"kty":"OKP","crv":"Ed25519","x":"cwa3dufHNLg8aQb2eEUqTyoM1cKQW3XnOkMkj_AAl5M","d":"me03qhLByT-NKrfXDeji-lpADSpVOKWoaMUzv5EyzKY"}
EXTERNAL_URL=http://example.com
INCR_AUTH_API_SECRET=verysecret
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
{
"id": "verifiableId",
"name": "Input descriptor for login credential",
"purpose": "Please provide your VerifiableId credential to sign-in.",
"constraints": {
"fields": [
{
"path": ["$.credentialSubject.type"],
"filter": {
"type": "string",
"pattern": "VerifiableId"
}
}
]
}
}
]
2 changes: 1 addition & 1 deletion vclogin/__tests__/testdata/policies/acceptAnything.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[
{
"credentialId": "credential1",
"credentialId": "1",
"patterns": [
{
"issuer": "*",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[
{
"credentialId": "some random string with spaces!",
"patterns": [
{
"issuer": "*",
"claims": [
{
"claimPath": "$.credentialSubject.id"
}
]
}
]
}
]
Loading
Loading