Skip to content

feat: get user details from token#363

Open
vnaren23 wants to merge 2 commits intomainfrom
users/naren/tokenidentity
Open

feat: get user details from token#363
vnaren23 wants to merge 2 commits intomainfrom
users/naren/tokenidentity

Conversation

@vnaren23
Copy link
Copy Markdown
Collaborator

Prompt used This is the Typescript SDK repo. We want to add a util method to into src/core/uipath.ts named getTokenIdentity()

The util method should be able to retrieve details of current logged in user from the jwt token stored. We already expose isAuthenticated method. Use that to validate if user has already been authenticated. If not authenticated throw an error. We already expose getToken() method to get the token. Use the same method internally to get the token, decode the jwt token. Response should be consisting of below 5 fields.
email
first_name
last_name
preferred_username
name

Follow coding and naming conventions mentioned in repo.

Generated claude plan

Plan: Add getTokenIdentity() to UiPath core class

Context

Consumers of the SDK currently have no first-class way to read identity claims (email, name, etc.) for the authenticated user. The only hook is getToken(), which returns the raw JWT string — forcing every app to pull in a JWT library and implement base64url decoding themselves. This util exposes the identity claims directly from the token already held in memory, so coded-apps (and any other SDK consumer) can render the current user without an extra round-trip or dependency.

The method is a local, read-only utility — no API call, just decode the JWT payload we already have.

Design

Method signature

public getTokenIdentity(): TokenIdentity

Synchronous, no parameters. Mirrors the style of the existing isAuthenticated() / getToken() methods on src/core/uipath.ts — plain public method, JSDoc block, no @track decorator (consistent with other UiPath core class methods — decorators are only used on service methods).

Return type

New interface TokenIdentity added to src/core/auth/types.ts (existing home for TokenInfo, AuthToken, OAuthContext — no need for a new file):

/**
 * Identity claims decoded from the current JWT access token.
 */
export interface TokenIdentity {
  email?: string;
  firstName?: string;
  lastName?: string;
  preferredUsername?: string;
  name?: string;
}

All fields optional — JWT claims are not guaranteed to be present, and marking them required would cause runtime undefined access. Raw JWT claims use snake_case (first_name, last_name, preferred_username) and are mapped to camelCase to match the rest of the SDK's public surface.

