{"_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.dotdigital.com/v2/docs/creating-a-push-notification-profile#in-engagement-cloud\\\"><div class=\\\"box box1\\\">Create a push notification profile in Engagement Cloud</div></a></div>\\n<div class=\\\"arrow\\\">→</div>\\n<div class=\\\"content\\\"><a href=\\\"https://developer.dotdigital.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.dotdigital.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 Engagement Cloud.\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 (Engagement Cloud)\",\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 Engagement Cloud. \\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 Engagement Cloud.\\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 Engagement Cloud.\\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 Engagement Cloud.\\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 Engagement Cloud.\\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 Engagement Cloud.\\n aud: \\\"<Audience>\\\",\\n //<Issuer> string must be the same as the value of the 'Issuer' field in your push notification profile in Engagement Cloud.\\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 Engagement Cloud. \\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 Engagement Cloud","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 Engagement Cloud