Example: Smart ID Mobile App provisioning
- Installed Hermod, see Deploy Smart ID.
Step-by-step instruction
Send provisioning request, see code example.
Example: Provisioning command
CODEPOST /rest/command/provision { "commandHeader":{ "lifespan":1500, "timeout":1500 }, "provCommand":{ "nonce":"123456789", "userid":"john.doe@nexusgroup.com", "responsesignaturekey":"ATTESTATION", "responseformat":"jws", "profile":{ "servername":"nexus-hermod1", "name":"TestProfile", "keygenrequests":[ { "keyid":"signer", "usage":"SIG", "keytypeprios":[ { "keytype":"RSA", "keylength":"2048", "responsemechanism":"RS256" } ], "storageprios":[ "APP" ], "keystate":"ACTIVE", "certreq":"MIIDAzCCAesCAQIwgb0xCzAJBgNVBAYTAlNFMRAwDgYDVQQIDAdVcHBsYW5kMRAwDgYDVQQHDAdVcHBzYWxhMRcwFQYDVQQKDA5VcHBzYWxhIEtvbW11bjEUMBIGA1UECwwLRnlyaXNza29sYW4xFjAUBgNVBAMMDUFuZGVycyBSb3PDqW4xLTArBgkqhkiG9w0BCQEWHmNsYWVzLnJvc2VuYmVyZ0BuZXh1c2dyb3VwLmNvbTEUMBIGCysGAQQBgTwHAQECDANBUEEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDV8SX7mnFExGdNwJe+1VqzQHhN4+2TdtW98uOE7s7jNRAZZGNM7J9hvkyvljbHD71/iI6tTvvDAlEU45pe4qYlpgG5WLntYzP1TT+NZR3wvbWZQyoZrIPqguU/EB77tB38E/quY3BmMZSQeMPidqvAapTotTnSeE/981kj8IyZqm2v9WHjJsCj5TexrHnqcswFOVrtI/LhTfWKUn1o3sG890wmQSdjT53vtiIn4bCgck5WD/4YHozr8TBOKXwXhUwJhOj/uLxLkdDB1+0VX7q8i+IUzSRKD4WMTG93F0jDzR6jYPWJJfuEPTbDTvTeKfL97CGXSZt772HyRbqqhUATAgMBAAGgADANBgkqhkiG9w0BAQUFAAOCAQEANmxKbGq+/yzZh8doUSnjxaVEygL2gamnCLQ3+hQttxI+zn9Z6smvlD2nJmuGErVgB77oTKTbLXMDVlKD1QoHmTucoMYpALNd+roVHLAL7/bppO6MWgmQmKyTnaR95466y1lKZRqc0LKgv1xSCP+cJXelOaE2Kxqbj94YkxP5auPcc1GrBVFjY/CZYjqD2tAozWb8R4l04yKjYo4hGggcAzjxObbVKBLZ5GCV1BV384ojHizVdP8SHT0YzULj5ZlWwPVsVxUFGkJGQlF9ze5hl0XMZsKSpwvShySDRMZOM+piqAQQh7ktz0daDvEL5HFLpnJQSmY+3YRfoL5hG8Etqw==" } ] } } }
Example: Provisioning response
CODEResponse 200 OK { "commandId": "1011", "destinations": [ { "to": "@tmp", "bid": "482ae2ba-3847-4fc8-bb98-73a3f2f809ca", "uri": "com.nexusgroup.plugout:///?url=https%3a%2f%2fnexus-cod1.test.nexusgroup.com%3A20400%2fhermod%2Frest%2Fms%2F482ae2ba-3847-4fc8-bb98-73a3f2f809ca&token=c3c5df6d-59a1-450f-b2e5-066363959c71", "mid": "66b2fec0-54ba-472b-817a-ef464da5e8fa", "location": "https://nexus-cod1.test.nexusgroup.com:20400/hermod/rest/ms/482ae2ba-3847-4fc8-bb98-73a3f2f809ca/66b2fec0-54ba-472b-817a-ef464da5e8fa" } ], "commandType": "PROV", "state": "IN_PROGRESS", "fqdn": "nexus-cod1.test.nexusgroup.com" }
The user can then enter the URL or scan the QR code (the URL is rendered as a QR code according to standard) in the mobile app. The profile info will be displayed and the user can accept to activate the profile:
When the user has accepted to activate the profile, then a response will be sent to the Application Server in a callback.
Validate the response and check the following:
- That the signature of the complete payload and that a trusted attestation key is used.
- Proof of possession, by checking the signature of each generated key.
- Store the public key to be able to verify future authentications.
Example: Provision response callback
POST https://my-registered-callbackserver/rest/callback/provision
{
"responseHeader" : {
"inReplyTo" : "https://nexus-cod1.test.nexusgroup.com:20400/hermod/rest/ms/21b279cc-3f82-48e2-b200-fd9bbc5dfb4a/08aeef86-b789-4bf3-88fa-ab0c96824a6c",
"status" : 200
},
"provResponse" : {
"code" : 0,
"result" : {
"contenttype" : "jws",
"data" : "eyJraWQiOiJBVFRFU1RBVElPTiIsIm5vbmNlIjoiMTIzNDU2Nzg5IiwiYWxnIjoiUlMyNTYiLCJqd2siOnsidXNlIjoic2lnIiwia2lkIjoiYXR0ZXN0YXRpb24iLCJuIjoiQU9JN1UtcHJrSThIUktvYUpLRDNRdFRTTm1zbTFfcF91aVhiMVFMeTlnTVN1R2paOEhOcnBWVDRrY1IxVXVkdzNwT0tuZG43TkJlYzViOTJBZ001V3ZTUHhHRE9ZZmdLM3hLUlVheXl3RkQzSjZSVjF2VVh0alc0d0xtdnpHYnRZd0hIUHlycWhUNzNLckhobkxoMmRwSjNNTzVTQ0FXdU5iaVE2RVZsbkxkU3hZcGhGeEd2bmdxY0pHNl9ESmhrb2xyOWJfTExUdDE0OXRHa3lZcUw3YWlPNk9qVnRKUlFkVWxIYUpFVmV3Z29tR0JuWURXRFV2WGxJM3FDakliWkFrc283NzAxMnFXbnRpX3RqTlNIYmZFUXItZF9KRzR3bnFKalVvaHdFM1ZyN3VJR0JmS1FaMTZROUFlb0dzYkhscDRIZkk5cS1pMmladG5OSFFuU2ZOVSIsImUiOiJBUUFCIiwia3R5IjoiUlNBIiwiYWxnIjoiUlMyNTYifX0=.
eyJwcm9maWxlIjp7ImlkIjoiNGI0NzBlYzgtMDAzMy00ZmFlLWIzZDgtNWUyNDhkOWU3YmMzIiwidXNlcmlkIjoiam9obi5kb2VAbmV4dXNncm91cC5jb20iLCJzaWduZWRrZXlzIjpbImV5SmhiR2NpT2lKU1V6STFOaUlzSW10cFpDSTZJbk5wWjI1bGNpSXNJbTV2Ym1ObElqb2lNVEl6TkRVMk56ZzVJbjA9LmV5SjFjMlVpT2lKVFNVY2lMQ0poYkdjaU9pSlNVekkxTmlJc0ltdDBlU0k2SWxKVFFTSXNJbVVpT2lKQlVVRkNJaXdpYmlJNkluaHhXWE5pWTNWSFNURTVUbFZzVjJveFVIRXpXRGN6UWxOWmJrbzRla1JtVUY4M09YWlZjRkJ4U25WdGFrVXpOV3BxZWtNNVIycG1ZWFJGYTFCR056UlZWVk0wVldGcVpuSmhOSEp0VGtscmJYVnRkM2QyTFdKdVRIVjJkMDlYZGxaRGJuUm9aVlUwV2xoU2NrVnhNUzEzY1hkSVZtNUVaM2R1UWtaVlMwaDFPVTlIYVU1bk5UVkVlVkpqWlZsaFJqbDFUME16UlVKSGRrNW1iMnBtZFVVNVRuUkVRalJRTURaWGNVbGhSMGRVWTNGWFVqTlRObkEwVFRCalQzVm5ZVmxSWVZobWJXeFJUWFEyU0dSblZXSm5UVE5NYmtOT1YzTkdhVkZRUkMxaFRrVXpXSEJJYmtkMlkxOUJXbmRaT1ROelMzcE9TVXBKVGxwdVQzQklTbTFDVFZSSlpIbHpSM05EZEhacGFWcGhaRW8xYldZNGVYSkdVa3hpZG1wZlR6UmxWVzlwWWsxQlRtbGFUVEJMY0RKcVMyUjRSRk5HUmtKYVIxOVlUVzFLVEZJMFEwRklVR3hsWmxJNFUyZE9helpKV1hkSWR5SXNJbXRwWkNJNkluTnBaMjVsY2lJc0ltNGpiR1Z1SWpvaU1qQTBPQ0lzSW10bGVWOXpkR0YwWlNJNklrRkRWRWxXUlNKOS5vU25HcE0xWkN3VjRMN3VtMUc1TFVwc3h5cXVRcG9TMDhINEstTUJNZVBuVk10VzhoRHpzSVVLRTc2WW1YeldGVkFoNy05RC1EaE91V0JicHRXV3ZMa2lMcURWRk1IXzlUVXA3WGh2MFZNaWpNQUpfcTN2M0UyamJJMXh0MUZsQUZJejBULS1LS081SS03SXNrMGUxejI1X0Q4R0FaajJqNFhZeTFxZjZ1UmFwSFNweG1wdlh1TE9fbXg1ZUdiR1p1cEVkamlaeUNyWDd1dUJ2TGNnTVJVYnpMNXBHaEIwd2RrSGJHNXlraEJlekVGLXFBNmlvSElCNGRSYmhxcWsxZl9TcjFzZE1SRHUtM2tnWnZXMlljUExBNmljTEE5VzZHVXBxQmUydUs5NlZFemt6TUh5N0Y5aUU0ZUVEd3RRb0FsaWxId3NESFFnbHZub2VQemtnUnciXSwibmFtZSI6IlRlc3RQcm9maWxlIiwic2VydmVybmFtZSI6Im5leHVzLWhlcm1vZDEiLCJib3h1cmwiOiJodHRwczpcL1wvbmV4dXMtY29kMS50ZXN0Lm5leHVzZ3JvdXAuY29tOjIwNDAwXC9oZXJtb2RcL3Jlc3RcL21zXC8zOGIwMGFmOC03YjYwLTQ0YzEtOGFmMS05ZDM3NDFjZjBhMzEifSwiZGV2aWNlaW5mbyI6eyJvcGVyYXRpbmdzeXN0ZW0iOiJpT1MgKDEwLjMuMikiLCJtb2RlbCI6ImlQaG9uZSIsImFwbmRldmljZXRva2VuIjoiNjU1MmNkZmEzN2M4NTgyODYwNjRmOTk1ZjFhYThiYWY3OTc4MjhlMzIzOGZkN2Y4NDFmYmZhMzRiYWViNjlkNCIsIm5hbWUiOiJBbmRlcnPigJlzIGlQaG9uZSJ9fQ==
.Sx54ArHOVWRPVcvozInXbRobI5WbVqCuH9gp7OnE0UPq1IcMHLr47Cf5mVhAOw7VS_93cCoZwRWVo3y6z1iFv40RyGuu7bqiOKtgZ4tWy601ITSS91Ur8GGux-wUg6eYM8DmhL_yPoVQqZvlSadrAZEOKP1pIYBu9snONK2Qmg4d30qWDPl4LImbJstFv3kIfuD1_ul2i1QLOH51A5-8HPcnFVNwglYFKtPQoTjUBS6_ioP3KdnqeI6eGDVcqsRxkdV9Uum5JXkF2Amnq72fbxqtYeic-_DCIn9m6h8g31ovoEPzftv8MpkvKSvxly4QSxVlkztRN7jK65Cu7KW2PA"
}
},
"commandId" : "1101",
"destinations" : [ {
"to" : "@tmp",
"bid" : "21b279cc-3f82-48e2-b200-fd9bbc5dfb4a",
"uri" : "com.nexusgroup.plugout:///?url=https%3a%2f%2fnexus-cod1.test.nexusgroup.com%3A20400%2fhermod%2Frest%2Fms%2F21b279cc-3f82-48e2-b200-fd9bbc5dfb4a&token=a8b6eeb1-8218-497a-b8f8-14c81435060e",
"mid" : "08aeef86-b789-4bf3-88fa-ab0c96824a6c",
"location" : "https://nexus-cod1.test.nexusgroup.com:20400/hermod/rest/ms/21b279cc-3f82-48e2-b200-fd9bbc5dfb4a/08aeef86-b789-4bf3-88fa-ab0c96824a6c"
} ],
"commandType" : "PROV",
"state" : "COMPLETED",
"fqdn" : "nexus-cod1.test.nexusgroup.com"
}
Where the generated profile and its keys are included in the data field and where data is a compact JSON Web Signature (JWS) base64url(header).base64url(payload).base64url(signature).
Example: header, payload, and signature
header
{
"kid":"ATTESTATION",
"nonce":"123456789",
"alg":"RS256","
jwk":{
"use":"sig",
"kid":"attestation",
"n":"AOI7U-prkI8HRKoaJKD3QtTSNmsm1_p_uiXb1QLy9gMSuGjZ8HNrpVT4kcR1Uudw3pOKndn7NBec5b92AgM5WvSPxGDOYfgK3xKRUayywFD3J6RV1vUXtjW4wLmvzGbtYwHHPyrqhT73KrHhnLh2dpJ3MO5SCAWuNbiQ6EVlnLdSxYphFxGvngqcJG6_DJhkolr9b_LLTt149tGkyYqL7aiO6OjVtJRQdUlHaJEVewgomGBnYDWDUvXlI3qCjIbZAkso77012qWnti_tjNSHbfEQr-d_JG4wnqJjUohwE3Vr7uIGBfKQZ16Q9AeoGsbHlp4HfI9q-i2iZtnNHQnSfNU",
"e":"AQAB",
"kty":"RSA",
"alg":"RS256"
}
}
payload
{
"profile":{
"id":"4b470ec8-0033-4fae-b3d8-5e248d9e7bc3",
"userid":"john.doe@nexusgroup.com",
"signedkeys":["eyJhbGciOiJSUzI1NiIsImtpZCI6InNpZ25lciIsIm5vbmNlIjoiMTIzNDU2Nzg5In0=.eyJ1c2UiOiJTSUciLCJhbGciOiJSUzI1NiIsImt0eSI6IlJTQSIsImUiOiJBUUFCIiwibiI6InhxWXNiY3VHSTE5TlVsV2oxUHEzWDczQlNZbko4ekRmUF83OXZVcFBxSnVtakUzNWpqekM5R2pmYXRFa1BGNzRVVVM0VWFqZnJhNHJtTklrbXVtd3d2LWJuTHV2d09XdlZDbnRoZVU0WlhSckVxMS13cXdIVm5EZ3duQkZVS0h1OU9HaU5nNTVEeVJjZVlhRjl1T0MzRUJHdk5mb2pmdUU5TnREQjRQMDZXcUlhR0dUY3FXUjNTNnA0TTBjT3VnYVlRYVhmbWxRTXQ2SGRnVWJnTTNMbkNOV3NGaVFQRC1hTkUzWHBIbkd2Y19BWndZOTNzS3pOSUpJTlpuT3BISm1CTVRJZHlzR3NDdHZpaVphZEo1bWY4eXJGUkxidmpfTzRlVW9pYk1BTmlaTTBLcDJqS2R4RFNGRkJaR19YTW1KTFI0Q0FIUGxlZlI4U2dOazZJWXdIdyIsImtpZCI6InNpZ25lciIsIm4jbGVuIjoiMjA0OCIsImtleV9zdGF0ZSI6IkFDVElWRSJ9.oSnGpM1ZCwV4L7um1G5LUpsxyquQpoS08H4K-MBMePnVMtW8hDzsIUKE76YmXzWFVAh7-9D-DhOuWBbptWWvLkiLqDVFMH_9TUp7Xhv0VMijMAJ_q3v3E2jbI1xt1FlAFIz0T--KKO5I-7Isk0e1z25_D8GAZj2j4XYy1qf6uRapHSpxmpvXuLO_mx5eGbGZupEdjiZyCrX7uuBvLcgMRUbzL5pGhB0wdkHbG5ykhBezEF-qA6ioHIB4dRbhqqk1f_Sr1sdMRDu-3kgZvW2YcPLA6icLA9W6GUpqBe2uK96VEzkzMHy7F9iE4eEDwtQoAlilHwsDHQglvnoePzkgRw"],
"name":"TestProfile",
"servername":"nexus-hermod1",
"boxurl":"https:\/\/nexus-cod1.test.nexusgroup.com:20400\/hermod\/rest\/ms\/38b00af8-7b60-44c1-8af1-9d3741cf0a31"
},
"deviceinfo":{
"operatingsystem":"iOS (10.3.2)",
"model":"iPhone",
"apndevicetoken":"6552cdfa37c858286064f995f1aa8baf797828e3238fd7f841fbfa34baeb69d4",
"name":"Anders's iPhone"
}
}
signature
Sx54ArHOVWRPVcvozInXbRobI5WbVqCuH9gp7OnE0UPq1IcMHLr47Cf5mVhAOw7VS_93cCoZwRWVo3y6z1iFv40RyGuu7bqiOKtgZ4tWy601ITSS91Ur8GGux-wUg6eYM8DmhL_yPoVQqZvlSadrAZEOKP1pIYBu9snONK2Qmg4d30qWDPl4LImbJstFv3kIfuD1_ul2i1QLOH51A5-8HPcnFVNwglYFKtPQoTjUBS6_ioP3KdnqeI6eGDVcqsRxkdV9Uum5JXkF2Amnq72fbxqtYeic-_DCIn9m6h8g31ovoEPzftv8MpkvKSvxly4QSxVlkztRN7jK65Cu7KW2PA==
The keys are included in the signed keys field. The JSON Web Key (JWK) is signed by itself for proof of possession.
Example: Decoded signed_keys element
Header
{
"alg":"RS256",
"kid":"signer",
"nonce":"123456789"
}
Payload (JWK)
{
"use":"SIG",
"alg":"RS256",
"kty":"RSA",
"e":"AQAB",
"n":"xqYsbcuGI19NUlWj1Pq3X73BSYnJ8zDfP_79vUpPqJumjE35jjzC9GjfatEkPF74UUS4Uajfra4rmNIkmumwwv-bnLuvwOWvVCntheU4ZXRrEq1-wqwHVnDgwnBFUKHu9OGiNg55DyRceYaF9uOC3EBGvNfojfuE9NtDB4P06WqIaGGTcqWR3S6p4M0cOugaYQaXfmlQMt6HdgUbgM3LnCNWsFiQPD-aNE3XpHnGvc_AZwY93sKzNIJINZnOpHJmBMTIdysGsCtviiZadJ5mf8yrFRLbvj_O4eUoibMANiZM0Kp2jKdxDSFFBZG_XMmJLR4CAHPlefR8SgNk6IYwHw",
"kid":"signer",
"n#len":"2048",
"key_state":"ACTIVE"
}
.
oSnGpM1ZCwV4L7um1G5LUpsxyquQpoS08H4K-MBMePnVMtW8hDzsIUKE76YmXzWFVAh7-9D-DhOuWBbptWWvLkiLqDVFMH_9TUp7Xhv0VMijMAJ_q3v3E2jbI1xt1FlAFIz0T--KKO5I-7Isk0e1z25_D8GAZj2j4XYy1qf6uRapHSpxmpvXuLO_mx5eGbGZupEdjiZyCrX7uuBvLcgMRUbzL5pGhB0wdkHbG5ykhBezEF-qA6ioHIB4dRbhqqk1f_Sr1sdMRDu-3kgZvW2YcPLA6icLA9W6GUpqBe2uK96VEzkzMHy7F9iE4eEDwtQoAlilHwsDHQglvnoePzkgRw