apache / apache/polaris-tools

[console] OIDC header shows "User" because getPrincipalNameFromToken always uses JWT `sub`

Open
#268 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
33
Forks
46
Avg merge
1d 4m
Merged PRs (30d)
2

Description

## Description

After a successful OIDC login (Microsoft Entra ID), the Console header shows **User** and avatar initials **US**, even though:

1. Polaris Server maps the principal by `preferred_username` (email / UPN).
2. The access token contains `name` and `preferred_username`.
3. `GET /api/management/v1/principals` returns that principal (e.g. `user@example.com`).
4. Catalogs and other management APIs work as that principal.

The Console then calls `GET /api/management/v1/principals/{sub}` and gets **404**. A follow-up `principal-roles` call also fails. The header falls back to `"User"`.

This looks Keycloak-centric: OIDC was added in #168 / #125 and tested with Keycloak, where `sub` is often the same as the Polaris principal name. Entra (and many other IdPs) use an opaque pairwise `sub` that is **not** the principal name.

## Root cause

[`console/src/lib/utils.ts`](https://github.com/apache/polaris-tools/blob/main/console/src/lib/utils.ts) — `getPrincipalNameFromToken()`:

```ts
return (
(decoded.sub as string) ||
(decoded.principal as string) ||
(decoded.principal_name as string) ||
(decoded.name as string) ||
null
)
```

## Actual

| Item | Result |
|------|--------|
| OIDC login | Succeeds |
| Header | User / initials US |
| `GET /api/management/v1/principals` | 200 — includes `user@example.com` (and `root`) |
| `GET /api/management/v1/principals/{entra-sub}` | 404 |
| `GET .../principals/{entra-sub}/principal-roles` | fails as a follow-on |
| Client-credentials login as `root` | Header correctly shows `root` |

Token claims present (redacted): `name` = display name, `preferred_username` = email/UPN, `sub` = opaque id, `scp` includes the Polaris API scope.

## Steps to reproduce

1. Configure Polaris Server mixed auth with an IdP where `sub` ≠ principal name, e.g.:
- `polaris.oidc.principal-mapper.name-claim-path=preferred_username`
- do **not** set `id-claim-path`
2. Create a Polaris principal named after `preferred_username` (email/UPN) and grant a principal role.
3. Configure Console OIDC (`VITE_OIDC_*`) against that IdP (Entra ID v2, or any IdP with opaque `sub`).
4. Log in via **Login with OIDC**.
5. In DevTools → Network, observe `GET /api/management/v1/principals/{sub}` → 404.
6. Header still shows **User**.

## Suggested fix

1. Change claim precedence in `getPrincipalNameFromToken` so opaque `sub` is last, e.g. `preferred_username` → `principal_name` → `principal` → `name` → `email` → `sub`.
2. Better: make the claim configurable (`VITE_OIDC_PRINCIPAL_CLAIM` / `config.oidc.principalClaim`) so Console can match server `name-claim-path`.
3. If `GET /principals/{id}` 404s, fall back to JWT `name` / `preferred_username` for the header instead of hardcoded `"User"`.
4. Optionally resolve the current user from the principals list by matching `preferred_username`.

## Environment

- Component: Polaris Console (`apache/polaris-tools` `console/`)
- Branch: `main` (`getPrincipalNameFromToken` as above)
- IdP: Microsoft Entra ID (OIDC v2, PKCE public client)
- Polaris Server: mixed internal + OIDC; principal mapped by `preferred_username`
- Related: #125 (OIDC, closed), #168 (OIDC PR, Keycloak), #176 (OIDC improvements — different scope)
- Server-side mapping discussion (not this UI bug): apache/polaris#2373, apache/polaris#3059

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in `console/src/lib/utils.ts` and read `getPrincipalNameFromToken()`, then trace how its result is used to fetch the current principal and populate the header. The issue describes the failure when an IdP's opaque `sub` differs from the Polaris principal name, and suggests several possible fixes. Done should mean the header identifies the mapped principal rather than falling back to “User” for this OIDC case.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.