PHP2Shell alert: critical PHP flaws CVE-2026-109618 / 109619 — check your servers and get patched fast
HashTech Systems
EV Charging
Part 5 of 11

OCPP 2.0.1 Authorization: IdTokens, Local Lists and Remote Start

IdTokenType and its types, Authorize and IdTokenInfo, the authorization cache, local lists, group tokens and RequestStartTransaction in OCPP 2.0.1.

HashTech Engineering · October 26, 2026 · 5 min read

Authorization in 2.0.1 covers the same ground as 1.6 (RFID cards, app starts, offline lists), but the data model is richer. A token is no longer a bare string, there are more status values, and remote start has been renamed and tightened. This article covers functional blocks C (Authorization), D (Local Authorization List Management) and the remote start/stop parts of F (Remote Control).

IdTokenType

In 1.6 an idTag was a string of up to 20 characters. In 2.0.1 an IdTokenType is an object with the token value (up to 36 characters), a mandatory type, and optional additionalInfo:

json
{
  "idToken": "04A2B3C4D5E680",
  "type": "ISO14443"
}
IdTokenEnumTypeUsed for
ISO14443RFID cards (MIFARE and similar), UID as hex
ISO15693Vicinity RFID cards
eMAIDE-mobility account identifiers, including Plug & Charge contracts
CentralTokens generated by the CSMS, for example for app-started sessions
LocalTokens generated locally by the station
KeyCodePIN or code entered on the station
MacAddressEV MAC address (Autocharge-style identification)
NoAuthorizationFree vend, no authorization needed

Authorize and IdTokenInfo

json
[2, "au-0101", "Authorize", {
  "idToken": {
    "idToken": "04A2B3C4D5E680",
    "type": "ISO14443"
  }
}]

[3, "au-0101", {
  "idTokenInfo": {
    "status": "Accepted",
    "cacheExpiryDateTime": "2026-11-26T00:00:00.000Z",
    "groupIdToken": {
      "idToken": "FLEET-ACME-01",
      "type": "Central"
    },
    "language1": "en",
    "personalMessage": {
      "format": "UTF8",
      "content": "Welcome back. Fleet tariff applies."
    }
  }
}]

status (AuthorizationStatusEnumType) can be Accepted, Blocked, ConcurrentTx, Expired, Invalid, NoCredit, NotAllowedTypeEVSE, NotAtThisLocation, NotAtThisTime or Unknown. The extra values over 1.6 are worth using: NoCredit and NotAtThisLocation give the station something specific to display. Optional fields include cacheExpiryDateTime, chargingPriority, language1/language2, evseId (restrict the token to specific EVSEs), groupIdToken and personalMessage (shown to the driver, see part 9).

AuthorizeRequest also has optional certificate and iso15118CertificateHashData fields, and the response an optional certificateStatus. Those are for contract certificates in Plug & Charge and are covered in part 8.

Group tokens

groupIdToken ties several tokens together, typically all cards for one fleet or household. Its main use is stopping: a transaction started with one card can be stopped with any other card in the same group (use case C09, Authorization by GroupId). Stations compare group tokens they have from the cache or local list; if a group is unknown locally, the station asks the CSMS. Return groupIdToken consistently for every token in the group, including in TransactionEventResponse, or stops with a colleague's card will fail.

The authorization cache

Stations may remember the result of recent authorizations (use case C10). The cache is controlled by AuthCacheCtrlr variables: whether it is enabled, the LifeTime of entries, and storage limits. cacheExpiryDateTime in IdTokenInfo overrides the default lifetime for that entry. ClearCache empties it, with response Accepted or Rejected.

When the station is online and AuthCtrlr.LocalPreAuthorize is true, it may start immediately for a token that is valid in the cache or local list without waiting for the CSMS. The CSMS still sees the token in the TransactionEvent and can deauthorize it via idTokenInfo in the response. When offline, AuthCtrlr.LocalAuthorizeOffline decides whether cached and listed tokens are honoured, and OfflineTxForUnknownIdEnabled whether unknown tokens are allowed to charge at all (C15).

