Authorize drivers with RFID cards
OCPP functional block C — Authorization, and D — LocalAuthorizationList.
A driver presents a card. The station does not know whether that card may charge, so it asks. This page covers the registry it is asking about, what happens when the network is down, and why token values are handled the way they are.
The registry#
Each environment has an authorization registry: the set of id tokens it will authorize. A token is a credential — an RFID card UID, a key code, an app-issued value — not a person.
curl -X POST https://api.flowion.io/v1/environments/$ENV/id-tokens \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"value": "045C7A2B4F1D80",
"label": "Fleet card 12",
"token_type": "ISO14443",
"expires_at": "2027-01-01T00:00:00Z"}'
Only value is required. label is for humans, expires_at makes a token
self-retiring, and token_type records what kind of credential it is —
ISO14443 and ISO15693 for RFID, KeyCode, MacAddress, eMAID,
Central, Local, NoAuthorization.
An OCPP 1.6 station never reports a token's type, so for 1.6 fleets this is your own bookkeeping rather than something observed.
How a value is stored#
A token value is stored twice, in two different forms, and neither is plaintext:
- A keyed hash, used to match a presented token during authorization.
- An encrypted copy, used only when a value has to leave the system — for pushing a local authorization list to a station.
The consequence for you: listing endpoints never return token values. Fetching an id token gives you its label, type, expiry and status, not the credential itself.
Recovering a value is a separate, deliberately awkward operation:
curl -X POST https://api.flowion.io/v1/id-tokens/$ID/reveal \
-H "Authorization: Bearer $TOKEN"
It requires the Owner role and it is audited — GET /v1/id-tokens/{id}/reveals
lists every reveal. Managing the registry needs only Admin; reading a value
back needs the top role and leaves a record. Design your workflows so reveal
is rare.
Retiring a token#
curl -X POST https://api.flowion.io/v1/id-tokens/$ID/revoke \
-H "Authorization: Bearer $TOKEN"
Revoking is preferable to deleting: it stops the token authorizing while keeping it attached to the transactions it started. A deleted token leaves history harder to read.
What a station does with a card#
Three things can happen, and only the first involves you in real time.
It asks. The station sends Authorize and waits. You answer Accepted,
Blocked, Expired, Invalid or ConcurrentTx. A refusal is a perfectly
successful message exchange — see
OCPP in ten minutes.
It decides locally from its cache. Stations may cache recent answers and
reuse them. You will not see an Authorize for a session that starts this
way.
It decides locally from its list. See below.
Because of the last two, you must re-check the credential when a transaction starts. The station may have accepted a card from a cache entry that has since been revoked, and the start response is your last chance to refuse. This happens automatically, but it is why a token can be revoked and a session still begin moments later.
Keeping a site working offline#
A station with no network cannot ask anyone. A local authorization list is the answer: a set of tokens pushed to the station in advance, which it authorizes against by itself.
Curate a station's list:
curl -X PUT https://api.flowion.io/v1/chargers/$CHARGER/local-auth-list \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"entries": [{"id_token_id": "..."}, {"id_token_id": "..."}]}'
This selects from the registry — you name tokens that already exist rather than inventing new ones. Curating takes Admin.
Pushing it to the station is a separate command, and takes Owner:
curl -X POST https://api.flowion.io/v1/chargers/$CHARGER/commands/send-local-list \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"update_type": "full"}'
The role difference is deliberate. Curating a list moves references around; pushing one puts token values on a wire, which is materially different and is recorded as such.
Check what a station currently holds:
curl -X POST https://api.flowion.io/v1/chargers/$CHARGER/commands/get-local-list-version \
-H "Authorization: Bearer $TOKEN"
Stations track list versions, so this tells you whether a push landed without sending the whole list again.
The authorization cache#
Separate from the list: the cache is what a station builds itself from answers you gave. You do not curate it, but you can clear it:
curl -X POST https://api.flowion.io/v1/chargers/$CHARGER/commands/clear-cache \
-H "Authorization: Bearer $TOKEN"
Do this after revoking a token that may be cached at a station — otherwise the station can keep accepting it while offline. Clearing the cache does not touch the local authorization list.
Fail-open behaviour worth knowing#
An environment with no tokens configured at all authorizes everything.
This is deliberate: an environment that has not been provisioned yet stays usable, rather than every station rejecting every driver until someone adds a first token. But it means an empty registry is not a locked-down one. If you intend to restrict access, add at least one token.