---
title: Example Setup
slug: guides/example-setup
docTags: 
createdAt: 2024-03-05T22:52:53.606Z
---

**This example setup shows one of the many possible ways to enable consent-based access decisions with IDENTOS Consent Management tools.**

In our example, we'll build off the [Access Management Example Setup](docId\:eBQAhPxiCB6vwiGMuCrGa) by using an IDENTOS [Wallet](docId\:M6-ez5loVsUqpwNwHtWnJ) to add a user to the authorization flow. This simple consent flow\... *Expand*.

`TODO: Create overview diagram.`

:::hint{type="info"}
**By the end of this tutorial, you'll have used the Wallet to do the following:**

- Enroll an Authorization Server in the Wallet **(Step 1)**
- Add Resource Definitions in the Wallet **(Step 2)**
- Enroll a Data Source in the Wallet **(Step 3)**
:::

## Prerequisites

**If you'd like to try this setup for yourself, please note the following assumptions:**

- You've already completed the [Access Management Quickstart](docId\:eBQAhPxiCB6vwiGMuCrGa).
- You have admin access to an **IDENTOS Wallet** that's already installed and running (this should already be setup for you).
- You know how to make **API calls using&#x20;**[cURL](https://curl.se/) (client URL command line utility).

*Define placeholder variables*

## Step-by-Step Procedure

TBD

`TODO: Create overview diagram.`

### 1. Enroll an Authorization Server

Enroll the Authorization Server used in the Access Management Quickstart

### 2. Add Resource Definitions

Create the same Resource types/definitions/scopes created in the Authorization Server from the Access Management Quickstart

### 3. Enroll a Data Source

Enroll a data source (in this case, the Resource Server from Access Management Quickstart; mention that an IDP can also be a data source)

### 4. Enroll a Client

Prerequisites: Configure Client as UMA Client, add/emphasize Client Redirect URL

Enroll the client from the Access Management Quickstart example (blood glucose app)

### 5. Create a Ticket

:::hint{type="info"}
🌟 **Key Concept:&#x20;**&#x41; [Ticket](docId\:OLHbVOQP8uTOn5EgZ5waR) is what allows a Client to obtain an [Access Token](docId\:J0pcQhmmKqIGZBCkmNiu9) from the Authorization Server. Tickets contain all the information that defines what Resources a Client can access.
:::

**To create a Ticket in the Authorization Server, we'll need to...**

1. **Define the Ticket Purpose&#x20;**&#x69;n the Authorization Server.
2. **Create a Capability Ticket&#x20;**&#x69;n the Authorization Server. This links the Ticket Purpose to the Client making the request.
3. **Define the Requested Resource&#x20;**&#x69;n the Authorization Server. This links the Client to the types of Resources and scopes they can access.
4. **Create a Requested Resource Capability Ticket&#x20;**&#x69;n the Authorization Server. This combines the Capability Ticket and Requested Resource into a single Ticket that represents the Client's overall permissions for accessing a Resource.

For our example, we want to create a Ticket that allows the hospital's web application to `read` `blood-glucose-level` Resources.

:::::WorkflowBlock
:::WorkflowBlockItem
**Define the Ticket Purpose in the Authorization Server.**

Run the API call below to declare that the purpose of the ticket is `"Blood Glucose App wants to read your blood glucose records."` In certain authorization flows, this is the message that would be presented to an end user. Since this is the first purpose we're declaring, it will be `id = 1` in the `purpose` database.

```curl
curl --location -g --request PATCH '{{AS_ADMIN_URI}}' \
--header 'Content-Type: application/vnd.api+json; ext=jsonpatch' \
--header 'Authorization: {{AS_ADMIN_STATIC_TOKEN}}' \
--header 'ApiVersion: v1.0' \
--header 'Accept-Language: en' \
--data-raw '[
    {
        "op": "add",
        "path": "/purpose",
        "value": {
            "type": "purpose",
            "id": 1,
            "attributes": {
                "name": "Blood Glucose App wants to read your blood glucose records."
            }
        }
    }
]'
```
:::

:::WorkflowBlockItem
**Create a Capability Ticket for the Client in the Authorization Server.**

Run the API call below to create the `Blood Glucose App Ticket` with the unique ID of `blood-glucose-app` in the `capability-ticket` database. This will also associate the Capability Ticket with the Ticket Purpose and the OAuth client (`id = 1`) created in Step 3.