Local authorization list

The local list (block D) is a CSMS-managed list of tokens that the station should honour, distinct from the cache because the CSMS controls its contents. It is versioned: GetLocalListVersion returns the station's current versionNumber, and SendLocalList installs a Full replacement or a Differential update.

json
[2, "sll-55", "SendLocalList", {
  "versionNumber": 43,
  "updateType": "Differential",
  "localAuthorizationList": [
    {
      "idToken": { "idToken": "04A2B3C4D5E680", "type": "ISO14443" },
      "idTokenInfo": { "status": "Accepted" }
    },
    {
      "idToken": { "idToken": "049988776655AA", "type": "ISO14443" }
    }
  ]
}]

[3, "sll-55", {
  "status": "Accepted"
}]

In a Differential update, an entry with idTokenInfo adds or updates the token, and an entry without idTokenInfo removes it. Response status is Accepted, Failed or VersionMismatch. Batch large lists according to LocalAuthListCtrlr.ItemsPerMessage and BytesPerMessage, and read Entries to know the station's capacity.

Remote start and stop

1.6's RemoteStartTransaction and RemoteStopTransaction become RequestStartTransaction and RequestStopTransaction. The names changed for a reason: the CSMS requests, and the station decides when (and whether) a transaction actually starts, according to its TxStartPoint.

json
[2, "rs-9001", "RequestStartTransaction", {
  "evseId": 1,
  "remoteStartId": 880213,
  "idToken": {
    "idToken": "app-user-5b1c9e",
    "type": "Central"
  }
}]

[3, "rs-9001", {
  "status": "Accepted"
}]

remoteStartId is an integer chosen by the CSMS, echoed back in transactionInfo.remoteStartId of the TransactionEvent that the request caused (with triggerReason RemoteStart). That is how you correlate an app tap to a transaction. If the EVSE already has a transaction (for example the cable was plugged in first and TxStartPoint includes EVConnected), the response includes its transactionId. Optional fields include chargingProfile (a TxProfile to apply, see part 6) and groupIdToken.

If AuthCtrlr.AuthorizeRemoteStart is true, the station sends Authorize for the token before starting; most CSMS operators set it to false because the CSMS already authorized the user in the app. Response status is Accepted or Rejected, nothing more: acceptance only means the station will try.

json
[2, "rq-9002", "RequestStopTransaction", {
  "transactionId": "7f3c2a10-5e61-4b8e-9d2a-0c4b1e8f6a33"
}]

[3, "rq-9002", {
  "status": "Accepted"
}]

The stop is confirmed by a TransactionEvent Ended with triggerReason RemoteStop and stoppedReason Remote (use case F03). Do not mark the session stopped on the Accepted alone.

Field gotchas

  • Unplug-to-start timeouts. After a remote start with no cable connected, the station waits TxCtrlr.EVConnectionTimeOut seconds. Show this countdown in your app, or users will think the start failed.
  • Stopping with a different card. Without consistent groupIdToken, only the starting card can stop the session.
  • Free vend stations. NoAuthorization tokens still appear in TransactionEvent. Do not treat them as unknown users.
  • Master pass. Use case C16 covers a master pass that can stop any transaction, configured via a group id on AuthCtrlr; make sure your billing treats those stops as operator actions.
  • Reservations. ReserveNow takes an idToken and optional groupIdToken as well; the same matching rules apply.

Next

Next up is smart charging in 2.0.1. The 1.6 equivalents are covered in Authorize and id tags and remote start/stop in 1.6, and the roaming side of tokens in OCPI tokens and real-time authorization.

Let's Talk

Ready to build something that lasts?

Whether it's a charging network, an AI rollout, or a core enterprise system — let's talk about what you're building.