Table of Contents

Access & Authentication

How to get access to our delivery API

DynamicWeb supports two authentication mechanisms, each optimized for a different purpose:

  • Cookie-based authentication — used by traditional (SSR) DynamicWeb websites implemented in razor templates. When a user logs in through an Extranet login form, a Dynamicweb.Extranet cookie is issued. This cookie automatically authenticates the user for all browser-based page requests.

  • Token-based authentication (JWT) — used by the Delivery API for headless and API-driven scenarios. Instead of relying on cookies, API clients send a Bearer token in the Authorization header. This makes the API suitable for client-side apps, mobile apps, and integrations.

In most cases, these two systems operate independently. However, when you want a user who is already logged in on your traditional DynamicWeb site to also access the Delivery API (for example, to load personalized content or order data dynamically), you can bridge the two by exchanging the user’s authenticated cookie for a JWT.

Many endpoints in the delivery API supports both anonymous and authenticated requests. If a user is authenticated, permissions and personalization will take affect on a given endpoint - changing returned data like prices, what content is available, discounts, assortments and other user dependent information.

Some endpoints always require authentication, e.g. endpoints related to users, order histories, and favorites.

Token-based authentication (JWT)

Authentication works through authenticating with a username and password. This returns a JWT containing the necessary information to identify the user and the validity of the token.

To authenticate a user and obtain a JWT, use the authenticate endpoint.

Using GET:

GET <yourHost>/dwapi/users/authenticate?userName=DemoUser&password=TestPassword123

Using POST:

POST <yourHost>/dwapi/users/authenticate
{
  "username": "DemoUser",
  "password": "TestPassword123"
}

Response would look like the following:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIxMyIsIm5iZiI6MTY4NDgyMTQ1MywiZXhwIjoxNjg0ODIyMDUzLCJpYXQiOjE2ODQ4MjE0NTMsImlzcyI6IkR5bmFtaWN3ZWIgQS9TIiwiYXVkIjoiV2ViQVBJIn0.E6qnfrmb2adq3SvFpyatjXsy78xf2SZxuVhCr1EJTXQ"
}

This token has to be stored in the client (your app) and then subsequently used in most of the other endpoints where authentication is required to handle on a specific user or with specific permissions or personalization.

The returned JWT has to be used as a header authorization bearer token:

authorization: Bearer <token>

where <token> is the value returned in the authenticate response, e.g.:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIxMyIsIm5iZiI6MTcxMzg4ODk5OCwiZXhwIjoxNzEzOTc1Mzk4LCJpYXQiOjE3MTM4ODg5OTgsImlzcyI6IkR5bmFtaWN3ZWIgQS9TIiwiYXVkIjoiV2ViQVBJIn0.Q1xPxgNqp9ahjexB0nl7xz5iv52q22mTOljj5va1a5U

JWTs are valid for a specific time. Default expiration for JWT in DynamicWeb is 1800 seconds, which is 30 minutes. This can be made shorter or longer when calling the authenticate endpoint. Longer expiration times are more insecure.

Refreshing the JWT

Before the token expires, it has to be refreshed, so your app should keep track of when the token was created so it can be refreshed before it expires. If a refresh is not made before the timeout, the login expires and the user has to authenticate again.

Refreshing the token is done using the refresh endpoint and passing in the Bearer token as well:

authorization: Bearer <token>

GET <yourHost>/dwapi/users/authenticate/refresh?expirationInSeconds=600

Which will provide a new token with a new expiration.

On a regular DynamicWeb website, user authentication is managed through the Dynamicweb.Extranet cookie. This cookie is automatically issued when a user logs in using the standard DynamicWeb login flow, and it keeps them authenticated across the site.

The Delivery API, however, uses JWT (JSON Web Tokens) for authentication. JWTs are lightweight, self-contained tokens that work well for API-based or headless scenarios — but they are not compatible with cookie-based authentication out of the box.

To connect the two authentication systems, DynamicWeb provides an endpoint that converts an existing authenticated session into a short-lived JWT token:

POST /dwapi/auth/token

