Authorization Flows - CSMS Developer Guide
Based on OCPP 2.0.1 Edition 4 Specification (Part 2). This guide covers all authorization flows from the CSMS (Charging Station Management System) perspective.
1. Overview
IntroductionAuthorization in OCPP 2.0.1 determines whether an EV Driver is allowed to charge at a Charging Station. The CSMS is the central authority that validates IdTokens and returns authorization decisions.
Core Concepts
IdToken
An identifier presented by the EV Driver (RFID card, app token, eMAID, etc.)
Authorization Cache
A local cache on the Charging Station that stores previously received authorization data from the CSMS. This is an autonomous Charging Station mechanism.
Local Authorization List
A CSMS-synchronized list of IdTokens stored on the Charging Station. The CSMS controls
this list via SendLocalListRequest.
Group IdToken
A parent token that links multiple individual IdTokens (e.g., a family or company account). Used for stopping transactions started by another token in the same group.
Relationship Between Authorization and Transactions
Authorization and transactions are decoupled in OCPP 2.0.1. The Charging Station
decides locally when to start/stop a transaction based on TxStartPoint and TxStopPoint configuration.
Authorization can happen before, during, or after a transaction starts. The CSMS receives authorization
requests and transaction events independently.
2. Key Data Types & Schemas
Reference2.1 IdTokenType
Sent by the Charging Station to identify the EV Driver.
{
"idToken": "string (max 36 chars, case-insensitive)",
"type": "IdTokenEnumType",
"additionalInfo": [ // optional
{
"additionalIdToken": "string (max 36)",
"type": "string (max 50)"
}
]
}IdTokenEnumType values:
| Value | Description |
|---|---|
Central | Identifier from the CSMS (used for GroupIdTokens) |
eMAID | Electro-Mobility Account Identifier (ISO 15118) |
ISO14443 | RFID card conforming to ISO 14443 (most common NFC cards) |
ISO15693 | RFID card conforming to ISO 15693 |
KeyCode | PIN code entered on keypad |
Local | Locally generated identifier (e.g., start button) |
MacAddress | MAC address-based identifier |
NoAuthorization | No authorization needed (AuthEnabled = false) |
2.2 IdTokenInfoType
Returned by the CSMS in responses to communicate the authorization decision.
{
"status": "AuthorizationStatusEnumType", // REQUIRED
"cacheExpiryDateTime": "date-time string", // optional
"chargingPriority": 0, // optional, integer -9 to 9
"language1": "string (max 8)", // optional, RFC 5646
"language2": "string (max 8)", // optional, RFC 5646
"evseId": [1, 2], // optional, array of integers
"groupIdToken": { // optional
"idToken": "string",
"type": "IdTokenEnumType"
},
"personalMessage": { // optional
"format": "MessageFormatEnumType", // REQUIRED
"content": "string (max 512)", // REQUIRED
"language": "string (max 8)" // optional, RFC 5646
}
}AuthorizationStatusEnumType values:
| Value | Description | CSMS Action |
|---|---|---|
Accepted | Token is valid, charging allowed | Token found and authorized |
Blocked | Token is blocked | Token is explicitly blocked in the system |
ConcurrentTx | Token is already in use in another transaction | Check for active transactions with this token |
Expired | Token has expired | Token validity period has passed |
Invalid | Token is unknown/invalid | Token not found in the system |
NoCredit | Token has no credit (prepaid) | Check balance for prepaid accounts |
NotAllowedTypeEVSE | Token not allowed on this EVSE type | Token has EVSE type restrictions |
NotAtThisLocation | Token not valid at this location | Token has location restrictions |
NotAtThisTime | Token not valid at this time | Token has time-of-day restrictions |
Unknown | Token status cannot be determined | CSMS cannot verify the token at this time |
MessageFormatEnumType values: ASCII, HTML, URI, UTF8
2.3 StatusInfoType
A generic type used in many responses to provide additional information about a status.
{
"reasonCode": "string (max 20)", // REQUIRED, case-insensitive predefined code
"additionalInfo": "string (max 512)" // optional, detailed human-readable information
}3. OCPP Messages Involved in Authorization
Protocol3.3 TransactionEventRequest (CS -> CSMS)
Sent by the Charging Station to report transaction lifecycle events. May contain idToken.
{
"eventType": "Started", // REQUIRED: Started | Updated | Ended
"timestamp": "2025-01-15T10:30:00Z", // REQUIRED
"triggerReason": "Authorized", // REQUIRED
"seqNo": 0, // REQUIRED, integer
"transactionInfo": { // REQUIRED
"transactionId": "uuid-string",
"chargingState": "Charging", // optional
"timeSpentCharging": 3600, // optional, seconds
"stoppedReason": "Local", // optional, only when eventType=Ended
"remoteStartId": 123 // optional
},
"idToken": { // optional
"idToken": "AABBCCDD",
"type": "ISO14443"
},
"evse": { "id": 1, "connectorId": 1 }, // optional
"meterValue": [...], // optional
"offline": false, // optional
"numberOfPhasesUsed": 3, // optional
"cableMaxCurrent": 32, // optional
"reservationId": 123 // optional
}ChargingStateEnumType values
| Value | Description |
|---|---|
Charging | EV is charging (energy is flowing) |
EVConnected | EV is connected but not charging |
SuspendedEV | Charging suspended by EV |
SuspendedEVSE | Charging suspended by EVSE |
Idle | No EV connected |
TriggerReasonEnumType values
| Value | When Sent |
|---|---|
Authorized | EV Driver has been authorized |
CablePluggedIn | Cable plugged in |
ChargingRateChanged | Charging rate has changed |
ChargingStateChanged | Charging state has changed |
Deauthorized | Authorization has been revoked |
EnergyLimitReached | Energy limit reached |
EVCommunicationLost | Communication with EV lost |
EVConnectTimeout | EV connection timeout |
EVDeparted | EV departed (parking bay) |
EVDetected | EV detected (parking bay) |
MeterValueClock | Clock-aligned meter value sample |
MeterValuePeriodic | Periodic meter value sample |
RemoteStart | Remote start requested |
RemoteStop | Remote stop requested |
ResetCommand | Reset command received |
SignedDataReceived | Signed meter data received |
StopAuthorized | Stop authorization received |
TimeLimitReached | Time limit reached |
Trigger | Triggered by TriggerMessage |
UnlockCommand | Unlock command received |
AbnormalCondition | Abnormal condition detected |
ReasonEnumType (stoppedReason) values
| Value | When Used |
|---|---|
DeAuthorized | Transaction deauthorized by CSMS (C15) |
EmergencyStop | Emergency stop button pressed |
EnergyLimitReached | Energy limit of transaction reached |
EVDisconnected | EV disconnected |
GroundFault | Ground fault detected |
ImmediateReset | Immediate reset command received |
Local | Stopped locally (unplug, stop button) |
LocalOutOfCredit | Local credit limit reached |
MasterPass | Stopped by Master Pass (C16) |
Other | Other reason |
OvercurrentFault | Overcurrent fault detected |
PowerLoss | Power loss detected |
PowerQuality | Power quality issue |
Reboot | Charging Station rebooting |
Remote | Stopped by CSMS via RequestStopTransaction |
SOCLimitReached | State of Charge limit reached |
StoppedByEV | Stopped by EV |
TimeLimitReached | Time limit reached |
Timeout | Transaction timed out |
3.4 TransactionEventResponse (CSMS -> CS)
The CSMS responds to acknowledge the transaction event. Can include updated authorization info.
{
"totalCost": 15.50, // optional, only when Ended
"chargingPriority": 0, // optional, overrides IdTokenInfo priority
"idTokenInfo": { // optional
"status": "Accepted",
"groupIdToken": {
"idToken": "GROUP001",
"type": "Central"
}
},
"updatedPersonalMessage": { // optional
"format": "UTF8",
"content": "Charging in progress..."
}
}CSMS implementation logic for TransactionEventResponse:
- Always: Acknowledge receipt (even an empty
{}response is valid) - On
eventType=StartedwithidToken: Validate the token and returnidTokenInfowith authorization status (C12.FR.03) - On
eventType=Ended: Optionally includetotalCost(omit = not free,0.00= free) - If token has groupIdToken: Include it in the response (C09.FR.12)
- If authorization status changed: Return updated
idTokenInfoto update the CS cache
3.5 RequestStartTransactionRequest (CSMS -> CS)
The CSMS can initiate a transaction remotely.
{
"remoteStartId": 123, // REQUIRED, integer
"idToken": { // REQUIRED
"idToken": "USER001",
"type": "Central"
},
"evseId": 1, // optional
"groupIdToken": { // optional
"idToken": "GROUP001",
"type": "Central"
},
"chargingProfile": { ... } // optional
}3.6 RequestStartTransactionResponse (CS -> CSMS)
{
"status": "Accepted", // REQUIRED: Accepted | Rejected
"statusInfo": { // optional
"reasonCode": "string (max 20)",
"additionalInfo": "string (max 512)"
},
"transactionId": "uuid-string" // optional, only when Accepted
}3.7 ClearCacheRequest (CSMS -> CS)
Used to clear the Authorization Cache on the Charging Station.
{}{
"status": "Accepted", // REQUIRED: Accepted | Rejected
"statusInfo": { // optional
"reasonCode": "string (max 20)",
"additionalInfo": "string (max 512)"
}
}5. Local Authorization List Management
D01-D02D01 - Send Local Authorization List
Direction: CSMS -> Charging Station
The CSMS can send either a full replacement list or a differential update.
{
"versionNumber": 5, // REQUIRED, integer > 0
"updateType": "Full", // REQUIRED: Full | Differential
"localAuthorizationList": [ // optional
{
"idToken": { // REQUIRED
"idToken": "AABBCCDD",
"type": "ISO14443"
},
"idTokenInfo": { // optional (absence = delete)
"status": "Accepted",
"cacheExpiryDateTime": "2025-12-31T23:59:59Z",
"groupIdToken": {
"idToken": "GROUP001",
"type": "Central"
}
}
}
]
}{
"status": "Accepted",
// REQUIRED: Accepted | Failed | VersionMismatch
"statusInfo": { // optional
"reasonCode": "string (max 20)",
"additionalInfo": "string (max 512)"
}
}Update Types:
| Type | Behavior |
|---|---|
Full | Replaces the entire list. If localAuthorizationList is empty/absent, clears the list. |
Differential | Adds/updates/removes individual entries. Entries WITH idTokenInfo are added/updated. Entries WITHOUT idTokenInfo are removed. |
CSMS Implementation Logic:
- Full update: Send all tokens with their idTokenInfo. The CS replaces its entire list.
- Differential update: To add/update a token: include both idToken and idTokenInfo. To remove a token: include only idToken (no idTokenInfo).
- Version management: Always increment versionNumber for each update. versionNumber must be > 0.
- Error handling: If CS returns Failed or VersionMismatch and the update was Differential, CSMS should resend the full list.
- Size constraints: The CS may limit message size via ItemsPerMessageSendLocalList and BytesPerMessageSendLocalList.
Requirements:
| ID | Requirement |
|---|---|
D01.FR.01 | SendLocalListRequest SHALL contain updateType and versionNumber |
D01.FR.03 | If Failed/VersionMismatch on Differential: CSMS SHOULD resend full list |
D01.FR.04 | Full update with no list: CS SHALL remove all IdTokens |
D01.FR.05 | Differential with empty list: no effect (version still updated) |
D01.FR.06 | All IdTokens in the list SHALL be unique |
D01.FR.15 | Full update with non-empty list: CS SHALL replace its list and set version |
D01.FR.16 | Differential with entries WITH idTokenInfo: CS SHALL add/update |
D01.FR.17 | Differential with entries WITHOUT idTokenInfo: CS SHALL remove |
D01.FR.18 | versionNumber SHALL be > 0 |
D01.FR.19 | Differential with versionNumber <= CS version: CS returns VersionMismatch |
[2, "msg030", "SendLocalList", {
"versionNumber": 1,
"updateType": "Full",
"localAuthorizationList": [
{
"idToken": { "idToken": "USER001", "type": "ISO14443" },
"idTokenInfo": {
"status": "Accepted",
"groupIdToken": { "idToken": "GROUP_A", "type": "Central" }
}
},
{
"idToken": { "idToken": "USER002", "type": "ISO14443" },
"idTokenInfo": { "status": "Accepted" }
},
{
"idToken": { "idToken": "USER003", "type": "ISO14443" },
"idTokenInfo": { "status": "Blocked" }
}
]
}][2, "msg031", "SendLocalList", {
"versionNumber": 2,
"updateType": "Differential",
"localAuthorizationList": [
{
"idToken": { "idToken": "USER004", "type": "ISO14443" },
"idTokenInfo": { "status": "Accepted" }
}
]
}][2, "msg032", "SendLocalList", {
"versionNumber": 3,
"updateType": "Differential",
"localAuthorizationList": [
{
"idToken": { "idToken": "USER003", "type": "ISO14443" }
}
]
}][2, "msg033", "SendLocalList", {
"versionNumber": 4,
"updateType": "Full"
}]D02 - Get Local List Version
Direction: CSMS -> Charging Station
CSMS queries the current version of the Local Authorization List on a Charging Station.
{}{
"versionNumber": 5 // REQUIRED, integer
}CSMS Responsibilities:
- Send GetLocalListVersionRequest before updating to determine the current version
versionNumber = 0means: no Local Authorization List installed- Use the response to decide whether a Full or Differential update is needed
| ID | Requirement |
|---|---|
D02.FR.01 | If LocalAuthListEnabled = true: CS SHALL respond with its list version |
D02.FR.02 | If enabled but no update ever received: CS responds with versionNumber = 0 |
D02.FR.03 | If LocalAuthListEnabled = not true: CS responds with versionNumber = 0 |
6. Configuration Variables Reference
ConfigThese are configuration variables on the Charging Station that affect authorization behavior.
The CSMS can read/write these via GetVariables/SetVariables messages.
Authorization Related (AuthCtrlr)
| Variable | Type | Mutability | Description |
|---|---|---|---|
AuthEnabled | boolean | ReadWrite | If false, no authorization is done before starting a transaction. IdToken type will be NoAuthorization. |
AdditionalInfoItemsPerMessage | integer | ReadOnly | Max additionalInfo items per message. CSMS expected to handle arbitrary amounts. |
OfflineTxForUnknownIdEnabled | boolean | ReadWrite | If true, CS accepts unknown tokens when offline. |
AuthorizeRemoteStart | boolean | RO/RW | If true, CS sends AuthorizeRequest before starting a remote transaction. |
LocalAuthorizeOffline | boolean | ReadWrite | If true, CS starts transactions for locally-authorized tokens when offline. |
LocalPreAuthorize | boolean | ReadWrite | If true, CS starts transactions for locally-authorized tokens immediately when online. |
MasterPassGroupId | string | ReadWrite | GroupId value that identifies Master Pass tokens. |
DisableRemoteAuthorization | boolean | ReadWrite | If true, CS does not send AuthorizeRequests and only uses Cache/Local List. |
SupportedIdTokenTypes | MemberList | ReadOnly | Subset of IdTokenEnumType supported by the CS. |
Authorization Cache Related (AuthCacheCtrlr)
| Variable | Type | Mutability | Description |
|---|---|---|---|
AuthCacheEnabled | boolean | ReadWrite | Enables/disables the Authorization Cache. |
AuthCacheAvailable | boolean | ReadOnly | Whether Authorization Cache is supported. |
AuthCacheLifeTime | integer (s) | ReadWrite | How long a token stays in cache since last used. |
AuthCacheStorage | integer | ReadOnly | Bytes used by cache (maxLimit = max capacity). |
AuthCachePolicy | OptionList | ReadWrite | Cache replacement policy: LRU, LFU, FIFO, CUSTOM. |
AuthCacheDisablePostAuthorize | boolean | ReadWrite | If true, disables re-authorization for non-Accepted cached tokens. |
AuthCacheEntries | integer | ReadOnly | Number of entries in cache (maxLimit = max capacity). |
Local Authorization List Related (LocalAuthListCtrlr)
| Variable | Type | Mutability | Description |
|---|---|---|---|
LocalAuthListEnabled | boolean | ReadWrite | Enables/disables the Local Authorization List. |
LocalAuthListEntries | integer | ReadOnly | Number of entries (maxLimit = max capacity). |
LocalAuthListAvailable | boolean | ReadOnly | Whether Local Authorization List is supported. |
ItemsPerMessageSendLocalList | integer | ReadOnly | Max items in a single SendLocalListRequest. |
BytesPerMessageSendLocalList | integer | ReadOnly | Max bytes for a SendLocalListRequest. |
LocalAuthListStorage | integer | ReadOnly | Bytes used (maxLimit = max capacity). |
LocalAuthListDisablePostAuthorize | boolean | ReadWrite | If true, disables re-authorization for non-Accepted local list tokens. |
LocalAuthListSupportsExpiryDateTime | boolean | ReadOnly | If true, CS enforces cacheExpiryDateTime in local list. |
Transaction Related (TxCtrlr)
| Variable | Type | Mutability | Description |
|---|---|---|---|
TxStartPoint | MemberList | RO/RW | Events that trigger TransactionEventRequest(Started). Values: ParkingBayOccupancy, EVConnected, Authorized, PowerPathClosed, EnergyTransfer, DataSigned |
TxStopPoint | MemberList | RO/RW | Events that trigger TransactionEventRequest(Ended). Same values as TxStartPoint. |
EVConnectionTimeOut | integer (s) | ReadWrite | Timeout for EV to connect after authorization. |
StopTxOnInvalidId | boolean | ReadWrite | If true, stop transaction when CSMS returns non-Accepted for a previously offline-authorized token. |
MaxEnergyOnInvalidId | integer (Wh) | ReadWrite | Max energy allowed when token is invalid but StopTxOnInvalidId = false. |
StopTxOnEVSideDisconnect | boolean | RO/RW | If true, deauthorize when cable is unplugged. |
7. CSMS Implementation Decision Matrix
ImplementationWhen Receiving TransactionEventRequest
TransactionEventRequest received
|
+-- eventType = "Started"?
| |
| +-- Has idToken?
| | |
| | +-- Validate token -> Return idTokenInfo in response
| | +-- Has groupIdToken? -> Include in response
| | +-- Is MasterPass token? -> Return non-Accepted (C16.FR.03)
| |
| +-- Record transaction start (transactionId, EVSE, timestamp)
|
+-- eventType = "Updated"?
| |
| +-- Has idToken? -> Re-validate, return updated idTokenInfo
| +-- Update transaction state (chargingState, meterValue)
|
+-- eventType = "Ended"?
| |
| +-- Record transaction end
| +-- Calculate totalCost (optional)
| +-- stoppedReason = "MasterPass"? -> Log Master Pass stop
| +-- stoppedReason = "DeAuthorized"? -> Log deauth reason
| +-- Return totalCost (omit = not free, 0.00 = free)
|
+-- Check seqNo for completeness (ensure no gaps)
+-- Return TransactionEventResponseWhen to Send RequestStartTransactionRequest
Remote start trigger (e.g., mobile app request)
|
+-- Build RequestStartTransactionRequest
| |
| +-- remoteStartId: unique integer
| +-- idToken: the user's token (type = "Central")
| +-- evseId: specific EVSE (optional)
| +-- groupIdToken: if user belongs to a group (optional)
| +-- chargingProfile: if specific charging constraints (optional)
|
+-- Send to Charging Station
|
+-- Response = "Accepted"?
| |
| +-- YES: Wait for TransactionEventRequest(Started) with matching remoteStartId
| +-- NO: Inform user that remote start was rejected
|
+-- If AuthorizeRemoteStart = true:
CS will send AuthorizeRequest -> Respond with AuthorizeResponseWhen to Send SendLocalListRequest
List update needed (new user, blocked user, periodic sync)
|
+-- Get current version: Send GetLocalListVersionRequest
|
+-- versionNumber = 0? (no list installed)
| |
| +-- Send Full update with all tokens
|
+-- Small change?
| |
| +-- Send Differential update (add/update/remove specific tokens)
| +-- versionNumber must be > CS's current version
|
+-- Large change or full sync needed?
| |
| +-- Send Full update
| +-- If too large for one message:
| +-- Send initial Full (first batch)
| +-- Send subsequent Differential updates until complete
|
+-- Response = "VersionMismatch"?
| |
| +-- Resend as Full update
|
+-- Response = "Failed"?
|
+-- Resend as Full update