gada121982 opened a new issue, #10436:
URL: https://github.com/apache/gravitino/issues/10436
**Version:** main branch (tested on v1.2.0)
## Describe what's wrong
The V2 Web UI uses `profile.name` (OIDC fullname) for `serviceAdmins`
authorization check, while the server uses `preferred_username` or `sub` (via
`principalFields` config). This causes the "Create Metalake" button to be
hidden even when the user is a valid service admin on the server side.
**Example:**
- Keycloak user: `admin` (firstName=`admin`, lastName=`admin`)
- Server extracts principal via `principalFields: "preferred_username,sub"`
→ `"admin"`
- UI gets identity via `OidcOAuthProvider.getUserProfile()` → `profile.name`
= `"admin admin"` (fullname per OIDC spec)
- UI checks `serviceAdmins.split(',').includes(authUser?.name)` → `"admin
admin"` ≠ `"admin"` → button hidden
**Workaround:** Add both values to `serviceAdmins` (e.g., `"admin,admin
admin"`). This is fragile.
Additionally, `OidcOAuthProvider.getAccessToken()` returns `id_token ||
access_token`, preferring ID token over access token. Per OAuth2 spec, access
token should be sent to resource servers.
## Error message and/or stacktrace
No error — the button is silently hidden. Server-side authorization works
correctly with `preferred_username`, confirming the mismatch is UI-only.
## How to reproduce
1. Deploy Gravitino with V2 Web UI (`GRAVITINO_USE_WEB_V2: true`)
2. Configure OAuth with OIDC provider (e.g., Keycloak):
```properties
gravitino.authenticator = oauth
gravitino.authenticator.oauth.provider = oidc
gravitino.authenticator.oauth.principalFields = preferred_username,sub
gravitino.authorization.enable = true
gravitino.authorization.serviceAdmins = admin
```
3. Create an IdP user with `username=admin`, `firstName=admin`,
`lastName=admin`
4. Login via OIDC flow
5. "Create Metalake" button is **hidden** despite `admin` being in
`serviceAdmins`
6. Add `"admin admin"` (fullname) to `serviceAdmins` → button appears
## Root cause in code
- `web-v2/web/src/lib/auth/providers/oidc.js:134` — `getUserProfile()`
returns `user.profile` where `name` = fullname (OIDC spec)
- `web-v2/web/src/lib/provider/session.js:124` —
`dispatch(setAuthUser(user))` sets `authUser` = profile object
- `web-v2/web/src/app/metalakes/page.js:364` —
`serviceAdmins.split(',').includes(authUser?.name)` compares fullname against
server principal
## Additional context
**Suggested fix (minimal):** Override `name` with `preferred_username` in
`getUserProfile()`:
```js
async getUserProfile() {
const user = await this.userManager.getUser()
if (!user) return null
return {
...user.profile,
name: user.profile.preferred_username || user.profile.name
}
}
```
**Suggested fix (proper):** Add a server endpoint (`GET /api/auth/me`)
returning the server-resolved principal. UI uses this instead of client-side
string matching.
**For id_token issue:** In `getAccessToken()`, prefer `access_token`:
```js
return user.access_token || user.id_token
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]