How To Create A Jwt Token In Java
Our mobile SDKs use JSON Web Tokens (JWT) to authenticate your app. These are a commonly used method for providing authentication and authorization using one simple token.
In your code, you'll need to create a function that generates a valid JWT using the JWT authorization details provided by Dotdigital in your push notification profile, and a cryptographic nonce which we pass. We will refer to this as the challenge function.
Whichever provider or method you use to create a JWT, the JWT's claims must include the following with values provided in the Authentication fields in your push notification profile you setup in Dotdigital:
JWT Claim | Value |
---|---|
| The Issuer value in your Dotdigital push notification profile |
| The Audience value in your Dotdigital push notification profile |
| A unique and consistent identifier for the user, such as a user id, email address |
| The nonce is used to randomize the ciphers for added security |
The sub
claim in the JWT is used to identify the push profile that is later associated with your Dotdigital contact when you set the email address on the profile. It needs to be unique and preferably consistent per user so that if a user uses your app on multiple devices all these devices are grouped under the same push profile id and therefore when you send a push to the contact it is sent to all their devices.
If you cannot allocate a unique and consistent sub
claim for a user possibly because your app allows anonymous users, then you must use a unique and consistent identifier for the device, such as a GUID which you store in the app, then contacts will be restricted to a single device for pushes.
🚧
Ensure your
sub
claim is unique and consistent per userThe value you pass in the sub claim will be the unique user id and cannot be changed later. It is really important that the values are unique per user, and ideally don't change between installs.
📘
Which push profile is associated with my contact?
On your Dotdigital contacts you will have had a PUSHOPTIN_xxx field automatically created when you setup your push notification channel. This will contain the push profile id that is associated with your contact.
JWTs are digitally signed to prove it was issued by a trusted party. You must sign the JWT with the value of the Shared secret field from your push notification profile and the nonce we pass your function to prove it was issued by you.
A cryptographic nonce must also be used by your JWT provider when creating the token to ensure that tokens always appear different even if they contain the same claims, this is a common security practice with cryptography. The SDK passes this nonce
as an argument to your challenge function during initialisation of the SDK where you will create or retrieve a JWT for your app user.
❗️
Important security note
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.
The following example code demonstrates how to create a challenge function and a self issued JWT for both Android and iOS:
JWT provider: Java JWT.
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.
package com.example.testapp; import android.content.SharedPreferences; import android.text.TextUtils; import android.util.Base64; import com.comapi.ComapiAuthenticator; import com.comapi.internal.network.AuthClient; import com.comapi.internal.network.ChallengeOptions; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; public class ChallengeHandler extends ComapiAuthenticator { @Override public void onAuthenticationChallenge(AuthClient authClient, ChallengeOptions challengeOptions) { try { byte[] data; //<Shared secret> string must be the same as the value of the 'Shared secret' field in your push notification profile in Dotdigital. data = "<Shared secret>".getBytes("UTF-8"); String base64Secret = Base64.encodeToString(data, Base64.DEFAULT); Map<String, Object> header = new HashMap<>(); header.put("typ", "JWT"); Map<String, Object> claims = new HashMap<>(); claims.put("nonce", challengeOptions.getNonce()); // ID claim, this claim name must be the same as the value of the 'ID claim' field in your push notification profile in Dotdigital, // the default value is 'sub', and the value of the claim must be a consitent unique value for the app user. claims.put("sub", "<Unique consitent app user id>"); //<Audience> string must be the same as the value of the 'Audience' field in your push notification profile in Dotdigital. claims.put("aud", "<Audience>"); //<Issuer> string must be the same as the value of the 'Issuer' field in your push notification profile in Dotdigital. claims.put("iss", "<Issuer>"); claims.put("iat", System.currentTimeMillis()); claims.put("exp", System.currentTimeMillis() + TimeUnit.DAYS.toMillis(30)); final String token = Jwts.builder() .setHeader(header) .setClaims(claims) .signWith(SignatureAlgorithm.HS256, base64Secret) .compact(); //Pass the JWT token to the SDK. authClient.authenticateWithToken(token); } catch (UnsupportedEncodingException e) { e.printStackTrace(); //Authorisation failed. authClient.authenticateWithToken(null); } } }
Here's an example implementation of a token generator in Objective-C and Swift using JWT
#import "CMPAuthenticationManager.h" #import <JWT/JWT.h> @implementation CMPAuthenticationManager + (NSString *)generateTokenForNonce:(NSString *)nonce profileID:(NSString *)profileID issuer:(NSString *)issuer audience:(NSString *)audience secret:(NSString *)secret { NSDate *now = [NSDate date]; NSDate *exp = [NSCalendar.currentCalendar dateByAddingUnit:NSCalendarUnitDay value:30 toDate:now options:0]; NSDictionary *headers = @{@"typ" : @"JWT"}; /* Claims notes: ID claim, this claim name must be the same as the value of the 'ID claim' field in your push notification profile in Dotdigital, the default value is 'sub', and the value of the claim must be a consitent unique value for the app user. 'aud' audience claim must be the same as the value of the 'Audience' field in your push notification profile in Dotdigital. 'iss' audience claim must be the same as the value of the 'Issuer' field in your push notification profile in Dotdigital. */ NSDictionary *payload = @{@"nonce" : nonce, @"sub" : profileID, @"iss" : issuer, @"aud" : audience, @"iat" : [NSNumber numberWithDouble:now.timeIntervalSince1970], @"exp" : [NSNumber numberWithDouble:exp.timeIntervalSince1970]}; NSData *secretData = [secret dataUsingEncoding:NSUTF8StringEncoding]; id<JWTAlgorithm> algorithm = [JWTAlgorithmFactory algorithmByName:@"HS256"]; NSString *token = [JWTBuilder encodePayload:payload].headers(headers).secretData(secretData).algorithm(algorithm).encode; return token; } @end /* Note that this should preferably be generated by your backend, the app should only retreive the token through an HTTP call */
import JWT class JWTokenGenerator { struct AuthHeaders { static let HeaderType = "JWT" } static func generate(tokenFor nonce: String, profileId: String, issuer: String, audience: String, secret: String) -> String { let now = Date() let exp = Calendar.current.date(byAdding: .day, value: 30, to: now)! let base64SecretKey = secret.data(using: .utf8)! let headers = ["typ" : NSString.init(string: AuthHeaders.HeaderType)] as [AnyHashable : Any] /* Claims notes: ID claim, this claim name must be the same as the value of the 'ID claim' field in your push notification profile in Dotdigital, the default value is 'sub', and the value of the claim must be a consitent unique value for the app user. 'aud' audience claim must be the same as the value of the 'Audience' field in your push notification profile in Dotdigital. 'iss' audience claim must be the same as the value of the 'Issuer' field in your push notification profile in Dotdigital. */ let claims = ["nonce" : NSString.init(string: nonce), "sub" : NSString.init(string: profileId), "iss" : NSString.init(string: issuer), "aud" : NSString.init(string: audience), "iat" : NSNumber(value: now.timeIntervalSince1970), "exp" : NSNumber(value: exp.timeIntervalSince1970)] as [AnyHashable : Any] let algorithm = JWTAlgorithmFactory.algorithm(byName: "HS256") let e = JWTBuilder.encodePayload(claims)! let h = e.headers(headers)! let s = h.secretData(base64SecretKey)! let b = s.algorithm(algorithm)! let token = b.encode return token! } } /* Note that this should preferably be generated by your backend, the app should only retreive the token through an HTTP call */
JWT provider: jsrassign 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).
function challengeHandler (options, answerAuthenticationChallenge) { // Header var oHeader = { alg: 'HS256', typ: 'JWT' }; // Payload var tNow = KJUR.jws.IntDate.get('now'); var tEnd = KJUR.jws.IntDate.get('now + 1day'); var oPayload = { // ID claim, this claim name must be the same as the value of the 'ID claim' field in your push notification profile in Dotdigital, // the default value is 'sub', and the value of the claim must be a consitent unique value for the app user. sub: "<Unique consitent app user id>", nonce: options.nonce, // 'aud' audience claim must be the same as the value of the 'Audience' field in your push notification profile in Dotdigital. aud: "<Audience>", // 'iss' audience claim must be the same as the value of the 'Issuer' field in your push notification profile in Dotdigital. iss: "<Issuer>", iat: tNow, exp: tEnd, }; var sHeader = JSON.stringify(oHeader); var sPayload = JSON.stringify(oPayload); //<Shared secret> string must be the same as the value of the 'Shared secret' field in your push notification profile in Dotdigital. var sJWT = KJUR.jws.JWS.sign("HS256", sHeader, sPayload, {utf8: "<Shared secret>"}); answerAuthenticationChallenge(sJWT); }
Updated 2 months ago
How To Create A Jwt Token In Java
Source: https://developer.dotdigital.com/docs/creating-a-json-web-token-new
Posted by: byrdcasent.blogspot.com
0 Response to "How To Create A Jwt Token In Java"
Post a Comment