```curl
curl --location -g --request PATCH '{{AS_ADMIN_URI}}' \
--header 'Content-Type: application/vnd.api+json; ext=jsonpatch' \
--header 'Authorization: {{AS_ADMIN_STATIC_TOKEN}}' \
--header 'ApiVersion: v1.0' \
--header 'Accept-Language: en' \
--data-raw '[
    {
        "op": "add",
        "path": "/capability-ticket",
        "value": {
            "type": "capability-ticket",
            "id": 1,
            "attributes": {
                "ticketId": "blood-glucose-app",
                "ticketName": "Blood Glucose App Ticket"
            },
            "relationships": {
                "purpose": {
                    "data": {
                        "id": 1,
                        "type": "purpose"
                    }
                },
                "umaClient": {
                    "data": {
                        "id": 1,
                        "type": "uma-client"
                    }
                }
            }
        }
    }
]'
```
:::

:::WorkflowBlockItem
**Define the Requested Resource in the Authorization Server.**

Run the API call below to declare the blood-glucose-level Resource Definition from Step 2 with the Client, Ticket Purpose, and `read` scope. Since this is our first Requested Resource, it will be `id = 1` in the `requested-resource` database.

```curl
curl --location -g --request PATCH '{{AS_ADMIN_URI}}' \
--header 'Content-Type: application/vnd.api+json; ext=jsonpatch' \
--header 'Authorization: {{AS_ADMIN_STATIC_TOKEN}}' \
--header 'ApiVersion: v1.0' \
--header 'Accept-Language: en' \
--data-raw '[
    {
        "op": "add",
        "path": "/requested-resource",
        "value": {
            "type": "requested-resource",
            "id": 1,
            "attributes": {
                "maxPermissionDuration": 300000000,
                "requestedResourceId": "8ddd9d0b-6776-4bfe-9865-b2fb9559b12312"
            },
            "relationships": {
                "resourceDefinition": {
                    "data": {
                        "id": 1,
                        "type": "resource-definition"
                    }
                },
                "umaClient": {
                    "data": {
                        "id": 1,
                        "type": "uma-client"
                    }
                }
            }
        }
    },
    {
        "op": "add",
        "path": "/requested-resource-scopes",
        "value": {
            "type": "requested-resource-scopes",
            "id": 1,
            "attributes": {},
            "relationships": {
                "scope": {
                    "data": 
                        {
                            "id": 1,
                            "type": "scope"
                        }
                },
                "purpose": {
                    "data": {
                        "id": 1,
                        "type": "purpose"
                    }
                },
                "requestedResource": {
                    "data": {
                        "id": 1,
                        "type": "requested-resource"
                    }
                }
            }
        }
    }
]'
```
:::

::::WorkflowBlockItem
**Create a Requested Resource Capability Ticket in the Authorization Server.**

Finally, run the API call below to create a single Ticket that combines the Capability Ticket and Requested Resource we created in the previous API calls. Since this is the first Ticket we're making, it will be `id = 1` in the `requested-resources-capability-tickets` database.

```curl
curl --location -g --request PATCH '{{AS_ADMIN_URI}}' \
--header 'Content-Type: application/vnd.api+json; ext=jsonpatch' \
--header 'Authorization: {{AS_ADMIN_STATIC_TOKEN}}' \
--header 'ApiVersion: v1.0' \
--header 'Accept-Language: en' \
--data-raw '[
  {
        "op": "add",
        "path": "/requested-resources-capability-tickets",
        "value": {
            "type": "requested-resources-capability-tickets",
            "id": 1,
            "attributes": {},
            "relationships": {
                "capabilityTicket": {
                    "data": {
                        "type": "capability-ticket",
                        "id": 1
                    }
                },
                "requestedResource": {
                    "data": {
                        "type": "requested-resource",
                        "id": 1
                    }
                }
            }
        }
    }
]'
```

:::hint{type="success"}
✅ **Step 4 complete!&#x20;**&#x4E;ow that we have a Ticket, the Client can use the Ticket to obtain an Access Token from the Authorization Server.

Note that the Client won't necessarily "have" or "present" this Ticket themselves. In reality, it's more of an internal record that the Authorization Server checks when a Client requests an Access Token.
:::
::::
:::::

::::::ExpandableHeading
### 6. Get an Access Token

:::hint{type="info"}
🌟 **Key Concept:&#x20;**&#x41;n [Access Token](docId\:J0pcQhmmKqIGZBCkmNiu9) is a credential granted by the Authorization Server that allows Client applications to access protected Resources from a Resource Server. The Authorization Server will only grant an Access Token if the Client has a valid [Ticket](docId\:OLHbVOQP8uTOn5EgZ5waR).
:::

**To get an Access Token from the Authorization Server, we'll need to...**

1. **Use a Ticket to request an authorization code&#x20;**&#x66;rom the Authorization Server.
2. **Use the authorization code to request an Access Token&#x20;**&#x66;rom the Authorization Server.
3. **Retrieve the Access Token&#x20;**&#x66;rom the Authorization Server.

