Integratiegids voor Service Providers (SP’s).
Als SP praat je enkel met het beID Hermes Platform.
payload_b64.payload_b64 met jouw private key./hosted/start.php.return_url met result_token.Endpoint:
https://beid.hermesplatform.be/hosted/start.php
POST‑velden:
| veld | beschrijving |
|---|---|
payload_b64 | base64(JSON) met de start‑payload (zie hieronder) |
sp_sig_alg | ES256 of RS256 |
sp_signature | base64( signature over payload_b64 ) |
Payload JSON (base64‑encoded in payload_b64):
{
"sp_id": "partner1",
"op": "read:identity",
"return_url": "https://sp.example/return",
"state": "opaque123",
"ts": 1700000000,
"nonce": "random-hex",
"tbs_b64": "..." // enkel voor auth/sign
}
Veld uitleg:
| veld | vereist | omschrijving |
|---|---|---|
sp_id | ja | jouw SP‑identifier |
op | ja | read:identity, read:address, read:photo, read:certs, auth, sign |
return_url | ja | moet op allowlist staan bij HP |
state | nee | opaque string, krijg je terug in de response |
ts | ja | Unix timestamp (seconden) |
nonce | ja | unieke waarde per request (anti‑replay) |
tbs_b64 | ja bij auth/sign | base64 van de te‑signen bytes |
Signature regels:
payload_b64 (niet de JSON‑bytes).sp_cert_pem.sp_sig_alg moet overeenkomen met wat bij HP geregistreerd is.Het platform POST naar jouw return_url met:
POST https://sp.example/return result_token=...&state=opaque123
Uitleg:
result_token: JWT (ES256) met resultaat + metadata.state: exact dezelfde waarde die je initieel meegaf.De SP valideert result_token met de public key van het platform en decodeert payload_b64.
Public key (download): /keys/challenge_pub.pem
Result‑token claims (voorbeeld):
{
"iss": "beid.hermesplatform.be",
"aud": "sp",
"sp_id": "partner1",
"op": "read:identity",
"status": "ok",
"payload_b64": "...",
"result_hash": "...",
"iat": 1700000000,
"exp": 1700000300
}
tbs_b64 is base64 van de te‑signen bytes.signature_b64 + signature_format=der).<?php
$payload = [
'sp_id' => 'partner1',
'op' => 'read:identity',
'return_url' => 'https://sp.example/return',
'state' => 'opaque123',
'ts' => time(),
'nonce' => bin2hex(random_bytes(16)),
];
$payloadB64 = base64_encode(json_encode($payload, JSON_UNESCAPED_SLASHES));
$privPem = file_get_contents('/path/to/sp_priv.pem');
$privKey = openssl_pkey_get_private($privPem);
openssl_sign($payloadB64, $sigDer, $privKey, OPENSSL_ALGO_SHA256);
$sigB64 = base64_encode($sigDer);
?>
<form method="POST" action="https://beid.hermesplatform.be/hosted/start.php">
<input name="payload_b64" value="<?php echo htmlspecialchars($payloadB64); ?>" />
<input name="sp_sig_alg" value="ES256" />
<input name="sp_signature" value="<?php echo htmlspecialchars($sigB64); ?>" />
</form>
<script>document.forms[0].submit()</script>
<?php
require 'vendor/autoload.php';
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
$token = $_POST['result_token'] ?? '';
$pubPem = file_get_contents('/path/to/platform_pub.pem');
$claims = JWT::decode($token, new Key($pubPem, 'ES256'));
$payload = json_decode(base64_decode($claims->payload_b64), true);
?>
var payload = new {
sp_id = "partner1",
op = "read:identity",
return_url = "https://sp.example/return",
state = "opaque123",
ts = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
nonce = Guid.NewGuid().ToString("N")
};
var payloadJson = System.Text.Json.JsonSerializer.Serialize(payload);
var payloadB64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(payloadJson));
var privPem = System.IO.File.ReadAllText("C:\\path\\sp_priv.pem");
var ecdsa = System.Security.Cryptography.ECDsa.Create();
ecdsa.ImportFromPem(privPem);
var sigDer = ecdsa.SignData(System.Text.Encoding.ASCII.GetBytes(payloadB64),
System.Security.Cryptography.HashAlgorithmName.SHA256);
var sigB64 = Convert.ToBase64String(sigDer);
var token = Request.Form["result_token"];
var pubPem = System.IO.File.ReadAllText("C:\\path\\platform_pub.pem");
var handler = new System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler();
var key = new Microsoft.IdentityModel.Tokens.ECDsaSecurityKey(
System.Security.Cryptography.ECDsa.Create(System.Security.Cryptography.ECCurve.NamedCurves.nistP256));
key.Ecdsa.ImportFromPem(pubPem);
var parms = new Microsoft.IdentityModel.Tokens.TokenValidationParameters {
ValidateIssuer = true, ValidIssuer = "beid.hermesplatform.be",
ValidateAudience = true, ValidAudience = "sp",
IssuerSigningKey = key,
ValidateLifetime = true
};
var principal = handler.ValidateToken(token, parms, out _);
var payloadB64 = principal.Claims.First(c => c.Type == "payload_b64").Value;
var payloadJson = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(payloadB64));
String payloadJson = "{...}"; // bouw JSON met sp_id/op/return_url/ts/nonce
String payloadB64 = Base64.getEncoder().encodeToString(payloadJson.getBytes(StandardCharsets.UTF_8));
PrivateKey privKey = loadPrivateKey("/path/sp_priv.pem");
Signature sig = Signature.getInstance("SHA256withECDSA");
sig.initSign(privKey);
sig.update(payloadB64.getBytes(StandardCharsets.US_ASCII));
byte[] sigDer = sig.sign();
String sigB64 = Base64.getEncoder().encodeToString(sigDer);
// bv. met Nimbus JOSE + JWT
SignedJWT jwt = SignedJWT.parse(resultToken);
JWK jwk = JWK.parseFromPEMEncodedObjects(pubPem);
JWSVerifier verifier = new ECDSAVerifier(jwk.toECKey());
if (!jwt.verify(verifier)) throw new Exception("invalid signature");
JWTClaimsSet claims = jwt.getJWTClaimsSet();
String payloadB64 = claims.getStringClaim("payload_b64");
String payloadJson = new String(Base64.getDecoder().decode(payloadB64), StandardCharsets.UTF_8);