> ## Documentation Index
> Fetch the complete documentation index at: https://litprotocol-vincent.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Authenticating Users

The Vincent Web App Client enables secure user authentication and delegation management for executing Vincent Abilities on their behalf.

Using the Web App Client, you can direct users to the Vincent Connect Page where:

* New users can review the Abilities your App is requesting and configure Vincent Policies
* Returning users can log in and confirm their identity and authorized App Version

## Authentication Flow

<Steps>
  <Step title="Redirect to Connect Page">
    Your App redirects users to the Vincent Connect Page
  </Step>

  <Step title="User Reviews and Configures">
    Users review requested Abilities and configure Policies
  </Step>

  <Step title="Return with JWT">
    Upon approval, users return to your App with a signed JWT
  </Step>

  <Step title="Verify and Store">
    Your App verifies and stores the JWT for authenticated requests
  </Step>
</Steps>

## Vincent JWT

The JWT proves user authentication via their Vincent Wallet and grants your App permission to act on their behalf.

### JWT Structure

<ParamField path="header" type="object">
  Standard JWT header containing algorithm and type information
</ParamField>

<ParamField path="signature" type="string">
  Signature from User's Vincent Wallet proving the JWT was signed using their wallet
</ParamField>

<ParamField path="data" type="string">
  The raw, unsigned payload string used during signing
</ParamField>