When a logged-in user calls this endpoint, the server validates the Dynamicweb.Extranet cookie and issues a JWT token. That token can then be used to authenticate any Delivery API requests. This allows your logged-in users to securely access /dwapi/* endpoints from the same session without requiring the user to log in twice.

An example flow could look like this:

  1. A user logs into your traditional DynamicWeb website (Extranet).
  2. The login sets a Dynamicweb.Extranet authentication cookie.
  3. Your frontend calls /dwapi/auth/token to exchange that cookie for a JWT.
  4. The returned JWT is used in Authorization: Bearer headers for any Delivery API calls.

Example request and response

POST /dwapi/auth/token
Content-Type: application/json

Response:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

The returned token is valid for 30 minutes (1800 seconds) by default. You can specify a custom lifetime (up to 86400 seconds, or 24 hours) by including the expirationInSeconds parameter in the request body:

POST /dwapi/auth/token
Content-Type: application/json

{
  "expirationInSeconds": 3600
}

If the requested expiration exceeds the allowed maximum, the endpoint returns a 403 Forbidden response.

Example JavaScript usage

Here’s how to exchange the cookie for a token and use it to call another Delivery API endpoint from a logged-in session:

async function getDeliveryApiToken() {
  const response = await fetch('/dwapi/auth/token', {
    method: 'POST',
    credentials: 'include', // include the login cookie
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ expirationInSeconds: 1800 })
  });

  if (!response.ok) {
    throw new Error('Failed to get token');
  }

  const data = await response.json();
  return data.token;
}

async function fetchUserInfo() {
  const token = await getDeliveryApiToken();

  const res = await fetch('/dwapi/users/info', {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });

  const userInfo = await res.json();
  console.log(userInfo);
}

fetchUserInfo();
Note

Please note that:

  • The credentials: 'include' flag ensures that the user’s existing authentication cookie is sent with the request
  • The returned JWT can be used in the Authorization header for any Delivery API endpoint
  • For security, store tokens only in memory (not in localStorage or cookies)
  • Tokens should be refreshed periodically when the session is still valid

Impersonation

Impersonating lets you act in the role as another specific user, as long as you have the proper permissions to do so. You will simply be granted another token to use, which will have the identity of the user that's being impersonated.

To list all the users that's allowed to be impersonated with the given JWT token in the request, use:

GET <yourHost>/dwapi/users/impersonatees

Including a header such as:

authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIxMyIsIm5iZiI6MTY4NDgyMTQ1MywiZXhwIjoxNjg0ODIyMDUzLCJpYXQiOjE2ODQ4MjE0NTMsImlzcyI6IkR5bmFtaWN3ZWIgQS9TIiwiYXVkIjoiV2ViQVBJIn0.E6qnfrmb2adq3SvFpyatjXsy78xf2SZxuVhCr1EJTXQ`

The response is a list of users that can be impersonated

[
  {
    "address": "Vejnavn 1",
    "city": "Aalborg",
    "company": "Company Customer DK",
    "country": "Denmark",
    "countryCode": "DK",
    "email": "noreply@dynamicweb.dk",
    "id": 87,
    "name": "Company Customer DK",
    "phone": "87654321",
    "userName": "CompanyCustomerDK",
    "zip": "9000",
  },
  {
    "email": "noreply@dynamicweb.dk",
    "id": 88,
    "name": "Company Customer UK",
    "userName": "CompanyCustomerUK",
  }
]

Impersonating one of these users is now as simple as calling GET <yourHost>/dwapi/users/impersonate?userId=87 With the authorization header as the previous request.

The response will the contain a new token for the specified user

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiI4NyIsIm5iZiI6MTY4NDgyMzA0MCwiZXhwIjoxNjg0ODIzNjQwLCJpYXQiOjE2ODQ4MjMwNDAsImlzcyI6IkR5bmFtaWN3ZWIgQS9TIiwiYXVkIjoiV2ViQVBJIn0.SpwDL7pq2LjcXSoZiaZ3hqdT3nU3X0JE4ZIBzBPlEnA"
}
To top