# Keycloak identity and DTS web-permission setup

The recommended setup is hybrid:

- Keycloak authenticates users and supplies one DTS application role.
- The DTS **Role Permissions** screen owns the role-to-permission matrix.

At login, DTS maps the application role to `users.role`. It does not overwrite permissions stored in `role_permissions`, so permission changes made in DTS take effect immediately and do not require another Keycloak login.

## 1. Create or select a realm

In the Keycloak Admin Console, create a dedicated realm such as `uhs` (do not use `master` for production application users). Set:

```dotenv
KEYCLOAK_REALM=uhs
KEYCLOAK_BASE_URL=https://keycloak.example.edu
KEYCLOAK_ACCOUNT_URL=https://keycloak.example.edu/realms/uhs/account/
```

## 2. Create the OIDC client

Go to **Clients > Create client** and configure:

- Client type: `OpenID Connect`
- Client ID: `uhs-dts` (or the value used by `KEYCLOAK_CLIENT_ID`)
- Client authentication: **On**
- Standard flow: **On**
- Valid redirect URI: `https://dts.example.edu/auth/keycloak/callback`
- Web origin: `https://dts.example.edu`

Use the exact application URL; avoid `*` redirect URIs in production. Copy the secret from **Clients > uhs-dts > Credentials** into `KEYCLOAK_CLIENT_SECRET`.

Application configuration:

```dotenv
KEYCLOAK_LOGIN_ENABLED=true
KEYCLOAK_LOGIN_ONLY=true
KEYCLOAK_CLIENT_ID=uhs-dts
KEYCLOAK_CLIENT_SECRET=replace-with-client-secret
KEYCLOAK_REDIRECT_URI="${APP_URL}/auth/keycloak/callback"
KEYCLOAK_REQUIRE_ROLE=true
KEYCLOAK_PERMISSIONS_SOURCE=database
KEYCLOAK_ROLE_PREFIX=dts-role-
KEYCLOAK_PERMISSION_PREFIX=dts-permission-
```

Use `KEYCLOAK_VERIFY_SSL=true` in production. After changing environment values, run `php artisan config:clear` (or rebuild the production config cache).

## 3. Create application roles

Open **Clients > uhs-dts > Roles > Create role**. Create the roles that your deployment needs:

| Keycloak client role | DTS role |
| --- | --- |
| `dts-admin` | `admin` |
| `dts-user` or legacy `dts-requester` | `user` |
| `dts-student` | `student` |
| `dts-rector` | `rector` |
| `dts-v-rector` | `vice_rector` |

For a custom DTS role, use `dts-role-<role-key>`, for example `dts-role-registry-officer`. The part after `dts-role-` must match the DTS custom-role key.

If a user has several mapped DTS roles, the fixed-role precedence is: admin, rector, vice rector, user, student. Assign exactly one application role to avoid ambiguity.

## 4. Configure permissions in DTS

Keycloak `dts-permission-*` composite roles are not required in database permission mode. Existing composites may remain in Keycloak, but DTS ignores them for authorization.

Open **Role Permissions** in DTS and configure the role. Changes are stored in `role_permissions` and take effect on the next request.

The Admin and Student permission sets are protected from accidental changes. A custom role that manages Role Permissions cannot remove that capability from itself; another permission manager or Admin can change it.

For a custom role created in DTS, create a matching Keycloak client role named `dts-role-<role-key>`. For example, the DTS role key `finance` requires `dts-role-finance` in Keycloak.

## 5. Assign roles to users or groups

For an individual user, go to **Users > select user > Role mapping > Assign role**, filter by client, and assign one DTS application role. For teams, create a Keycloak group, assign the application role to the group, and add users to it. Group application roles are inherited automatically.

Ensure every user has a valid email address. DTS uses email to find or create the local user record.

## 6. Ensure the application role is present in the token

Keycloak normally emits client roles under:

```json
{
  "resource_access": {
    "uhs-dts": {
      "roles": [
        "dts-admin"
      ]
    }
  }
}
```

Check **Clients > uhs-dts > Client scopes > dedicated scope > Scope**. If **Full Scope Allowed** is off, add the DTS client roles to that client's role scope mappings. Use the client-scope evaluation/token preview to confirm the application role is present.

## 7. Apply and verify changes

1. Sign out and sign in through **Continue with UHS SSO (Keycloak)**.
2. Confirm the local user's role changed to the assigned Keycloak role.
3. Configure that role in the DTS **Role Permissions** screen.
4. Confirm the relevant dashboard sections and actions update immediately.

The Keycloak subject (`sub`) is stored as `users.keycloak_id`, while DTS keeps its numeric `users.id` as the primary key for documents and workflows. Name, first name, last name, email, role, and active login state are refreshed from Keycloak at every successful login. This stable subject link means changing an email in Keycloak does not create a duplicate DTS user.

If login says the account has no DTS application role, the application role is either not assigned or not included in the token. If login works but every capability is denied, configure the role in DTS or confirm that its `role_permissions` record is active.
