Set up a custom Okta authorization server with the claims, roles, and access policies required by Halo. This is a prerequisite for both [Halo Portal SSO](/halo/okta-portal-sso) and [Halo API Bearer Authentication](/halo/okta-api-bearer-authentication).

## Prerequisites

- An Okta organization with admin access
- Network access from your Halo deployment to Okta

## Create authorization server

1. Navigate to `Security` -> `API` and create a new Authorization server.
    - Give an appropriate name. e.g. `Glasswall Halo`
    - Enter a common audience value that will be shared across all Halo clients (Portal and API). e.g. `api://halo`
    - Give an appropriate description. e.g. `Glasswall Halo Authorization server`
    - Once saved, make a note of the `Issuer Metadata URI`. Remove `/.well-known/oauth-authorization-server` from the end of the URI. e.g.

        ```sh
        export ORIGINAL_ISSUER_URI=https://your-org.okta.com/oauth2/aus1234567890abcdef/.well-known/oauth-authorization-server
        export OKTA_ISSUER_URI=https://your-org.okta.com/oauth2/aus1234567890abcdef
        export VALID_AUDIENCE="api://halo"
        ```

![Screenshot: Create new authorization server](/.attachments/image-013901ef-d0dc-4245-bfff-e851b0fd601f.png)
![Screenshot: Authorization server details with issuer URI](/.attachments/image-bc0a38e5-da71-4dd9-9c9f-b305e20c3f37.png)

> **Note:** The audience `api://halo` is shared across all Halo clients. Both Portal SSO and API Bearer authentication validate tokens against this audience. This allows a single authorization server to serve both use cases.

## Add custom scope for Halo API access

2. Navigate to the `Scopes` tab on the authorization server and add a new scope:
    - Name: `halo.api`
    - Display Phrase: Halo API
    - Description: `Access to Halo API`
    - Check `Set as a default scope`

![Screenshot: Custom scope configuration](/.attachments/image-633093f2-ee2a-44a5-b105-e1ca75e6abfd.png)

> **Note:** The OIDC scopes (e.g. `openid`, `profile`, `email`) are user-context only and cannot be used with the Client Credentials flow. A custom scope is required for machine-to-machine API access.

## Set up claims

3. Configure the claims needed by Halo services. Navigate to the `Claims` tab on the authorization server.

    - Full name:
        - Name: `name`
        - Include in token type: `Access Token`
        - Value type: `Expression`
        - Value: `user.firstName + " " +  user.lastName`
        - Include in: `Any scope`
    - Family name:
        - Name: `family_name`
        - Include in token type: `Access Token`
        - Value type: `Expression`
        - Value: `user.lastName`
        - Include in: `Any scope`
    - Given name:
        - Name: `given_name`
        - Include in token type: `Access Token`
        - Value type: `Expression`
        - Value: `user.firstName`
        - Include in: `Any scope`
    - Email ID:
        - Name: `unique_name`
        - Include in token type: `Access Token`
        - Value type: `Expression`
        - Value: `user.email`
        - Include in: `Any scope`

![Screenshot: Claims configuration](/.attachments/image-371c17b5-e427-4ed4-866f-ca9d93dbded9.png)

## Define roles

> **Note:** Halo uses two separate role claims:
> - `roles`: used by the Portal (via Portal-Access) to control UI access
> - `role`: used by the API-Access service for endpoint authorization
>
> If the role claims are not configured, the Portal defaults to a read-only role and the API defaults to the `User` role. See [Portal Roles to Action Mapping](/halo/portal-roles-to-action-mapping) and [API Roles to Action Mapping](/halo/api-roles-to-action-mapping) for details on what each role can access.

4. Halo recognizes two role values: `User` and `Admin` (case-insensitive). Okta doesn't have a native way of defining roles in Authorization servers. Role claims need to be added to pass the user/client roles in the access token.

### Portal SSO roles (`roles` claim)

This claim is used by the Portal to determine which pages and features are available to the user. We recommend using Halo-specific group names rather than generic `User` or `Admin` groups, which may conflict with other applications in your Okta organization.

1. Create the groups in Okta. Navigate to `Directory` -> `Groups` and create:
    - `Halo_User`
    - `Halo_Admin`

2. Assign users to the appropriate group.

3. Navigate to the authorization server's `Claims` tab and create a `roles` claim that translates group names to Halo role values:
    - Name: `roles`
    - Include in token type: `Access Token`
    - Value type: `Expression`
    - Value:
        ```
        isMemberOfGroupName("Halo_Admin") ? "Admin" : isMemberOfGroupName("Halo_User") ? "User" : ""
        ```
    - Include in: `Any scope`

    ![Screenshot: Roles claim using groups with expression](/.attachments/image-19618104-a00e-46d3-bbf7-600b7c62a840.png)

> **Note:** The `isMemberOfGroupName()` function only works in user-context flows (e.g., Authorization Code). It does not apply to Client Credentials (machine-to-machine) flows.

### API roles (`role` claim)

This claim is used by the API-Access service to authorize operations. Since API clients use the Client Credentials flow (no user context), group membership expressions don't apply. Instead, map the `client_id` to a role value.

4. Navigate to the authorization server's `Claims` tab and create a `role` claim:
    - Name: `role`
    - Include in token type: `Access Token`
    - Value type: `Expression`
    - Value:
        ```
        (app.clientId == "<your-api-client-id>") ? "Admin" : "User"
        ```
    - Include in: `Any scope`

    ![Screenshot: Role claim using client ID expression](/.attachments/image-84c1c1ed-c9da-484a-a7a5-fa41d92e8848.png)

> **Note:** Replace `<your-api-client-id>` with the `client_id` of your API Services application. Add additional conditions for multiple API clients, e.g.:
> ```
> (app.clientId == "<client-1>") ? "Admin" : (app.clientId == "<client-2>") ? "Admin" : "User"
> ```

## Next steps

With the authorization server configured, proceed to set up one or both of:

- [Halo Portal SSO](/halo/okta-portal-sso) - configure Okta as the identity provider for the Halo Portal
- [Halo API Bearer Authentication](/halo/okta-api-bearer-authentication) - configure Bearer token authentication for the Halo API

Each guide includes configuring an access policy on this authorization server for its respective client.