OCPI is, in effect, a financial protocol. It moves invoices, energy readings, and user identifiers between two parties that may barely know each other: a CPO on one side, an eMSP on the other. A single leaked credential lets an attacker push fake billing records or read another operator’s confidential session data. The security model itself is not complicated. The operational discipline around it is what separates a genuinely secure deployment from one that is only nominally compliant.
At the protocol layer, OCPI security comes down to two things: TLS for transport and a bearer token for identity. This article walks through how that model works and where the real failure modes live. If you want the wider protocol context first, see what OCPI is and how it differs from OCPP and ISO 15118, which secure different links in the same chain.
The OCPI security model in one paragraph
Every OCPI interaction is a TLS-encrypted HTTPS request carrying a bearer token in the Authorization header. The two parties exchanged those tokens during the Credentials handshake. The token authenticates the calling party, and trust in the token rests entirely on the assumption that it has not leaked. There is no per-request signing, no nonce mechanism, and no challenge-response. The bearer token plus TLS is the whole security story at the protocol layer.
The header itself uses the literal scheme word Token, not Bearer:
Authorization: Token IpbJOXxkxOAuKR92z0nEcmVF3Qw09VG7I7d/WCg0koM=
One version detail worth knowing: in OCPI 2.2.1 the credentials token carried in that header is Base64-encoded, whereas 2.1.1 sent it verbatim. That changes how you store and compare tokens across versions, so it matters the moment you support both. For the full list of what changed between releases, see the OCPI version history.
One ordering point that trips people up: TLS always comes first. Because OCPI is HTTP over TLS, the TLS handshake completes before any OCPI data crosses the connection. The bearer token, and even the very first registration call, travel inside the already-encrypted channel, never in the clear. It helps to keep two separate handshakes straight. The transport-layer TLS handshake sets up encryption (and under mTLS also verifies the client’s certificate), and it runs first. The application-layer Credentials handshake described below, where the tokens are exchanged, runs on top of it. TLS establishes the tunnel and the tokens ride inside. You never trigger TLS yourself: a client calling an https:// URL negotiates it as soon as the TCP socket opens, and the server (or its load balancer) terminates it and hands plain HTTP to the OCPI app.
This is intentionally simple. It is also fragile if you do not operate it carefully.
The Credentials handshake (the trust anchor)
Everything starts with the Credentials handshake, handled by the Credentials and Versions modules. The token exchange happens in three steps:
- Out-of-band exchange of a registration token (token A). The party you are registering with (the receiver) generates token A and hands it to you through some channel outside OCPI: email, a partner portal, a Slack DM, sometimes a contract attachment.
- First authenticated call uses token A to POST your own freshly generated real token (token B) to the partner’s
/credentialsendpoint. Token B is what they will use to authenticate to you from now on. - The partner responds with their real token (token C). From here on, you authenticate to them with token C and they authenticate to you with token B. Token A is single-use. The spec says it MAY no longer be used, so it gets thrown away.
sequenceDiagram
participant A as Party A
participant B as Party B
Note over A,B: B generates token A,<br/>hands it to A out-of-band
A->>B: POST /credentials<br/>auth with token A<br/>body carries token B
B-->>A: Returns token C
Note over A,B: A stores token C<br/>B stores token B
Note over A,B: Token A invalidated (single-use)
A->>B: Future calls<br/>auth with token C
B->>A: Future calls<br/>auth with token B
That is the flow as OCPI 2.2 and 2.2.1 name it. OCPI 2.1.1 has the same logic with less explicit naming. The property it buys you: a party cannot masquerade as another without obtaining the real token, and the real token only ever crosses the wire inside an already-encrypted channel, authenticated by a registration token that is discarded immediately afterwards.
The handshake is the easy part. What happens over the following years of the partnership is where mistakes accumulate.
The threat model: what could go wrong
Everything below is something the protocol permits and does not prevent.
Token leakage via source code. An engineer commits a config file containing the OCPI token. Automated scanners crawl public repositories for credential-shaped strings, so the exposure window opens the moment the push lands, not when a human notices.
Token leakage via logs. The token is printed in application logs, the logs are aggregated to a central service, and anyone with log access can extract it. Shipping logs to a third-party SaaS makes it worse, because the credential has now left your perimeter without anyone deciding that it should.
Token reuse across environments. A production token ends up in staging by accident. Staging is built to a lower security bar, so an attacker who gets into staging walks out with production access.
Long-lived tokens. A token issued years ago and never rotated accumulates readers: engineers who have since left, a contractor onboarded once, a runbook page in a wiki. Forensic accountability is gone before an incident even starts.
Compromised TLS. Old TLS versions or weak ciphers on the server open the door to a machine-in-the-middle against OCPI traffic. Stolen tokens, modified messages.
Authentication without authorization. The server confirms the bearer token is valid and correctly identifies party X, then never checks whether party X may perform this action on this resource. Any authenticated party can read or write anything.
Cross-party data leakage. The server logs Session details indiscriminately. A support engineer debugging one issue can read Sessions belonging to parties they have no relationship with.
Fake CDRs. An attacker holding a leaked CPO token POSTs fabricated CDRs to an eMSP, which bills its users for sessions that never happened. Financial loss, plus a reputational problem that outlasts the refunds.
Offboarded partner with a live token. The commercial relationship ended and nobody revoked the credential. The partner’s old systems keep sending data, sometimes for months, sometimes deliberately.
The thread connecting all of these: not one is a flaw in the protocol. Every one is a decision about storage, logging, or lifecycle that OCPI deliberately leaves to you. OCPI integration pitfalls covers the non-security version of the same pattern.
The defense layers
A reasonably-secure OCPI deployment has several layers.
Layer 1: TLS done right
In a standard OCPI deployment, TLS is one-way (server-authenticated): the server presents an X.509 certificate that the client verifies against a trusted CA, and the whole channel is encrypted. What one-way TLS does not do is identify the client. At the transport layer the caller is anonymous. That is precisely why OCPI also needs the bearer token. TLS proves which server you reached and keeps the bytes private on the wire; the token proves which party is calling. Two independent jobs, and each one fails on its own terms: get the transport wrong and the token leaks, get the token wrong and encryption cannot save you.
- TLS 1.2 minimum; TLS 1.3 strongly preferred.
- Modern cipher suites only (no RC4, no 3DES, no export ciphers, no plain CBC).
- Forward secrecy required (ECDHE or DHE key exchange).
- Server certificate from a real CA, properly chained, with HSTS enabled.
- Skip certificate pinning. Every certificate rotation then becomes a coordinated release with your partner, and a well-managed PKI gets you the same assurance without that breakage.
- Periodic SSL Labs (or similar) audit of your endpoints.
The charge point side of the network solves this same problem with a different shape: OCPP bundles transport and authentication choices into numbered security profiles, so a deployment picks a level rather than assembling the pieces. OCPI leaves the equivalent decisions to you and each partner.
If you do not get TLS right, nothing else matters. Bearer tokens flying over weak TLS are tokens about to leak.
Layer 2: Token management
- Generate tokens with sufficient entropy. Do not roll your own; use a secure random source (32+ bytes of CSPRNG output, base64-encoded).
- Store tokens encrypted at rest. Database encryption, or a secrets manager (Vault, AWS Secrets Manager, GCP Secret Manager, and so on). Never plaintext in app config.
- Never log full tokens. If you must log something for debugging, log the first 4-8 characters as an identifier and nothing more.
- Rotate tokens on a schedule. Quarterly or biannually depending on your risk posture. OCPI’s Credentials PUT endpoint exists for exactly this; use it.
- Rotate on personnel changes. An engineer with access leaves the team, rotate. An engineer changes role, rotate.
- Audit token access. Who inside your organization can read the production tokens? That should be a short list, reviewed quarterly.
Layer 3: Authentication AND authorization
Token validation and permission checking are two separate steps, and it is easy to build only the first. The token tells you who is calling. It says nothing about what they should be allowed to do.
A complete check:
- Is the token valid? (authentication)
- Is the calling party authorized to perform this specific action on this specific resource? (authorization)
- For Locations, is this party allowed to read this Location? (a CPO can restrict specific sites to named partners)
- For Sessions and CDRs, is this party a counterparty to this transaction? (a CPO should not be able to query another CPO’s CDRs through your eMSP system)
- For Commands, is this party allowed to issue this command on this resource?
Without a per-request authorization check, one leaked token from any party gives access to everything.
Layer 4: Audit logging
- Log every OCPI request with: caller party ID, endpoint, method, response status, timestamp.
- Do NOT log: full tokens, full PII (hash or pseudonymize user identifiers), full energy data you have no use for.
- Retain logs long enough to cover billing disputes and the record-keeping rules of every market you bill in. Those retention periods come from tax and commercial law rather than from OCPI, and the longest applicable one sets your floor.
- Monitor for anomalies: unusual volume from a partner, unusual endpoints, unusual error rates.
- Alert on security-relevant events: Credentials PUT (token rotation), a spike in authentication failures, repeated unauthorized access attempts.
Layer 5: Network and infrastructure
- OCPI endpoints behind a WAF (Web Application Firewall), which also gives you rate limiting, basic injection filtering, and IP allowlisting if you want it.
- Per-partner rate limits to contain runaway loops and DoS attempts. See OCPI rate limiting and abuse protection (coming soon) for the details.
- IP allowlisting wherever a partner can commit to a stable set of egress addresses.
- Regular dependency scanning. Your TLS library, your HTTP library, and your framework all need patching on someone’s schedule.
- Network isolation. An OCPI server should not reach internal systems beyond what it needs (no direct database admin access, for instance).
Layer 6: Partner-side hygiene
Your security is only as strong as your weakest partner. Some things you can do, and ask of partners:
- Quarterly check-in on token rotation. Has the partner rotated their token recently?
- Incident notification agreements. If they have a breach, when do they tell you?
- Joint testing of revocation flows. Can you verify that a revoked token stops working in their systems?
- Coordinated penetration testing. Annually, ideally bilateral with major partners.
Mutual TLS (mTLS): when and how
Standard TLS authenticates only the server. Mutual TLS (mTLS) adds the missing half: the client must also present an X.509 certificate that the server validates, so both ends prove their identity at the transport layer before a single OCPI byte is processed. The bearer token does not go away. mTLS layers a second, independent identity check underneath it. The practical payoff is that a leaked token stops being sufficient on its own. An attacker holding a stolen token still cannot open a connection without the matching client certificate and its private key, which live somewhere else entirely and are far harder to exfiltrate than a string in a config file or a log line.
Here is who proves what in each setup:
| Plain TLS + token | mTLS + token | |
|---|---|---|
| Channel encrypted | ✓ | ✓ |
| Server identity verified (by the client) | ✓ | ✓ |
| Client identity at the transport layer | ✗ (anonymous) | ✓ (X.509 client cert) |
| Client identity at the application layer | ✓ (bearer token) | ✓ (bearer token) |
So plain TLS plus a token gives the caller one proof of identity, at the application layer. mTLS plus a token gives two independent proofs: a client certificate at the transport layer and the token at the application layer. That defense in depth is the entire reason to add it.
Pros:
- Infrastructure-level identity verification, separate from the application-level token.
- A compromised token alone is not enough; the attacker also needs the client certificate and its key.
- If a compliance framework in your market requires transport-layer client authentication, mTLS is how you satisfy it.
Cons:
- Certificate lifecycle management (issuance, renewal, revocation, distribution) is much heavier than rotating a string.
- Hub-mediated connections put certificate provisioning and renewal onto infrastructure you do not control.
- Partner onboarding gains a step that has to succeed before any OCPI traffic flows at all.
Recommendation:
- For high-volume bilateral partnerships, mTLS is worth the operational overhead.
- For hub-mediated long-tail roaming it is usually impractical, because the hub sits between you and many parties at once. Hub versus peer-to-peer OCPI is the same tradeoff viewed from the topology side.
- A mixed deployment (mTLS for your largest partners, bearer-only for the rest) is a defensible middle ground: you spend certificate lifecycle effort only where the traffic and the money justify it.
If you want a look at what certificate lifecycle management costs when it is not optional, contract certificates and PKI in ISO 15118 (coming soon) is the same machinery applied to vehicles instead of servers.
The PII dimension
OCPI carries personal data, and the Tokens module carries the most concentrated dose of it. User identifiers such as RFID UIDs are personal data under the GDPR in Europe, and identifiers of that kind fall under California’s CCPA/CPRA and Canada’s PIPEDA as well. Session data is personal data. CDRs are personal data.
A complete security story includes:
- Data minimization. Request only the fields you actually use.
- Pseudonymization where possible. Hash user identifiers before storing them for analytics.
- Data subject access requests. Be able to export or delete a user’s data on request: GDPR Articles 15-17 in the EU, and the equivalent access and deletion rights under CCPA/CPRA in California or PIPEDA in Canada.
- Cross-border data transfer compliance. If a CPO in the EU sends Sessions to an eMSP in the US, GDPR’s third-country transfer rules apply (SCCs, adequacy decisions). The reverse direction and intra-North-American flows carry their own obligations, so map the data flows before you switch on a cross-border roaming partner.
- Retention limits. Do not keep PII forever. Define a retention policy and enforce it in code, not in a document.
Half of this is an OCPI problem and half is a general data-protection problem. What makes it worth flagging here is that an OCPI integration moves personal data across an organizational boundary in a format that nobody on either side instinctively thinks of as a personal-data export.
Common operational mistakes (checklist)
A short checklist to audit your OCPI security posture against.
- All endpoints HTTPS, TLS 1.2+, modern cipher suites only.
- Tokens stored in a secrets manager, not in code or in plaintext environment variables.
- Tokens never appear in logs.
- Tokens rotated at least biannually.
- Per-request authorization, not just authentication.
- Audit logs retained long enough for billing disputes, and monitored for anomalies.
- Partner offboarding procedure includes token revocation, verified.
- Annual penetration testing or security review of OCPI endpoints.
- mTLS evaluated for top partners.
- Data retention policy defined and enforced.
The list is a roadmap, not a pass/fail. The useful discipline is writing a reason and a date next to every box you leave unchecked, because the gaps nobody has consciously decided about are the ones that bite.
What an incident response looks like
If you suspect a compromise:
- Rotate immediately. Do not wait for confirmation; rotate the suspect token or tokens right now.
- Audit logs for unusual activity. Look for endpoints that are normally quiet, volume that does not match the partner’s pattern, unfamiliar source addresses.
- Notify affected partners. If they sent you data via the compromised token, they need to know. Trust degrades fast without proactive communication.
- Forensic review. Where did the token leak from? A source code commit, a compromised laptop, a misconfigured log pipeline? Fix the root cause, not the symptom.
- External notification. If PII was potentially exposed, regulators may need telling. The GDPR sets a 72-hour reporting window in the EU, US state breach-notification laws apply per state, and PIPEDA carries its own breach-reporting duty in Canada. Work out which apply to your footprint before you need the answer at 2am.
- Post-mortem. Document what happened, what you changed, and how you will prevent a recurrence.
Nobody announces a stolen OCPI token. A compromise shows up as side effects instead: a partner asking about CDRs they never sent, a spike in authentication failures, sustained traffic on an endpoint that is normally idle. If nothing is watching for those signals, an attacker’s access lasts exactly as long as the token stays valid.
The honest summary
OCPI’s protocol-layer security is TLS plus a bearer token, and that simplicity is fine. What fails is everything the spec leaves to you: storage, logging, lifecycle, offboarding.
The part worth internalizing is an asymmetry in the credentials model that is easy to miss. Each party generates the token that the other party uses to call it. Your inbound credential is therefore yours: you minted it, you can push a replacement with a Credentials PUT, and you can stop honoring the old one without asking permission or booking a joint maintenance window. Cutting off a partner who has been breached, or one you offboarded last quarter, is a unilateral action you can take in minutes.
The reverse does not hold. You cannot rotate the token you use to call them, and you cannot make them rotate anything. So a token-hygiene program has two halves with very different levers: the half you control outright, and the half you can only ask about. Automate the first half on a schedule. Put the second half in the contract, because a polite quarterly email is the only enforcement mechanism you actually have.