Verifying your identity
Read the Identity overview first for the IdentityProvider
resource, userInfoPrefix, and claim mappings — this page shows you what those
settings produced for a real caller.
Role bindings match on exact strings, so the first question to answer when
access doesn't behave is who does Hub think I am? Ask Hub rather than
deriving the answer from your IdentityProvider config: a binding whose
subject name is off by one character grants nothing, silently.
kubectl auth whoami
The quickest check. It posts a SelfSubjectReview under the hood and prints
the two fields role bindings match against:
$ kubectl auth whoami
ATTRIBUTE VALUE
Username entra:alice@example.com
Groups [entra:platform-eng system:authenticated]
Check three things:
- The username matches
<userInfoPrefix><username-claim-value>(entra:alice@example.comin the example). - Every group you expect appears, prefixed with
userInfoPrefix. - If groups are missing, the IdP either didn't emit a
groupsclaim or you pointedclaimMappings.groups.claimat the wrong claim name.
This needs kubectl wired up against Hub — see kubectl
login.
The request and response
SelfSubjectReview is the standard Kubernetes authentication.k8s.io/v1
resource, cluster-scoped and create-only. Hub ignores the request body
entirely and answers from the bearer token you authenticated with, so the
review can't be made to describe anyone but the caller:
POST /apis/authentication.k8s.io/v1/selfsubjectreviews
Authorization: Bearer <hub-token>
Content-Type: application/json
{
"apiVersion": "authentication.k8s.io/v1",
"kind": "SelfSubjectReview"
}
The response carries the resolved identity under status.userInfo:
{
"apiVersion": "authentication.k8s.io/v1",
"kind": "SelfSubjectReview",
"status": {
"userInfo": {
"username": "entra:alice@example.com",
"groups": [
"entra:platform-eng",
"system:authenticated"
],
"extra": {
"authentication.hub.upbound.io/identity-provider": ["entra"],
"authentication.hub.upbound.io/issuer": ["https://login.microsoftonline.com/<tenant-id>/v2.0"],
"authentication.hub.upbound.io/sub": ["8f14e45f-ceea-467a-9a1c-2b3d4e5f6a7b"],
"authentication.hub.upbound.io/email": ["alice@example.com"],
"authentication.hub.upbound.io/is-human": ["true"],
"authentication.hub.upbound.io/expiry": ["2026-07-31T16:04:11Z"],
"upbound.io/org": ["acme"]
}
}
}
}
username and groups are the values every role binding matches against —
already carrying the userInfoPrefix from the IdentityProvider that
authenticated you. kubectl auth whoami renders exactly these two fields.
To issue the request without kubectl:
curl -s -X POST "$HUB_URL/apis/authentication.k8s.io/v1/selfsubjectreviews" \
-H "Authorization: Bearer $(hub-credential-helper get-token --hub-url=$HUB_URL)" \
-H "Content-Type: application/json" \
-d '{"apiVersion":"authentication.k8s.io/v1","kind":"SelfSubjectReview"}'
Every authenticated principal may create a SelfSubjectReview, regardless of
role — it's part of the built-in system:basic-user grant.
The extra attributes
The extra map carries the identity attributes Hub derived while minting your
token. Each value is a list, per the Kubernetes UserInfo schema, even when
only one value is meaningful:
| Key | Carries |
|---|---|
authentication.hub.upbound.io/identity-provider | Name of the IdentityProvider that authenticated you |
authentication.hub.upbound.io/issuer | The upstream OIDC issuer URL |
authentication.hub.upbound.io/sub | The sub claim from the upstream token |
authentication.hub.upbound.io/email | The verified email address |
authentication.hub.upbound.io/is-human | "true" for browser and device-flow logins, "false" for exchanged workload tokens |
authentication.hub.upbound.io/expiry | Token expiry, RFC 3339 |
upbound.io/org | The organization the token was minted for |
uid is present in the schema but Hub doesn't populate it — identity is keyed
on the prefixed username, not on an opaque ID.
When the identity is right but access still isn't
SelfSubjectReview answers who am I. When the answer looks correct and
access still doesn't behave, the question becomes what am I allowed to do,
which is a different endpoint: see Filtering and
self-review for SelfSubjectAccessReview
and how to read the filter it returns.
Related resources
- Identity overview — the claim mappings that produce these values.
- kubectl login — wiring
kubectlup against Hub. - Workload identities — reading back a CI job's or ServiceAccount's username before binding it.
- Troubleshooting access — when the groups are missing or a binding doesn't apply.