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

# Server-side verification

When an end user connects their wallet, you, the developer, get a [JSON Web Token (JWT)](https://jwt.io/introduction) that can be used to verify some claims about the end user, notably a proof of ownership over a wallet public address.

Upon authentication, we generate a JWT signed with a private key (using RS256 algorithm) that is unique to you. In turn, you can use the associated public key (found in the [API tab](https://app.dynamic.xyz/dashboard/api) of your developer dashboard) to ensure that the token is authentic and hasn't been tampered with. In other words, if a JWT issued by Dynamic can be successfully verified with your public key, the information it contains can be trusted.

You can do this in multiple ways.

#### Option 1: Leverage [NextAuth](https://next-auth.js.org/)

If you are using Next.js, you can easily [integrate the NextAuth library with Dynamic](/guides/frameworks/next-auth) to perform server-side verification and then use a session client-side.

#### Option 2: Leverage [Passport.js](https://www.passportjs.org)

We offer an official [passport-dynamic](https://github.com/dynamic-labs/passport-dynamic) extension.

#### Option 3: Do-It-Yourself Verification

1. Get the JWT through the Dynamic SDK with an [authToken](/react-sdk/utilities/getauthtoken).
2. Send the authToken to the server as a Bearer token

```JavaScript
import { useEffect, useState } from "react";

export const useFetch = (authToken: string | null) => {
  const [data, setData] = useState({});

  useEffect(() => {
    const fetchApi = async () => {
      await fetch("http://localhost:9000/api", {
        headers: {
          Authorization: `Bearer ${authToken}`,
        },
      }).then(response => response.json()).then(setData);
    }

    fetchApi()
  }, [authToken]);

  return { data };
};
```

3. Install the [node-jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) and [jwks-rsa](https://www.npmjs.com/package/jwks-rsa) packages
4. Validate the JWT on your server by fetching the public key from the [JWKS endpoint](https://docs.dynamic.xyz/api-reference/sdk/find-jwks-for-public-key) API endpoint and verifying the encoded JWT against the public key:

```TypeScript
import jwt, { JwtPayload } from 'jsonwebtoken';
import { JwksClient } from 'jwks-rsa';

// can be found in https://app.dynamic.xyz/dashboard/developer/api
const jwksUrl = `https://app.dynamic.xyz/api/v0/sdk/${YOUR_DYNAMIC_ENV_ID}/.well-known/jwks`

// The client should be initialized as
const client = new JwksClient({
  jwksUri: jwksUrl,
  rateLimit: true,
  cache: true,
  cacheMaxEntries: 5,  // Maximum number of cached keys
  cacheMaxAge: 600000 // Cache duration in milliseconds (10 minutes in this case))}
 });

const signingKey = await client.getSigningKey();
const publicKey = signingKey.getPublicKey();

const decodedToken: JwtPayload = jwt.verify(encodedJwt, publicKey, {
  ignoreExpiration: false,
}) as JwtPayload;

if (decodedToken.scopes.includes('requiresAdditionalAuth')) {
  // Either reject or handle the scopes appropriately.
  // `requiresAdditionalAuth` is the scope used to indicate that JWT requires additional verification such as MFA.
  throw new Error('Additional verification required');
}

console.log(decodedToken) // { iss: 'xxxx', exp: nnnn, ... }
```

This uses the following libraries:

* [jwks-rsa](https://www.npmjs.com/package/jwks-rsa): Provides client to interact and parse JWKS key signing data for a JWT.
* [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken): Provides library to encode/decode and validate a JWT token.
