# Identity and access management

So you want to run the login and have Iteras decide what each logged-in user has access to, typically whether the person may read the article they just opened. This page covers how to build that. It assumes the machinery described in synchronizing with an external system is set up with a webhook.

Before building, it is worth deciding whether identity should live outside Iteras at all. The Iteras self-service and paywall handle sign-in, password resets and one-time passwords out of the box, they are brandable, and they keep working as we add features - while everything on this page is something you take on building and maintaining. If it mainly exists because it was there first, consider letting Iteras handle sign-in instead. But if the external identity has to stay, this page is for you.

# What decides access

Iteras models a person as a customer with subscriptions. A subscription runs in periods, each period is on a campaign, and the period grants a set of subscription products - see concepts and terminology.

Build your access rules on the subscription products, not on campaigns. Campaigns are commercial packaging - prices and offers that come and go - while the products are the durable layer, and they carry an external_id you control.

Ask for subscriptions with their current period, and you get the products:

GET /api/customers/?id=141280&fields=data,subscriptions,subscriptions.current_period
{
  "customers": [
    {
      "id": "141280",
      "data": { "name": "Jane Doe", "email": "jane@example.com" },
      "subscriptions": [
        {
          "id": "7612471",
          "state": "active",
          "current_period": {
            "id": "835270",
            "campaign_id": "12MPRO",
            "begin": "2026-06-28",
            "end": "2027-06-28",
            "subscribed_to": [
              { "name": "Digital access", "external_id": "digital" },
              { "name": "Archive", "external_id": "archive" }
            ]
          }
        }
      ]
    }
  ]
}

The entitlement calculation on your side is then: for each subscription in state active, take the external_id of everything in the current period's subscribed_to, and union them. That set is what the user has access to. Store it on your user record, and you have a local answer to the access question.

Two other subscription states deserve a deliberate decision rather than being lumped in with "no access": suspended means the subscription has not been paid and is being sanctioned; awaiting means a paid subscription that starts on a future date, which is different from not having one.

# Which events change access

Set the webhook up with the customer and subscription to paywall event categories. The paywall category is narrow, carrying the events that can change what a person has access to, leaving out renewals and other information. The customer events keep your user record current, and subscription:created, subscription:updated, subscription:changed-status and subscription:changed-campaign cover subscriptions appearing, changing state and changing content.

Rather than mapping each event type to a specific change, recompute the whole entitlement set for the affected customer whenever any of them arrives. This is simple, idempotent, and an event you did not anticipate becomes a harmless recomputation. Turn on prefetching with data,subscriptions,subscriptions.current_period so every event carries what the recomputation needs.

Note that access changes are not announced in advance: a subscription whose period ends tonight produces its status change when it happens. If you cache entitlements with an expiry, use the current period's end and re-evaluate when it passes.

# Checking access at request time

With entitlements stored locally, the check on each page view is a local lookup, and that is how it should be - an article request should usually not wait on an HTTP call to the Iteras server.

For the occasional case where you need a definitive answer right now - a support screen, a high-value action - read /api/customers/?id=... directly. Just keep that off the hot path.

If parts of your site use the Iteras paywall as well, its pass cookie is signed with a key from your account settings and carries the access level and customer number - a server-side check with no API call, which fits a static or heavily cached front end.

# Single sign-on into the self-service

You can use your own login with the self-service. Once your login has established who the user is, ask the API for a short-lived pre-authentication token for the matching Iteras customer:

GET /api/customers/?id=141280&fields=data,preauth_token&preauthseconds=300
{
  "customers": [
    {
      "id": "141280",
      "data": {
        "name": "Jane Doe",
        "preauth_token": "Azxd123:JOIj123:JOjOIJASDF"
      }
    }
  ]
}

Then send the user on to the self-service with the token appended as iteraspreauth:

https://app.iteras.dk/yourservice/?iteraspreauth=Azxd123%3AJOIj123%3AJOjOIJASDF

This works for a stand-alone page as well as embedded components. Keep preauthseconds short, a few minutes at most: the token is a bearer credential that ends up in browser history, and it only has to survive one redirect.

The token does not depend on the user's password, which is the point. You are not proving the user's password to Iteras, you are asserting an identity you have already verified.

If Iteras holds the passwords and you are building a login screen in front of them, use /api/authenticatecustomer/ instead, which verifies an ID or email plus password and can return a pre-auth token in the same call. Mind the note about putting a rate limit in front.

# Turning off the built-in login

When identity lives in your system, Iteras can be configured so that customers are never offered a second way to sign in. Turn on external login for customers in the customer service settings, and the self-service and paywall stop showing their own login and instead send anyone who needs to sign in to your login page. Turn on external passwords for customers in the account settings, and Iteras stops managing passwords entirely - no password on the customer, no reset flow, no password links in emails.

Beyond that, you can choose which login methods Iteras accepts if it should still handle some sign-ins, and you can point the self-service URL to the page on your own site where the self-service is embedded, so outgoing emails link there.