{"_id":"5b3de50fe785c80003658650","project":"55dd9f2e0efd5821000d54d9","version":{"_id":"55dd9f4dab0e4d210045aae9","__v":45,"project":"55dd9f2e0efd5821000d54d9","createdAt":"2015-08-26T11:13:17.024Z","releaseDate":"2015-08-26T11:13:17.024Z","categories":["55dd9f4dab0e4d210045aaea","55ddb5fa9067202b00ddff6f","55e0472c6bad670d0081f213","55e04764a44fae0d00214671","55e047a9a44fae0d00214672","55e047b258c5460d0076a9a7","55e95e337fc27b2d00d32cf2","55e979bda7ca823900ad549a","55edb8c18dcb210d0056900b","55f0365c8563861700a33765","55f03677d58f9b1900acf996","55f036938eeefc23001ea5de","55f036a38563861700a33767","55f036c08563861700a33769","55f036d02911b72100482cd7","55f036e92911b72100482cd9","55f036fa8563861700a3376b","55f0370ee507711900e58c69","55f0371df6101b1900c70700","55f0374f2911b72100482cdb","55f0375e2911b72100482cdc","560eb0f659cb8d0d0015cd52","560eb25239fad419002ae1e0","561fb64d4d67490d00804b2a","562b9f775a39cd0d009aff22","562ba0505a39cd0d009aff23","562ba149d56bc30d00f0cb18","562ba595f68a5f0d007b1f3b","562ba78fd56bc30d00f0cb1b","562ba8b95a39cd0d009aff27","562baadf6562140d001501d2","562bab37f68a5f0d007b1f3d","562bc1bf9ebc950d000f7523","562bc99ced4bea0d00c11dfa","562bd29c1b98640d00714520","562bd5875a39cd0d009aff60","562bdfabff2da50d002c0aaf","562be0bd5a39cd0d009aff75","57a0b476d8313e1900454439","5b19051beece890003020163","5b34ded01cb20f000391ad6d","5b3a325acffe770003fd29e5","5b3c737a7f7b890003365501","5b3c929b367036000391b11e","5b7c1e210dc2e20003871521"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"2.0.0","version":"2"},"category":{"_id":"5b34ded01cb20f000391ad6d","project":"55dd9f2e0efd5821000d54d9","version":"55dd9f4dab0e4d210045aae9","__v":0,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2018-06-28T13:12:48.898Z","from_sync":false,"order":2,"slug":"push-notifications","title":"Push notifications"},"user":"5a251846c297dc0012e531cd","githubsync":"","__v":0,"parentDoc":null,"updates":[],"next":{"pages":[],"description":""},"createdAt":"2018-07-05T09:29:51.917Z","link_external":false,"link_url":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":2,"body":"[block:html]\n{\n  \"html\": \"<div id=\\\"userMap\\\">\\n<div class=\\\"content\\\"><a href=\\\"https://developer.dotmailer.com/v2/docs/creating-a-push-notification-profile#in-dotmailer\\\"><div class=\\\"box box1\\\">Create a push notification profile in dotmailer</div></a></div>\\n<div class=\\\"arrow\\\">→</div>\\n<div class=\\\"content\\\"><a href=\\\"https://developer.dotmailer.com/v2/docs/creating-a-json-web-token\\\"><div class=\\\"box box2 active\\\">Create a class or function that generates a JSON Web Token</div></a></div>\\n<div class=\\\"arrow\\\">→</div>\\n<div class=\\\"content\\\"><a href=\\\"https://developer.dotmailer.com/v2/docs/setting-up-push-notifications#section-mobile-sdk-options\\\"><div class=\\\"box box3\\\">Use one of our mobile SDKs in your app</div></a></div>\\n<div class=\\\"clearfix\\\"></div></div>\\n\\n<style>\\n  .box {\\n    padding: 10px;\\n    border: 2px solid #000;\\n    width: 120px;\\n    height: 120px;\\n    background-color: #EAEAEA;\\n    hyphens: auto;\\n    float: left;\\n    font-size: 12px;\\n}\\n\\n.box:hover {\\n    background-color: #82bc42;\\n}\\n\\n.box.active {\\n    background-color: #82bc42;\\n}\\n\\n#userMap {\\n    overflow-x: auto;\\n    overflow-y: auto;\\n    padding: 20px;\\n    min-width: 770px;\\n}\\n\\n#userMap a:hover {\\n    text-decoration: none;\\n  }\\n\\ndiv.arrow {\\n    max-width: 50px;\\n    margin-left: 15px;\\n    margin-right: 15px;\\n    font-size: 50px;\\n}\\n\\n\\n#userMap div.arrow, #userMap div.content {\\n    float: left;\\n}\\n\\n.clearfix {\\n    clear: both;\\n}\\n\\n\\n#userMap div.arrow {\\n    position: relative;\\n    top: 45px;\\n}\\n\\n.box1 {\\n    margin-left:0px;\\n}\\n\\ndiv.box.box1 {\\n    margin-left: -20px;\\n}\\n\\n</style>\"\n}\n[/block]\nOur mobile SDKs  use [JSON Web Tokens (JWT)](https://jwt.io/) to authenticate your app.\n\nIn your code, you'll need to create a class, or a function that generates a JWT and sends it to dotmailer.\n\nWhichever provider you use to create a JWT, the JWT's registered claims must match the values of the following 'Authentication' fields in your push notifications profile:\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"JWT registered claim\",\n    \"h-1\": \"Authentication field (dotmailer)\",\n    \"h-2\": \"Example value\",\n    \"0-0\": \"`iss`\",\n    \"1-0\": \"`aud`\",\n    \"2-0\": \"`sub`\",\n    \"0-1\": \"Issuer\",\n    \"1-1\": \"Audience\",\n    \"2-1\": \"ID Claim\",\n    \"2-2\": \"'sub'\",\n    \"1-2\": \"'https://api.comapi.com'\",\n    \"0-2\": \"'https://api.comapi.com/defaultauth'\"\n  },\n  \"cols\": 3,\n  \"rows\": 3\n}\n[/block]\nYou must sign the JWT with the value of the 'Shared secret' field in your push notification profile.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/eca3883-Channel_management_push_notification_profile_-_Authentication-shared_secret.png\",\n        \"Channel management_push notification profile - Authentication-shared secret.png\",\n        600,\n        262,\n        \"#e7e3e2\"\n      ]\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"danger\",\n  \"title\": \"Important security note\",\n  \"body\": \"We recommend that you do not hard code your shared secret on the client side. Instead, this value should be stored on the server side.\"\n}\n[/block]\nA cryptographic nonce must also be used by your JWT provider to create the token. The SDK passes this `nonce` as an argument to your class or function during initialisation of the SDK.\n\n## Android JWT code sample\n\n*JWT provider:* [Java JWT](https://github.com/jwtk/jjwt).\n\nAny class that you create to generate a JWT token must extend the `ComapiAuthenticator` class.\n\nAny logic that creates the JWT token must be inside the `onAuthenticationChallenge()` method.\nThis method takes two parameters: `AuthClient` and `ChallengeOptions`.\n\nGet the value of the nonce by calling the `ChallengeOptions.GetNonce()` method\n\nWhen your JWT token is returned, pass it to the `authenticateWithToken()` method of the `AuthClient` object.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"package com.example.testapp;\\n\\nimport android.content.SharedPreferences;\\nimport android.text.TextUtils;\\nimport android.util.Base64;\\n\\nimport com.comapi.ComapiAuthenticator;\\nimport com.comapi.internal.network.AuthClient;\\nimport com.comapi.internal.network.ChallengeOptions;\\n\\nimport java.io.UnsupportedEncodingException;\\nimport java.util.HashMap;\\nimport java.util.Map;\\nimport java.util.concurrent.TimeUnit;\\n\\nimport io.jsonwebtoken.Jwts;\\nimport io.jsonwebtoken.SignatureAlgorithm;\\n\\npublic class ChallengeHandler extends ComapiAuthenticator {\\n\\n\\n    :::at:::Override\\n    public void onAuthenticationChallenge(AuthClient authClient, ChallengeOptions challengeOptions) {\\n\\n      try {\\n\\n        byte[] data;\\n        //<Shared secret> string must be the same as the value of the 'Shared secret' field in your push notification profile in dotmailer. \\n        data = \\\"<Shared secret>\\\".getBytes(\\\"UTF-8\\\");\\n\\n        String base64Secret = Base64.encodeToString(data, Base64.DEFAULT);\\n\\n        Map<String, Object> header = new HashMap<>();\\n        header.put(\\\"typ\\\", \\\"JWT\\\");\\n\\n        Map<String, Object> claims = new HashMap<>();\\n        claims.put(\\\"nonce\\\", challengeOptions.getNonce());\\n        //<ID claim> string must be the same as the value of the 'ID claim' field in your push notification profile in dotmailer.\\n        claims.put(\\\"sub\\\", \\\"<ID claim>\\\");\\n        //<Audience> string must be the same as the value of the 'Audience' field in your push notification profile in dotmailer.\\n        claims.put(\\\"aud\\\", \\\"<Audience>\\\");\\n        //<Issuer> string must be the same as the value of the 'Issuer' field in your push notification profile in dotmailer.\\n        claims.put(\\\"iss\\\", \\\"<Issuer>\\\");\\n        claims.put(\\\"iat\\\", System.currentTimeMillis());\\n        claims.put(\\\"exp\\\", System.currentTimeMillis() + TimeUnit.DAYS.toMillis(30));\\n\\n        final String token = Jwts.builder()\\n          .setHeader(header)\\n          .setClaims(claims)\\n          .signWith(SignatureAlgorithm.HS256, base64Secret)\\n          .compact();\\n\\n        //Pass the JWT token to the SDK.\\n        authClient.authenticateWithToken(token);\\n\\n      } catch (UnsupportedEncodingException e) {\\n        e.printStackTrace();\\n        //Authorisation failed.\\n        authClient.authenticateWithToken(null);\\n      }\\n    }\\n}\",\n      \"language\": \"java\",\n      \"name\": \"ChallengeHandler sample class\"\n    }\n  ]\n}\n[/block]\n## iOS JWT code sample\n\n*JWT provider:* ['Swifty JWT' framework](https://github.com/Wstunes/SwiftyJWT).\n\nAny class that you create to generate a JWT token must be a subclass of the `AuthenticationDelegate` superclass.\n\nGet the value of the nonce by using the `authenticationChallenge.nonce` property.\n\nWhen your JWT token is returned, pass it to the `continueWithToken()` method.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"import SwiftyJWT\\n\\nclass ChallengeHandler: AuthenticationDelegate {\\n    \\n    func client(_ client: ComapiClient,\\n                didReceiveAuthenticationChallenge authenticationChallenge: AuthenticationChallenge,\\n                completion continueWithToken: @escaping (String?) -> Void) {\\n\\nlet alg = JWTAlgorithm.hs256(\\\"<Shared secret>\\\")\\nvar payload = JWTPayload()\\npayload.issuer = \\\"<Issuer>\\\"\\npayload.subject = \\\"<ID Claim>\\\"\\npayload.audience = \\\"<Audience>\\\"\\npayload.nonce = authenticationChallenge.nonce\\n\\nlet token = try? JWT.init(payload: payload, algorithm: alg)\\n\\n                  continueWithToken(token)\\n\\t\\t}\\n}\",\n      \"language\": \"swift\",\n      \"name\": \"ChallengeHandler sample class\"\n    }\n  ]\n}\n[/block]\n## JavaScript JWT code sample\n\n*JWT provider:* [jsrassign](https://kjur.github.io/jsrsasign/) library.\n\nGet the value of the nonce by using the `nonce` property of the first parameter.\n\nWhen your JWT token is returned, pass it to the `answerAuthenticationChallenge()` function (second parameter of your `challengeHandler()` function).\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"function challengeHandler (options, answerAuthenticationChallenge) {\\n    // Header\\n    var oHeader = { alg: 'HS256', typ: 'JWT' };\\n    // Payload\\n    var tNow = KJUR.jws.IntDate.get('now');\\n    var tEnd = KJUR.jws.IntDate.get('now + 1day');\\n    var oPayload = {\\n      \\t//<ID claim> string must be the same as the value of the 'ID claim' field in your push notification profile in dotmailer.\\n        sub: \\\"<ID Claim>\\\",\\n        nonce: options.nonce,\\n      \\t//<Audience> string must be the same as the value of the 'Audience' field in your push notification profile in dotmailer.\\n        aud: \\\"<Audience>\\\",\\n      //<Issuer> string must be the same as the value of the 'Issuer' field in your push notification profile in dotmailer.\\n        iss: \\\"<Issuer>\\\",\\n        iat: tNow,\\n        exp: tEnd,\\n    };\\n    var sHeader = JSON.stringify(oHeader);\\n    var sPayload = JSON.stringify(oPayload);\\n  \\t//<Shared secret> string must be the same as the value of the 'Shared secret' field in your push notification profile in dotmailer. \\n    var sJWT = KJUR.jws.JWS.sign(\\\"HS256\\\", sHeader, sPayload, \\\"<Shared secret>\\\");\\n    answerAuthenticationChallenge(sJWT);\\n}\",\n      \"language\": \"javascript\",\n      \"name\": \"challengeHandler sample function\"\n    }\n  ]\n}\n[/block]","excerpt":"A tutorial for creating a function or class that generates a JWT for authorising your app to receive push notifications from dotmailer","slug":"creating-a-json-web-token","type":"basic","title":"Creating a JSON Web Token"}

Creating a JSON Web Token

A tutorial for creating a function or class that generates a JWT for authorising your app to receive push notifications from dotmailer

[block:html] { "html": "<div id=\"userMap\">\n<div class=\"content\"><a href=\"https://developer.dotmailer.com/v2/docs/creating-a-push-notification-profile#in-dotmailer\"><div class=\"box box1\">Create a push notification profile in dotmailer</div></a></div>\n<div class=\"arrow\">→</div>\n<div class=\"content\"><a href=\"https://developer.dotmailer.com/v2/docs/creating-a-json-web-token\"><div class=\"box box2 active\">Create a class or function that generates a JSON Web Token</div></a></div>\n<div class=\"arrow\">→</div>\n<div class=\"content\"><a href=\"https://developer.dotmailer.com/v2/docs/setting-up-push-notifications#section-mobile-sdk-options\"><div class=\"box box3\">Use one of our mobile SDKs in your app</div></a></div>\n<div class=\"clearfix\"></div></div>\n\n<style>\n .box {\n padding: 10px;\n border: 2px solid #000;\n width: 120px;\n height: 120px;\n background-color: #EAEAEA;\n hyphens: auto;\n float: left;\n font-size: 12px;\n}\n\n.box:hover {\n background-color: #82bc42;\n}\n\n.box.active {\n background-color: #82bc42;\n}\n\n#userMap {\n overflow-x: auto;\n overflow-y: auto;\n padding: 20px;\n min-width: 770px;\n}\n\n#userMap a:hover {\n text-decoration: none;\n }\n\ndiv.arrow {\n max-width: 50px;\n margin-left: 15px;\n margin-right: 15px;\n font-size: 50px;\n}\n\n\n#userMap div.arrow, #userMap div.content {\n float: left;\n}\n\n.clearfix {\n clear: both;\n}\n\n\n#userMap div.arrow {\n position: relative;\n top: 45px;\n}\n\n.box1 {\n margin-left:0px;\n}\n\ndiv.box.box1 {\n margin-left: -20px;\n}\n\n</style>" } [/block] Our mobile SDKs use [JSON Web Tokens (JWT)](https://jwt.io/) to authenticate your app. In your code, you'll need to create a class, or a function that generates a JWT and sends it to dotmailer. Whichever provider you use to create a JWT, the JWT's registered claims must match the values of the following 'Authentication' fields in your push notifications profile: [block:parameters] { "data": { "h-0": "JWT registered claim", "h-1": "Authentication field (dotmailer)", "h-2": "Example value", "0-0": "`iss`", "1-0": "`aud`", "2-0": "`sub`", "0-1": "Issuer", "1-1": "Audience", "2-1": "ID Claim", "2-2": "'sub'", "1-2": "'https://api.comapi.com'", "0-2": "'https://api.comapi.com/defaultauth'" }, "cols": 3, "rows": 3 } [/block] You must sign the JWT with the value of the 'Shared secret' field in your push notification profile. [block:image] { "images": [ { "image": [ "https://files.readme.io/eca3883-Channel_management_push_notification_profile_-_Authentication-shared_secret.png", "Channel management_push notification profile - Authentication-shared secret.png", 600, 262, "#e7e3e2" ] } ] } [/block] [block:callout] { "type": "danger", "title": "Important security note", "body": "We recommend that you do not hard code your shared secret on the client side. Instead, this value should be stored on the server side." } [/block] A cryptographic nonce must also be used by your JWT provider to create the token. The SDK passes this `nonce` as an argument to your class or function during initialisation of the SDK. ## Android JWT code sample *JWT provider:* [Java JWT](https://github.com/jwtk/jjwt). Any class that you create to generate a JWT token must extend the `ComapiAuthenticator` class. Any logic that creates the JWT token must be inside the `onAuthenticationChallenge()` method. This method takes two parameters: `AuthClient` and `ChallengeOptions`. Get the value of the nonce by calling the `ChallengeOptions.GetNonce()` method When your JWT token is returned, pass it to the `authenticateWithToken()` method of the `AuthClient` object. [block:code] { "codes": [ { "code": "package com.example.testapp;\n\nimport android.content.SharedPreferences;\nimport android.text.TextUtils;\nimport android.util.Base64;\n\nimport com.comapi.ComapiAuthenticator;\nimport com.comapi.internal.network.AuthClient;\nimport com.comapi.internal.network.ChallengeOptions;\n\nimport java.io.UnsupportedEncodingException;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\nimport io.jsonwebtoken.Jwts;\nimport io.jsonwebtoken.SignatureAlgorithm;\n\npublic class ChallengeHandler extends ComapiAuthenticator {\n\n\n @Override\n public void onAuthenticationChallenge(AuthClient authClient, ChallengeOptions challengeOptions) {\n\n try {\n\n byte[] data;\n //<Shared secret> string must be the same as the value of the 'Shared secret' field in your push notification profile in dotmailer. \n data = \"<Shared secret>\".getBytes(\"UTF-8\");\n\n String base64Secret = Base64.encodeToString(data, Base64.DEFAULT);\n\n Map<String, Object> header = new HashMap<>();\n header.put(\"typ\", \"JWT\");\n\n Map<String, Object> claims = new HashMap<>();\n claims.put(\"nonce\", challengeOptions.getNonce());\n //<ID claim> string must be the same as the value of the 'ID claim' field in your push notification profile in dotmailer.\n claims.put(\"sub\", \"<ID claim>\");\n //<Audience> string must be the same as the value of the 'Audience' field in your push notification profile in dotmailer.\n claims.put(\"aud\", \"<Audience>\");\n //<Issuer> string must be the same as the value of the 'Issuer' field in your push notification profile in dotmailer.\n claims.put(\"iss\", \"<Issuer>\");\n claims.put(\"iat\", System.currentTimeMillis());\n claims.put(\"exp\", System.currentTimeMillis() + TimeUnit.DAYS.toMillis(30));\n\n final String token = Jwts.builder()\n .setHeader(header)\n .setClaims(claims)\n .signWith(SignatureAlgorithm.HS256, base64Secret)\n .compact();\n\n //Pass the JWT token to the SDK.\n authClient.authenticateWithToken(token);\n\n } catch (UnsupportedEncodingException e) {\n e.printStackTrace();\n //Authorisation failed.\n authClient.authenticateWithToken(null);\n }\n }\n}", "language": "java", "name": "ChallengeHandler sample class" } ] } [/block] ## iOS JWT code sample *JWT provider:* ['Swifty JWT' framework](https://github.com/Wstunes/SwiftyJWT). Any class that you create to generate a JWT token must be a subclass of the `AuthenticationDelegate` superclass. Get the value of the nonce by using the `authenticationChallenge.nonce` property. When your JWT token is returned, pass it to the `continueWithToken()` method. [block:code] { "codes": [ { "code": "import SwiftyJWT\n\nclass ChallengeHandler: AuthenticationDelegate {\n \n func client(_ client: ComapiClient,\n didReceiveAuthenticationChallenge authenticationChallenge: AuthenticationChallenge,\n completion continueWithToken: @escaping (String?) -> Void) {\n\nlet alg = JWTAlgorithm.hs256(\"<Shared secret>\")\nvar payload = JWTPayload()\npayload.issuer = \"<Issuer>\"\npayload.subject = \"<ID Claim>\"\npayload.audience = \"<Audience>\"\npayload.nonce = authenticationChallenge.nonce\n\nlet token = try? JWT.init(payload: payload, algorithm: alg)\n\n continueWithToken(token)\n\t\t}\n}", "language": "swift", "name": "ChallengeHandler sample class" } ] } [/block] ## JavaScript JWT code sample *JWT provider:* [jsrassign](https://kjur.github.io/jsrsasign/) library. Get the value of the nonce by using the `nonce` property of the first parameter. When your JWT token is returned, pass it to the `answerAuthenticationChallenge()` function (second parameter of your `challengeHandler()` function). [block:code] { "codes": [ { "code": "function challengeHandler (options, answerAuthenticationChallenge) {\n // Header\n var oHeader = { alg: 'HS256', typ: 'JWT' };\n // Payload\n var tNow = KJUR.jws.IntDate.get('now');\n var tEnd = KJUR.jws.IntDate.get('now + 1day');\n var oPayload = {\n \t//<ID claim> string must be the same as the value of the 'ID claim' field in your push notification profile in dotmailer.\n sub: \"<ID Claim>\",\n nonce: options.nonce,\n \t//<Audience> string must be the same as the value of the 'Audience' field in your push notification profile in dotmailer.\n aud: \"<Audience>\",\n //<Issuer> string must be the same as the value of the 'Issuer' field in your push notification profile in dotmailer.\n iss: \"<Issuer>\",\n iat: tNow,\n exp: tEnd,\n };\n var sHeader = JSON.stringify(oHeader);\n var sPayload = JSON.stringify(oPayload);\n \t//<Shared secret> string must be the same as the value of the 'Shared secret' field in your push notification profile in dotmailer. \n var sJWT = KJUR.jws.JWS.sign(\"HS256\", sHeader, sPayload, \"<Shared secret>\");\n answerAuthenticationChallenge(sJWT);\n}", "language": "javascript", "name": "challengeHandler sample function" } ] } [/block]