<Note>
  To access these claims, use [`decodeVincentJWTFromUri`](https://docs.heyvincent.ai/interfaces/vincent-app-sdk.webAuthClient.WebAuthClient.html#decodevincentjwtfromuri) in your frontend.
</Note>

### JWT Contains

<ParamField path="JWT" type="object">
  The Vincent JWT containing authentication and authorization details.

  <Expandable title="properties">
    <ParamField path="pkp" type="object" required>
      User's Vincent Wallet containing ethAddress, publicKey, and tokenId
    </ParamField>

    <ParamField path="app" type="object" required>
      Vincent App the JWT was issued for, including id and version fields
    </ParamField>

    <ParamField path="authentication" type="object" required>
      Authentication method with type (email, phone, or passkey) and optional value
    </ParamField>

    <ParamField path="aud" type="string" required>
      Valid audience (your domain/redirect URI)
    </ParamField>

    <ParamField path="exp" type="number" required>
      Expiration timestamp (seconds since Unix epoch)
    </ParamField>
  </Expandable>
</ParamField>

## Setting Up the Web App Client

<ParamField path="getWebAuthClient" type="function">
  Creates a Vincent Web App Client instance

  <Expandable title="parameters">
    <ParamField path="appId" type="string" required>
      Your Vincent App ID from the dashboard
    </ParamField>
  </Expandable>

  <Expandable title="returns">
    <ParamField path="vincentAppClient" type="object">
      The Vincent App Client instance with authentication methods
    </ParamField>
  </Expandable>
</ParamField>

```javascript theme={null}
import { getWebAuthClient } from '@lit-protocol/vincent-app-sdk/webAuthClient';

const vincentAppClient = getWebAuthClient({
  appId: process.env.MY_VINCENT_APP_ID
});
```

## Handling Authentication

<ParamField path="vincentAppClient.uriContainsVincentJWT" type="method">
  Checks if the current URL contains a Vincent JWT

  <Expandable title="returns">
    <ParamField path="hasJWT" type="boolean">
      Returns true if URL contains a Vincent JWT, false otherwise
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="vincentAppClient.decodeVincentJWTFromUri" type="method">
  Extracts and validates JWT from URL

  <Expandable title="parameters">
    <ParamField path="origin" type="string" required>
      The origin URL to validate against (e.g., window\.location.origin)
    </ParamField>
  </Expandable>

  <Expandable title="returns">
    <ParamField path="decodedJWT" type="object">
      The decoded JWT object containing all JWT claims
    </ParamField>

    <ParamField path="jwtStr" type="string">
      The raw JWT string for storage
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="vincentAppClient.removeVincentJWTFromURI" type="method">
  Removes the Vincent JWT query parameter from the current URL
</ParamField>

<ParamField path="vincentAppClient.redirectToConnectPage" type="method">
  Redirects user to Vincent Connect Page for authentication

  <Expandable title="parameters">
    <ParamField path="redirectUri" type="string" required>
      The URI to redirect back to after authentication. Must be one of your configured Authorized Redirect URIs.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="isExpired" type="function">
  Checks if a JWT has expired

  <Expandable title="parameters">
    <ParamField path="jwt" type="string" required>
      The JWT string to check
    </ParamField>
  </Expandable>

  <Expandable title="returns">
    <ParamField path="expired" type="boolean">
      Returns true if the JWT is expired, false otherwise
    </ParamField>
  </Expandable>
</ParamField>

```javascript theme={null}
import { getWebAuthClient } from '@lit-protocol/vincent-app-sdk/webAuthClient';
import { isExpired } from '@lit-protocol/vincent-app-sdk/jwt';

const vincentAppClient = getWebAuthClient({
  appId: process.env.MY_VINCENT_APP_ID
});

// Check for JWT in URL after Connect flow
if (vincentAppClient.uriContainsVincentJWT()) {
  const { decodedJWT, jwtStr } = vincentAppClient.decodeVincentJWTFromUri(
    window.location.origin
  );

  // Store JWT
  localStorage.setItem('VINCENT_AUTH_JWT', jwtStr);

  // Clean URL
  vincentAppClient.removeVincentJWTFromURI();
} else {
  // Check for existing JWT
  const storedJwt = localStorage.getItem('VINCENT_AUTH_JWT');
  const expired = storedJwt ? isExpired(storedJwt) : true;

  if (!storedJwt || expired) {
    // Redirect to Connect Page
    vincentAppClient.redirectToConnectPage({
      redirectUri: window.location.href
    });
  }
}
```

<Warning>
  The `redirectUri` must be one of your configured Authorized Redirect URIs.
</Warning>

## Backend Verification

Always verify JWTs submitted to your backend:

<ParamField path="verify" type="function">
  Verifies a Vincent JWT on your backend

  <Expandable title="parameters">
    <ParamField path="jwt" type="string" required>
      The Vincent JWT string returned from the Connect flow
    </ParamField>

    <ParamField path="audience" type="string" required>
      The redirect URI that received the JWT from the Vincent Connect Page
    </ParamField>
  </Expandable>

  <Expandable title="returns">
    <ParamField path="decodedJWT" type="object">
      The decoded and verified JWT object if valid
    </ParamField>
  </Expandable>
</ParamField>

```javascript theme={null}
import { verify } from '@lit-protocol/vincent-app-sdk/jwt';

const vincentJwt = '...'; // JWT from frontend
const jwtAudience = 'https://my-redirect-uri.com';

try {
  const decodedJWT = verify(vincentJwt, jwtAudience);
  // JWT is valid and was created specifically for your App
} catch (error) {
  // JWT is invalid, expired, or mis-scoped
}
```

<Warning>
  The verify method will throw an error if the JWT is invalid, expired, or mis-scoped.
</Warning>

## FAQ

<AccordionGroup>
  <Accordion title="What happens when a JWT expires?" icon="clock">
    When a JWT expires, you'll need to redirect the user back to the Vincent Connect Page using `redirectToConnectPage()`. Returning users will be able to quickly re-authenticate and get a new JWT without reconfiguring their Policies.
  </Accordion>

  <Accordion title="Can I use the same JWT across multiple domains?" icon="globe">
    No, JWTs are scoped to specific redirect URIs for security. Each domain needs its own JWT obtained through the Vincent Connect flow with that domain as the redirect URI.
  </Accordion>

  <Accordion title="How long are JWTs valid?" icon="timer">
    JWT expiration is set by the Vincent platform. Check the `exp` claim in the JWT to see when it expires (timestamp in seconds since Unix epoch).
  </Accordion>

  <Accordion title="Do I need to verify JWTs in my frontend?" icon="shield-check">
    The `decodeVincentJWTFromUri` method automatically validates JWTs in your frontend. However, you MUST always verify JWTs on your backend using the `verify` function before processing authenticated requests.
  </Accordion>

  <Accordion title="What's the difference between new and returning users?" icon="users">
    New users will see your App's requested Abilities and can configure Policies before granting permission. Returning users who have already authorized your App will simply confirm their identity and the App version they've authorized.
  </Accordion>

  <Accordion title="Can users revoke access to my App?" icon="user-minus">
    Yes. If access is revoked, the user will need to repermit the app before they can generate a new JWT for it. Execution of Vincent Abilities on their behalf will also fail.
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.