We've already created a Ticket for our Client in the previous step. When the Client requests a protected Resource, the Authorization Server will check the request against the Client's ticket. If the request is inline with the Resource defintion and scopes that the Client is authorized to access, then then Authorization Server will grant an Access Token to the Client.

For our example,&#x20;

:::::WorkflowBlock
:::WorkflowBlockItem
**Retrieve an authorization code from the Authorization Server.**

Navigate to the URL below to `GET` an authorization code... *Expand.*

```shell
https://{AuthorizationServer_base_url}/oauth2/authorize?&client_id=client_id&state=1648810292&redirect_uri={Client_redirect_url}&response_type=code&scope=read-ticket
```

The authorization code will be appended to the redirect URL (`code`). In this case, the authorization code is `df4ba24c-ebfb-43b8-90d9-64d90f7dd647`.

```shell
https://{Client_redirect_url}?code=df4ba24c-ebfb-43b8-90d9-64d90f7dd647&state=1654029277
```
:::

:::WorkflowBlockItem
**Use the authorization code to request an Access Token from the Authorization Server.**

Run the API call below to request an Access Token using the authorization code obtained in the previous step.

```curl
curl --location --request POST 'https://{AuthorizationServer_base_url}/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'redirect_uri={Client_redirect_url}' \
--data-urlencode 'code=df4ba24c-ebfb-43b8-90d9-64d90f7dd647' \
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
--data-urlencode 'client_assertion=eyJraWQiOiJyc2ExIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJjbGllbnRfaWQiLCJhdWQiOiJ1cmx0aGluZ3MiLCJpc3MiOiJjbGllbnRfaWQiLCJleHAiOjE2NTQzMjE4MTMsImlhdCI6MTY1NDMwMDIxMywianRpIjoiMDMyZTcyNDItOWFhYi00ZDkxLWI2NjYtZDcyMjgwMTU0MjkxIn0.ht8P5FeTze0-2Y-ISsmxTUaTF246weLxjvbfX4Zb3cfrpPmdW2trg6bGgfq8lBDtkOyPzmLFieUxkNtfZDpqYV6UgRtaVcqerCysEVLHHIaxa5mB7tfUQtBFzIidVDoPfvAEOmMowc6F7whH1IuOmDTp6szfm_uYEHZzLNEERm_bXr0R6uN-ig-l6bgVNsTvswtvRx7AtlvOb0B62FH1Kp4mLc7W8JoqMkowfV-UVXKoFFtIOQj6d9omwEHljWPY9BR_YtUVfkGzxTk1S3Ieax0tQT4Ke0ed9kPTviLKAD04D7lrRu2gpPAq4y8S1UEVshddQmDZEt7WlgmgDkK5pw'
```
:::

::::WorkflowBlockItem
**Retrieve the Access Token from the Authorization Server response.**

The response will include the `access_token`, as well as other details such as when the Access Token expires and what the available scopes are.

```curl
{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJodHRwOlwvXC9sb2NhbGhvc3Q6ODA4NiIsInN1YiI6IkJ1Y1IzaGNnNDNRWUhObjYxN2psUEtUZW1IS0J4aFg1dnpxZmx5MG9PSkNFVkIzWEl1NmNycVRReUFpR3RWMWIiLCJyZXNvdXJjZV9vd25lciI6IjBhNDhmNTA5LWY0MjgtNDZjNi04ZWI5LTRkOTYwOWMwMTZmYiIsImlzcyI6Imh0dHA6XC9cL2xvY2FsaG9zdDo4MDg0IiwicmVzb3VyY2VfaWQiOiJvcGVuaWQiLCJncmFudGVkX3Njb3BlcyI6WyJyZWFkIl0sInR5cGUiOiJwZXJtaXNzaW9uIiwiZXhwIjoxNjU4MjMwNzMzLCJjbGllbnRfaWQiOiJvYXV0aF91bWFfY2xpZW50In0.FHWGOTFg0K06L1VhNasc-pKZ8OLCUB7clUbjwdSSIHs",
  "expires_in": 3599,
  "token_type": "Bearer",
  "refresh_token": "e0dd0169-36a9-4cf4-b30a-3b78c6162bc3",
  "scope": "read"
}
```

:::hint{type="success"}
✅ **Step 4 complete!&#x20;**&#x52;ead on to finish the setup and learn the next steps.
:::
::::
:::::
::::::

:::hint{type="success"}
�&#xDF89;**&#x20;Tutorial complete! Congratulations!**

You've just...
:::

## Next Steps

TBD

- Learn how to manage consent with the Wallet?
- Add an Identity Provider (as Data Source)



