OCPP chargers normally depend on the CSMS (coming soon) for user authorization. When you tap your RFID card, the charger sends an Authorize message to the CSMS, the CSMS checks (often querying the user’s eMSP via OCPI), and responds with Accepted or Invalid.
But what if the charger can’t reach the CSMS? Cellular outage, ISP problem, CSMS maintenance — these happen. Without local authorization, the charger becomes useless during the outage.
LocalAuthList is the solution. It’s a list of authorized user identifiers stored on the charger itself, allowing the charger to authorize users locally when the back-end is unreachable.
This article explains how LocalAuthList works, the patterns for keeping it useful, and the trade-offs of relying on it.
The basic concept
A LocalAuthList is a list of (idTag, status, expiry) entries stored locally on the charger.
When a user presents an idTag (RFID, etc.) and the charger sends Authorize to the CSMS:
- If the CSMS responds, the charger uses that response (CSMS is authoritative).
- If the CSMS doesn’t respond (offline), the charger checks its local list.
- If the idTag is in the list with status Accepted, authorize.
- If status Blocked or Expired, reject.
- If not in the list, behavior depends on AllowOfflineTxForUnknownId setting.
The list is pushed to the charger by the CSMS via OCPP messages.
OCPP 1.6: GetLocalListVersion, SendLocalList
Two main messages.
GetLocalListVersion — the CSMS asks the charger which version of the list it currently has:
// Response from charger
{ "listVersion": 42 }
SendLocalList — the CSMS sends a new list or updates to the existing list:
{
"listVersion": 43,
"localAuthorizationList": [
{ "idTag": "ABC123", "idTagInfo": { "status": "Accepted" } },
{ "idTag": "DEF456", "idTagInfo": { "status": "Blocked" } },
{ "idTag": "GHI789", "idTagInfo": { "status": "Accepted", "expiryDate": "2027-01-01T00:00:00Z" } }
],
"updateType": "Full"
}
The updateType is either:
- Full — replace the entire list with this one.
- Differential — apply these as changes to the existing list.
OCPP 2.0.1: GetLocalListVersionRequest, SendLocalListRequest
Same conceptual structure, slightly different naming and richer data:
{
"versionNumber": 43,
"localAuthorizationList": [
{
"idToken": { "idToken": "ABC123", "type": "ISO14443" },
"idTokenInfo": { "status": "Accepted", "cacheExpiryDateTime": "2027-01-01T00:00:00Z" }
}
],
"updateType": "Full"
}
The idToken structure in 2.0.1 supports more identifier types (ISO15118 EmaIds, central tokens, key codes, etc.). This mirrors the broader shift in OCPP 2.0.1 (coming soon), where flat 1.6 fields become structured objects.
The Authorize fallback flow
Without LocalAuthList:
- User presents idTag.
- Charger sends Authorize to CSMS.
- CSMS unreachable; Authorize times out.
- Charger has no way to know if user is valid.
- Charger rejects (or accepts based on AllowOfflineTxForUnknownId setting).
With LocalAuthList:
- User presents idTag.
- Charger checks local list first (some implementations) or sends Authorize to CSMS first (most implementations).
- If CSMS responds, use that response.
- If CSMS unreachable and idTag is in local list with Accepted status, authorize.
- If CSMS unreachable and idTag is NOT in local list, reject (or accept based on AllowOfflineTxForUnknownId).
The LocalAuthList becomes the authoritative source during offline periods.
flowchart TD
A[User presents idTag] --> B{CSMS reachable?}
B -->|Yes| C[Use CSMS response]
B -->|No| D{idTag in<br/>local list?}
D -->|Accepted| E[Authorize offline]
D -->|Blocked or Expired| F[Reject]
D -->|Not found| G{AllowOffline<br/>for unknown?}
G -->|True| E
G -->|False| F
style E fill:#e8f5e9,stroke:#2e7d32
style F fill:#ffebee,stroke:#c62828
Configuration variables that matter
A few OCPP configuration variables affect LocalAuthList behavior.
LocalAuthListEnabled — turns LocalAuthList on or off on the charger. If false, the list is ignored even if present.
LocalAuthListMaxLength — the maximum number of entries the charger supports. Reported by the charger; read-only from the CSMS’s perspective.
SendLocalListMaxLength — the maximum number of entries that can be sent in a single SendLocalList message. The CSMS must batch large updates.
AllowOfflineTxForUnknownId — if true, the charger authorizes any idTag when CSMS is unreachable (even unknown ones), with the assumption that the CSMS will reconcile later. If false, only known idTags from LocalAuthList work offline.
AuthorizationCacheEnabled — a related but distinct feature. The authorization cache stores idTags that recently authorized via CSMS query, so a re-presentation doesn’t require a new query. Useful supplement to LocalAuthList. (The distinction between RFID tokens and contract-based Plug & Charge auth (coming soon) matters here — LocalAuthList covers the former.)
The size constraint
Charger memory is finite. A typical Level 2 charger supports a few thousand entries; some support tens of thousands. DC fast chargers often support more.
If your network has 100,000 users but each charger only supports 5,000 entries, you can’t push the entire list. Strategies:
Push only active users. Maintain “last seen” data per user; push only the most-recent N thousand.
Push only frequent users at each location. If charger X is at a workplace, push the employees of that workplace, not the entire network.
Push only highest-priority partners. If your eMSP partner A is your largest, push their users; rely on online lookup for smaller partners.
Tiered approach. Top-tier users in LocalAuthList; others fall back to AllowOfflineTxForUnknownId.
The right strategy depends on your operational model. Workplace chargers can be highly selective; public DC fast chargers serving anonymous travelers need broader coverage or AllowOffline.
Update frequency
How often to push the LocalAuthList to chargers.
Daily. Common pattern. Captures user additions, removals, status changes within 24 hours. Reasonable balance of freshness and bandwidth.
Real-time on changes. Push differential updates as users change. Lower latency but more message traffic. Useful for chargers with bandwidth budget.
Weekly. Acceptable for stable user bases. Users added today won’t work at chargers until next weekly push.
Hourly. Aggressive but achievable. Catches changes faster but uses more bandwidth.
A common pattern: nightly full sync plus real-time differential pushes for important changes (new partner, mass user import, etc.).
When to use LocalAuthList
It’s not always the right answer. Considerations.
Use LocalAuthList when:
- Network reliability matters for the charger’s location.
- Cellular signal is weak or unreliable.
- You have a defined user base that fits in charger memory.
- Downtime tolerance is low.
Maybe skip LocalAuthList when:
- Charger has reliable wired internet.
- User base is too large to push meaningfully.
- AllowOfflineTxForUnknownId is sufficient (you’ll reconcile billing later).
Definitely use it for:
- Workplace chargers with known employee base.
- Apartment chargers with known resident base.
- Fleet depots (coming soon) with known vehicle list.
Less critical for:
- Highway DC fast chargers with reliable wired internet and broad public user base.
The reconciliation problem
LocalAuthList authorizations happen offline. The CSMS doesn’t know about them in real time. Reconciliation matters.
When the charger reconnects after an offline period:
- The charger reports buffered events (StartTransaction, MeterValues, StopTransaction) to the CSMS.
- The CSMS sees transactions for users it didn’t pre-authorize.
- The CSMS handles billing — querying the eMSP for actual authorization status at the time of session.
- If the user was actually invalid (revoked, expired, blocked) at the time, the CSMS must decide: write off the loss, attempt to bill anyway, dispute with the eMSP.
This reconciliation is the cost of offline operation. LocalAuthList minimizes this by encoding what was known at last push time, but doesn’t eliminate it.
Common implementation pitfalls
A list of things that go wrong.
LocalAuthList not updated. Charger has stale list. Newly-added user can’t charge; recently-blocked user still can. Periodic sync verification matters.
LocalAuthListMaxLength exceeded. CSMS tries to push 10,000 entries to a charger that only supports 5,000. Either the SendLocalList fails or the charger truncates silently. Validate before sending.
Version mismatch. CSMS thinks the charger has version 42; charger actually has version 40 (a recent update was lost). Differential updates applied to wrong base. Always verify with GetLocalListVersion before differential updates.
AllowOfflineTxForUnknownId set wrong. True when you wanted false (or vice versa) leads to unexpected auth behavior during outages.
Cache vs LocalAuthList confusion. The auth cache is separate from LocalAuthList. They interact. Understand the distinction in your specific charger’s implementation.
Charger reports support but doesn’t actually implement. Some chargers claim LocalAuthList support but ignore the list. Test with offline scenarios.
Operational best practices
A short checklist.
- Push the LocalAuthList on a schedule that matches your operational reality.
- Validate updates by querying GetLocalListVersion after pushing.
- Monitor per-charger list freshness in your operations dashboard.
- Test offline scenarios in commissioning — simulate network failure and verify expected auth behavior.
- Audit reconciliation — review offline-authorized transactions after each outage; identify any that should have been rejected.
- Define AllowOfflineTxForUnknownId policy per charger location and document it.
The honest summary
LocalAuthList is essential for chargers that operate in environments with unreliable connectivity. Its design is straightforward; the operational discipline around keeping it current, sized appropriately, and reconciling offline transactions is where the work happens. Get this layer right and your chargers stay useful during the inevitable network outages; ignore it and you’re vulnerable to every CSMS or cellular hiccup.