-
Notifications
You must be signed in to change notification settings - Fork 40
[SDK-136] Add JWT Token generator #765
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: jwt/master
Are you sure you want to change the base?
Changes from all commits
e5a5d18
7d9011a
fe926aa
0c34d2e
6fa6fcb
1b4f196
a843b5d
d484c41
51441fb
12d0add
c4d86d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,9 @@ | |
| import android.net.Uri; | ||
| import android.os.Bundle; | ||
|
|
||
| import java.time.Duration; | ||
| import java.util.Date; | ||
|
|
||
| import androidx.annotation.NonNull; | ||
| import androidx.annotation.Nullable; | ||
| import com.facebook.react.bridge.Promise; | ||
|
|
@@ -37,6 +40,7 @@ | |
| import com.iterable.iterableapi.IterableLogger; | ||
| import com.iterable.iterableapi.IterableUrlHandler; | ||
| import com.iterable.iterableapi.RNIterableInternal; | ||
| import com.iterable.iterableapi.util.IterableJwtGenerator; | ||
|
|
||
| import org.json.JSONArray; | ||
| import org.json.JSONException; | ||
|
|
@@ -593,6 +597,28 @@ public void pauseAuthRetries(boolean pauseRetry) { | |
| IterableApi.getInstance().pauseAuthRetries(pauseRetry); | ||
| } | ||
|
|
||
| public void generateJwtToken(ReadableMap opts, Promise promise) { | ||
| try { | ||
| String secret = opts.getString("secret"); | ||
| long durationMs = (long) opts.getDouble("duration"); | ||
| String userId = opts.hasKey("userId") && !opts.isNull("userId") ? opts.getString("userId") : null; | ||
| String email = opts.hasKey("email") && !opts.isNull("email") ? opts.getString("email") : null; | ||
|
|
||
| // Validate that exactly one of userId or email is provided | ||
| if ((userId != null && email != null) || (userId == null && email == null)) { | ||
| promise.reject("E_INVALID_ARGS", "The token must include a userId or email, but not both.", (Throwable) null); | ||
| return; | ||
| } | ||
|
|
||
| // Use the Android SDK's Duration-based JWT generator | ||
| Duration duration = Duration.ofMillis(durationMs); | ||
| String token = IterableJwtGenerator.generateToken(secret, duration, email, userId); | ||
| promise.resolve(token); | ||
| } catch (Exception e) { | ||
| promise.reject("E_JWT_GENERATION_FAILED", "Failed to generate JWT: " + e.getMessage(), e); | ||
| } | ||
|
Comment on lines
+600
to
+619
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Comment on lines
+600
to
+619
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Comment on lines
+600
to
+619
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| } | ||
|
|
||
| @Override | ||
| public void onTokenRegistrationSuccessful(String authToken) { | ||
| IterableLogger.v(TAG, "authToken successfully set"); | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -23,7 +23,8 @@ _example app directory_. To do so, run the following: | |||||
|
|
||||||
| ```bash | ||||||
| cd ios | ||||||
| pod install | ||||||
| bundle install | ||||||
| bundle exec pod install | ||||||
| ``` | ||||||
|
|
||||||
| Once this is done, `cd` back into the _example app directory_: | ||||||
|
|
@@ -40,12 +41,15 @@ In it, you will find: | |||||
|
|
||||||
| ```shell | ||||||
| ITBL_API_KEY=replace_this_with_your_iterable_api_key | ||||||
| ITBL_JWT_SECRET=replace_this_with_your_jwt_secret | ||||||
| ITBL_ID=replace_this_with_your_user_id_or_email | ||||||
| ``` | ||||||
|
|
||||||
| Replace `replace_this_with_your_iterable_api_key` with your _mobile_ Iterable API key, | ||||||
| and replace `replace_this_with_your_user_id_or_email` with the email or user id | ||||||
| that you use to log into Iterable. | ||||||
| Replace `replace_this_with_your_iterable_api_key` with your **_mobile_ Iterable | ||||||
| API key**, replace `replace_this_with_your_jwt_secret` with your **JWT Secret** | ||||||
| (if you have a JWT-enabled API key) and replace | ||||||
| `replace_this_with_your_user_id_or_email` with the **email or user id** that you | ||||||
| use to log into Iterable. | ||||||
|
|
||||||
| Follow the steps below if you do not have a mobile Iterable API key. | ||||||
|
|
||||||
|
|
@@ -57,10 +61,9 @@ To add an API key, do the following: | |||||
| 4. Fill in the followsing fields: | ||||||
|
||||||
| 4. Fill in the followsing fields: | |
| 4. Fill in the following fields: |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -215,7 +215,8 @@ import React | |||||
| ITBError("Could not find message with id: \(messageId)") | ||||||
| return | ||||||
| } | ||||||
| IterableAPI.track(inAppOpen: message, location: InAppLocation.from(number: locationNumber as NSNumber)) | ||||||
| IterableAPI.track( | ||||||
| inAppOpen: message, location: InAppLocation.from(number: locationNumber as NSNumber)) | ||||||
| } | ||||||
|
|
||||||
| @objc(trackInAppClick:location:clickedUrl:) | ||||||
|
|
@@ -414,8 +415,10 @@ import React | |||||
| templateId: Double | ||||||
| ) { | ||||||
| ITBInfo() | ||||||
| let finalCampaignId: NSNumber? = (campaignId as NSNumber).intValue <= 0 ? nil : campaignId as NSNumber | ||||||
| let finalTemplateId: NSNumber? = (templateId as NSNumber).intValue <= 0 ? nil : templateId as NSNumber | ||||||
| let finalCampaignId: NSNumber? = | ||||||
| (campaignId as NSNumber).intValue <= 0 ? nil : campaignId as NSNumber | ||||||
| let finalTemplateId: NSNumber? = | ||||||
| (templateId as NSNumber).intValue <= 0 ? nil : templateId as NSNumber | ||||||
| IterableAPI.updateSubscriptions( | ||||||
| emailListIds, | ||||||
| unsubscribedChannelIds: unsubscribedChannelIds, | ||||||
|
|
@@ -480,7 +483,7 @@ import React | |||||
| @objc(passAlongAuthToken:) | ||||||
| public func passAlongAuthToken(authToken: String?) { | ||||||
| ITBInfo() | ||||||
| passedAuthToken = authToken | ||||||
| self.passedAuthToken = authToken | ||||||
| authHandlerSemaphore.signal() | ||||||
| } | ||||||
|
|
||||||
|
|
@@ -490,6 +493,62 @@ import React | |||||
| IterableAPI.pauseAuthRetries(pauseRetry) | ||||||
| } | ||||||
|
|
||||||
| @objc(generateJwtToken:resolver:rejecter:) | ||||||
| public func generateJwtToken( | ||||||
| _ opts: NSDictionary, | ||||||
| resolver: @escaping RCTPromiseResolveBlock, | ||||||
| rejecter: @escaping RCTPromiseRejectBlock | ||||||
| ) { | ||||||
| ITBInfo() | ||||||
|
|
||||||
| // Extract parameters | ||||||
| guard let secret = opts["secret"] as? String else { | ||||||
| rejecter("E_INVALID_ARGS", "secret is required", nil) | ||||||
| return | ||||||
| } | ||||||
|
|
||||||
| guard let durationMs = opts["duration"] as? Double else { | ||||||
| rejecter("E_INVALID_ARGS", "duration is required", nil) | ||||||
| return | ||||||
| } | ||||||
|
|
||||||
| let userId = opts["userId"] as? String | ||||||
| let email = opts["email"] as? String | ||||||
|
|
||||||
| // Validate that exactly one of userId or email is provided | ||||||
| if (userId != nil && email != nil) || (userId == nil && email == nil) { | ||||||
| rejecter("E_INVALID_ARGS", "The token must include a userId or email, but not both.", nil) | ||||||
| return | ||||||
| } | ||||||
|
|
||||||
| // Calculate iat and exp | ||||||
| let iat = Int(Date().timeIntervalSince1970) | ||||||
| let durationSeconds = Int(durationMs / 1000) | ||||||
| let exp = iat + durationSeconds | ||||||
|
|
||||||
| let token: String | ||||||
| if let userId = userId { | ||||||
| token = IterableTokenGenerator.generateJwtForUserId( | ||||||
| secret: secret, | ||||||
| iat: iat, | ||||||
| exp: exp, | ||||||
| userId: userId | ||||||
| ) | ||||||
| } else if let email = email { | ||||||
| token = IterableTokenGenerator.generateJwtForEial( | ||||||
|
||||||
| token = IterableTokenGenerator.generateJwtForEial( | |
| token = IterableTokenGenerator.generateJwtForEmail( |
Uh oh!
There was an error while loading. Please reload this page.