Skip to main content

Node.js

Official

Server-side SDK for verifying tokens and securing Node.js services.

Accessing Protected APIs

~5 min

This guide shows how to retrieve the user's access token from the ThunderID Node.js SDK and use it to call protected downstream APIs.

Accessing Protected APIs

1

Prerequisites

- Complete the [Handling Authentication](../handling-authentication) guide to set up the client and session management. - The user must be signed in before you retrieve an access token.

2

Retrieve the Access Token

Use the `getAccessToken` method to retrieve the access token for the current user session.

src/services/userService.ts
ts

export async function fetchUserProfile(sessionId: string) {
  const accessToken = await auth.getAccessToken(sessionId)

  const response = await fetch('https://localhost:8090/users/<user_id>', {
    headers: {
      Authorization: `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
    },
  })

  if (!response.ok) {
    throw new Error(`API request failed: ${response.status}`)
  }

  return response.json()
}
3

Call a Protected API from a Route

Use the service function in a route handler that already requires authentication.

src/routes/profile.ts
ts

app.get('/profile', requireAuth, async (req, res) => {
  const sessionId = req.cookies[CookieConfig.SESSION_COOKIE_NAME]

  try {
    const profile = await fetchUserProfile(sessionId)
    res.render('profile', { profile })
  } catch (error) {
    res.status(500).render('error', { message: 'Failed to load profile.' })
  }
})
4

Send Multiple Requests in Parallel

Use `Promise.all` to send multiple authenticated requests concurrently.

src/services/dashboardService.ts
ts

export async function fetchDashboardData(sessionId: string) {
  const accessToken = await auth.getAccessToken(sessionId)

  const headers = {
    Authorization: `Bearer ${accessToken}`,
    'Content-Type': 'application/json',
  }

  const [profile, organizations] = await Promise.all([
    fetch('https://localhost:8090/users/<user_id>', { headers }).then(r => r.json()),
    fetch('https://localhost:8090/organizations', { headers }).then(r => r.json()),
  ])

  return { organizations, profile }
}
5

Handle Token Expiry

The SDK refreshes the access token automatically when `isSignedIn` is called (for example, in your authentication middleware). This means that by the time a route handler executes, the access token is already up to date. If you call `getAccessToken` outside a middleware-protected route, verify the session first:

ts
const signedIn = await auth.isSignedIn(sessionId)

if (!signedIn) {
  throw new Error('User is not signed in.')
}

const accessToken = await auth.getAccessToken(sessionId)
6

Use the Token Exchange Flow

For advanced scenarios such as impersonation or delegated access, use `exchangeToken` to get a token with a different scope or for a different subject.

ts

const newTokens = await auth.exchangeToken(
  {
    attachToken: false,
    data: {
      client_id: '<your-client-id>',
      grant_type: 'account_switch',
      scope: 'openid profile',
      token: currentAccessToken,
    },
    id: 'account-switch',
    returnResponse: true,
    returnsSession: true,
    signInRequired: true,
  },
  sessionId,
)
7

Revoke an Access Token

To revoke the access token when the user signs out or when you want to invalidate a session immediately, call `revokeAccessToken`.

ts
await auth.revokeAccessToken(sessionId)
8

Next Steps

- [Protecting Routes](../protecting-routes): Restrict access to routes based on authentication state - [`ThunderIDNodeClient`](../../apis/clients/thunderid-node-client): Base client class reference

ThunderID LogoThunderID Logo

Product

DocsAPIsSDKs
© Copyright Linux Foundation Europe.For web site terms of use, trademark policy and other project policies please see https://linuxfoundation.eu/en/policies.