OCPP lets a charger prove who it is when it opens the WebSocket, using one of three security profiles. The CSMS has to enforce them, and the only way to find out whether yours does is to connect with the right credentials, the wrong ones and none. Doing that with real chargers means reconfiguring hardware for every case. A simulated station takes its credentials from the create request, so each case is one API call.
The profiles and the field that selects them
A station created without a security object connects with no credentials, which is the unsecured profile (Profile 0 in SimItNow's terms). The other three are chosen by the URL scheme and by what you put in security:
| Profile | csmsUrl | What the station sends | security field |
|---|---|---|---|
| 1 | ws:// | HTTP Basic Auth | basicAuth |
| 2 | wss:// | HTTP Basic Auth over TLS | basicAuth |
| 3 | wss:// | A TLS client certificate | clientCert |
Profile 1 sends the password in clear text, so use it only against a CSMS on a network you trust. The background on how the profiles differ between OCPP versions is in OCPP 1.6 vs 2.0.1.
Basic Auth
curl -X PUT https://api.simitnow.com/v2/cs/CP-001 \
-H "SIMITNOW-API-KEY: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"csmsUrl":"wss://csms.example.com/ocpp","protocol":"ocpp2.0.1",
"security":{"basicAuth":{"password":"the-station-password"}}}'
The username defaults to the station id, which is what the OCPP specifications require. Set basicAuth.username only when you want to test a CSMS that expects something else. The password is the one your CSMS holds for that station.
Client certificate
For Profile 3 the certificate and private key go into the request as PEM text. Building the JSON by hand is error prone, so let jq read the files:
jq -n --arg cert "$(cat station.crt)" --arg key "$(cat station.key)" \
'{csmsUrl:"wss://csms.example.com/ocpp", protocol:"ocpp2.0.1",
security:{clientCert:{certificate:$cert, privateKey:$key}}}' |
curl -X PUT https://api.simitnow.com/v2/cs/CP-001 \
-H "SIMITNOW-API-KEY: $API_KEY" \
-H "Content-Type: application/json" \
-d @-
basicAuth and clientCert cannot be combined, and clientCert needs a wss:// URL. A request that breaks either rule, or leaves out the password, the certificate or the key, is refused with 400 and nothing is dialled. So is a csmsUrl that is not a WebSocket address, such as one without the ws:// or wss:// start.
SimItNow checks the CSMS server certificate against the usual public authorities. A CSMS with a self-signed certificate or a private CA fails that check. For a test setup, set "skipServerCertVerify": true inside security to connect anyway. It only has an effect on wss:// URLs, and it removes the check that protects Profile 2 and 3 from a man in the middle, so leave it off wherever the CSMS has a real certificate.
Check the credentials before you create the station
The connection probe accepts the same security object and runs one real handshake with it:
curl -X POST https://api.simitnow.com/v1/cs/probe \
-H "SIMITNOW-API-KEY: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"csmsUrl":"wss://csms.example.com/ocpp","id":"CP-001","protocol":"ocpp2.0.1",
"security":{"basicAuth":{"password":"the-station-password"}}}'
A wrong password or an unknown station comes back as credentials_refused (the CSMS answered 401 or 403) or path_not_found (404). A certificate problem during TLS shows as certificate_untrusted or tls_failed. The probe sends no BootNotification, so you can run it as often as you like within the limit of 20 a minute.
The negative tests
The positive case, a valid credential that connects, is the one everyone tests. These are the ones that find holes:
- Wrong password for a known station. The CSMS should refuse the upgrade with 401. The station keeps retrying with a wait that grows to about a minute, so check how your CSMS logs repeated failures from one address and whether it blocks the source after a few.
- A correct password with a station id the CSMS does not know. It should refuse, not create the station on the fly.
- No credentials at all, on a CSMS that requires them. Create the station without a security object.
- A plain ws:// connection to a CSMS that requires TLS. It should not accept Basic Auth over an unencrypted link.
- A certificate that belongs to another station. Many CSMSs check that the certificate subject matches the station id in the URL, and this is the test that shows whether yours does.
The station's credentials are fixed when it is created. To test a second password, create another station under a different id.
Reporting a security event
A station reports tampering, a firmware update or a certificate problem with a SecurityEventNotification. Nothing on the CSMS side can ask for one, so SimItNow has an endpoint that makes the station send it:
curl -X POST https://api.simitnow.com/v2/cs/CP-001/security-event \
-H "SIMITNOW-API-KEY: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"type":"TamperDetectionActivated","techInfo":"enclosure sensor 3"}'
The type can be any string up to 50 characters, so you can send the standard ones and vendor-specific ones. The endpoint works on every protocol version and sends that version's SecurityEventNotification. Check that your CSMS stores the event, alerts on the serious ones and does not close the connection on a type it has not seen.
The hosted CSMS in private mode checks HTTP Basic Auth on a wss:// address, which is Profile 2, so it is a quick way to see a working Basic Auth setup before you test your own. Create a free account to run these tests.