Description
greenhouse/AuthProvider passes auth state to pluginAuth.setAuthState() for consumption by plugins via useAuth(). The userId field was being set from parsed.userId, which was null for logged in users in greenhouse, breaking heureka plugin features that rely on it (e.g. the remediation modals in Heureka pre-filling the "User ID" field).
In packages/oauth/src/tokenHelpers.ts, parsed.userId is derived from the token's sub claim only when it matches the SAP employee-ID regex (^[c,d,i,s,p][0-9]+$):
const userId = tokenData?.sub?.match(regex) ? tokenData.sub : null
Any user whose sub is a UUID gets userId = null.
parsed.loginName is resolved from a broader chain of claims and is reliable across all auth paths:
const loginName = tokenData.login_name || tokenData.name || tokenData.subject || tokenData.sub || ""
What was changed
AuthProvider now maps parsed.loginName → userId in the auth state so plugins receive a consistent, non-null value for all user types.
Description
greenhouse/AuthProvider passes auth state to pluginAuth.setAuthState() for consumption by plugins via useAuth(). The userId field was being set from parsed.userId, which was null for logged in users in greenhouse, breaking heureka plugin features that rely on it (e.g. the remediation modals in Heureka pre-filling the "User ID" field).
In packages/oauth/src/tokenHelpers.ts, parsed.userId is derived from the token's sub claim only when it matches the SAP employee-ID regex (^[c,d,i,s,p][0-9]+$):
const userId = tokenData?.sub?.match(regex) ? tokenData.sub : null
Any user whose sub is a UUID gets userId = null.
parsed.loginName is resolved from a broader chain of claims and is reliable across all auth paths:
const loginName = tokenData.login_name || tokenData.name || tokenData.subject || tokenData.sub || ""
What was changed
AuthProvider now maps parsed.loginName → userId in the auth state so plugins receive a consistent, non-null value for all user types.