Behavior

  1. If !this.isAuthenticated() → throw AuthenticationError with message 'User is not authenticated. Call initialize() before getTokenIdentity().'
  2. Read this.getToken(). If undefined (defensive — shouldn't happen when isAuthenticated() is true, but possible with secret-auth empty-token path at src/core/uipath.ts:120) → throw AuthenticationError.
  3. Split the JWT on . — must be 3 segments. Otherwise → throw ValidationError with message 'Invalid JWT token format.'
  4. Base64url-decode the payload segment (replace -+, _/, pad with = to multiple of 4), then decodeBase64() from src/utils/encoding/base64.ts and JSON.parse(). Any failure in this chain → throw ValidationError with message 'Failed to decode JWT token payload.'
  5. Map the 5 snake_case claims to camelCase and return.

Error type choices

  • Not authenticatedAuthenticationError from src/core/errors/authentication.ts. The error type is designed for "missing authentication" (see class JSDoc).
  • Malformed token / decode failureValidationError from src/core/errors/validation.ts. Per agent_docs/conventions.md error-types section: ValidationError is for invalid data format (user-supplied input), ServerError is for failed parsing of API response data. A malformed JWT sitting in auth state is closer to invalid input than a server response issue. This is a judgment call; using ServerError here would also be defensible, but ValidationError matches the "invalid data format" description more directly.

Files to modify

File Change
src/core/auth/types.ts Add TokenIdentity interface
src/core/uipath.ts Add getTokenIdentity() method after getToken() (line 239); add imports for TokenIdentity, AuthenticationError, ValidationError, decodeBase64
src/core/index.ts Add export type { TokenIdentity } alongside existing TokenInfo export (line 48)

No changes needed to src/index.ts — it doesn't explicitly re-export TokenInfo either, so TokenIdentity follows the same pattern (available via @uipath/uipath-typescript/core).

No changes to package.json, rollup.config.js, mkdocs.yml — this is a method on an existing class exported through an existing path, not a new service.

No docs/oauth-scopes.md entry — this method makes no API call, so no OAuth scope is required.

No docs/pagination.md entry — not a paginated method.

Reused utilities

JSDoc

Example to include in the method's JSDoc:

const sdk = new UiPath({ /* ... */ });
await sdk.initialize();

const identity = sdk.getTokenIdentity();
console.log(identity.email, identity.name);

Tests

Add a new describe('getTokenIdentity') block to tests/unit/core/uipath.test.ts. The existing test file already mocks AuthService with configurable hasValidToken and getToken — extend the mock so individual tests can override the returned token.

Cases to cover:

  1. Returns all 5 mapped fields when JWT payload contains the claims (uses a fixture JWT assembled with base64url-encoded payload { email, first_name, last_name, preferred_username, name }).
  2. Returns fields as undefined when claims are missing from the payload.
  3. Throws AuthenticationError when isAuthenticated() is false.
  4. Throws ValidationError when token is not a valid JWT structure (e.g., 'not.a.jwt' has 3 segments but the middle is not valid base64url JSON; also test 2-segment and 1-segment strings).
  5. Throws ValidationError when payload base64 decodes but is not valid JSON.

Use TEST_CONSTANTS style; build the fixture JWT inline with a small helper in the test file (no new test util needed for a single use).

Verification

npm run typecheck     # must be clean
npm run lint          # 0 errors
npm run test:unit     # all unit tests pass, new tests green
npm run build         # dist/ produced

Manual end-to-end check (optional, relies on a live auth setup):

import { UiPath } from '@uipath/uipath-typescript/core';
const sdk = new UiPath({ /* oauth config */ });
await sdk.initialize();
console.log(sdk.getTokenIdentity());

Confirm the console output shows the 5 camelCase fields populated from the real token claims.

Local Testing image

@vnaren23 vnaren23 self-assigned this Apr 13, 2026
@vnaren23 vnaren23 requested a review from a team April 13, 2026 09:35
Comment thread src/core/uipath.ts
Comment thread src/core/uipath.ts
Comment thread src/core/uipath.ts
Comment thread tests/unit/core/uipath.test.ts
Comment thread src/core/uipath.ts
* console.log(identity.email, identity.name);
* ```
*/
public getTokenIdentity(): TokenIdentity {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getTokenIdentity seems very technical name. IMO it should be getUserDetails

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getUserDetails might seem like we are querying our backend for user info. Since all we are doing is decoding a token, used getTokenIdentity

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then by this logic, even getToken method can also be interpreted by someone in the same manner

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, even this method is on top of getToken. Just a helper for easier SDK usage, nothing more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from a user's POV, I dont like this name

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open to changing. Maybe getTokenUserDetails ?

Comment thread src/core/uipath.ts
}

const token = this.getToken();
if (!token) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any scenario possible where this.isAuthenticated() is true but token is undefined/null? If yes, then we should handle that scenario.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The if condition is checking the exact scenario you are saying isnt it?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant to ask how will this scenario even occur? It should never be the case where this.isAuthenticated() is true but token is undefined/null

Comment thread src/core/uipath.ts
Comment thread src/core/uipath.ts
Comment thread src/core/uipath.ts
Comment thread src/core/uipath.ts
Comment thread tests/unit/core/uipath.test.ts
@vnaren23 vnaren23 force-pushed the users/naren/tokenidentity branch from e483d3d to fd9fc52 Compare April 13, 2026 10:09
@sonarqubecloud
Copy link
Copy Markdown

Comment thread src/core/uipath.ts
Comment thread src/core/uipath.ts
Comment thread src/core/uipath.ts
Comment thread tests/unit/core/uipath.test.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants