Skip to content

Commit f0ff3f8

Browse files
committed
Merge branch 'jwt/master' into loren/embedded/master
2 parents 0e68107 + 8ae3889 commit f0ff3f8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+3171
-425
lines changed

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,5 @@ module.exports = {
4848
},
4949
},
5050
],
51+
ignorePatterns: ['coverage/**/*', 'lib/**/*', 'docs/**/*'],
5152
};

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ ios/generated
8585
android/generated
8686

8787
# Iterable
88+
.env.local
8889
.env
8990
.xcode.env.local
9091
coverage/

CHANGELOG.md

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,50 @@
1-
## 2.1.0-beta.1
1+
## 2.2.0-alpha.1
22

3-
## Fixes
4-
- Add Temporary fix for circular paths, which break expo ([9c09743](https://github.com/Iterable/react-native-sdk/commit/9c09743))
3+
### Updates
4+
* [SDK-149] Added logout functionality
5+
6+
### Fixes
7+
* [SDK-151] Fixed "cannot read property authtoken of undefined" error
8+
9+
10+
## 2.2.0-alpha.0
11+
12+
### Updates
13+
- Updated Android SDK version to [3.6.2](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.6.2)
14+
- Updated iOS SDK version to [6.6.3](https://github.com/Iterable/swift-sdk/releases/tag/6.6.3)
15+
- Added JWT Capabilities:
16+
- Added `Iterable.authhManager`, which manages the authentication flow
17+
- Added `IterableRetryBackoff` and `IterableAuthFailureReason` enums
18+
- Added `onJwtError` and `retryPolicy` for control over JWT flow
19+
- Moved all native calls to `IterableApi.ts`
20+
- Added JWT example to our example app
521

6-
## 2.1.0-beta.0
22+
### Fixes
23+
- Created a standalone `IterableLogger` to avoid circular dependencies
724

25+
## 2.1.0
826
### Updates
27+
* SDK is now compatible with both New Architecture and Legacy Architecture. Fix
28+
for #691, #602, #563.
29+
30+
### Fixes
31+
- Dependencies update
932
- Update SDK so that it has full support for [React Native New Architecture](https://reactnative.dev/architecture/landing-page)
33+
- Add Temporary fix for circular paths, which break expo ([9c09743](https://github.com/Iterable/react-native-sdk/commit/9c09743))
1034

1135
### Chores
1236
- Update dependencies for React Navigation and related packages ([95053bb](https://github.com/Iterable/react-native-sdk/commit/95053bb))
1337

38+
## 2.0.4
39+
40+
### Updates
41+
- Added API documentation via Netlify([1087275](https://github.com/Iterable/react-native-sdk/commit/1087275))
42+
- Removed dependency on `react-native-vector-icons`, per issues
43+
[#513](https://github.com/Iterable/react-native-sdk/issues/513),
44+
[#683](https://github.com/Iterable/react-native-sdk/issues/683) and
45+
[#675](https://github.com/Iterable/react-native-sdk/issues/675)
46+
([6ece6e0](https://github.com/Iterable/react-native-sdk/commit/6ece6e0))
47+
- Updated dependencies
1448

1549
## 2.0.3
1650

Iterable-React-Native-SDK.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Pod::Spec.new do |s|
1717
s.private_header_files = "ios/**/*.h"
1818

1919
# Load Iterables iOS SDK as a dependency
20-
s.dependency "Iterable-iOS-SDK", "6.6.1"
20+
s.dependency "Iterable-iOS-SDK", "6.6.3"
2121

2222
# Basic Swift support
2323
s.pod_target_xcconfig = {

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ Iterable's React Native SDK relies on:
4444
_UI Components require additional peer dependencies_
4545
- [React Navigation 6+](https://github.com/react-navigation/react-navigation)
4646
- [React Native Safe Area Context 4+](https://github.com/th3rdwave/react-native-safe-area-context)
47-
- [React Native Vector Icons 10+](https://github.com/oblador/react-native-vector-icons)
4847
- [React Native WebView 13+](https://github.com/react-native-webview/react-native-webview)
4948

5049
- **iOS**
@@ -120,13 +119,13 @@ For quick reference, the following table lists the versions of the [Android SDK]
120119
121120
| RN SDK Version | Android SDK Version | iOS SDK Version |
122121
| --------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | --------------- |
123-
| [2.1.0-beta.0](https://www.npmjs.com/package/@iterable/react-native-sdk/v/2.1.0-beta.0) | [3.5.2](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.5.2) | [6.5.4](https://github.com/Iterable/swift-sdk/releases/tag/6.5.4)
122+
| [2.2.0](https://www.npmjs.com/package/@iterable/react-native-sdk/v/2.2.0) | [3.6.2](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.6.2) | [6.6.3](https://github.com/Iterable/swift-sdk/releases/tag/6.6.3)
123+
| [2.1.0](https://www.npmjs.com/package/@iterable/react-native-sdk/v/2.1.0) | [3.5.2](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.5.2) | [6.5.4](https://github.com/Iterable/swift-sdk/releases/tag/6.5.4)
124+
| [2.0.4](https://www.npmjs.com/package/@iterable/react-native-sdk/v/2.0.4) | [3.5.2](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.5.2) | [6.5.4](https://github.com/Iterable/swift-sdk/releases/tag/6.5.4)
124125
| [2.0.3](https://www.npmjs.com/package/@iterable/react-native-sdk/v/2.0.3) | [3.5.2](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.5.2) | [6.5.4](https://github.com/Iterable/swift-sdk/releases/tag/6.5.4)
125126
| [2.0.2](https://www.npmjs.com/package/@iterable/react-native-sdk/v/2.0.2) | [3.5.2](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.5.2) | [6.5.4](https://github.com/Iterable/swift-sdk/releases/tag/6.5.4)
126127
| [2.0.1](https://www.npmjs.com/package/@iterable/react-native-sdk/v/2.0.1) | [3.5.2](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.5.2) | [6.5.4](https://github.com/Iterable/swift-sdk/releases/tag/6.5.4)
127128
| [2.0.0](https://www.npmjs.com/package/@iterable/react-native-sdk/v/2.0.0) | [3.5.2](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.5.2) | [6.5.4](https://github.com/Iterable/swift-sdk/releases/tag/6.5.4)
128-
| [2.0.0-beta.1](https://www.npmjs.com/package/@iterable/react-native-sdk/v/2.0.0-beta.1) | [3.5.2](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.5.2) | [6.5.4](https://github.com/Iterable/swift-sdk/releases/tag/6.5.4)
129-
| [2.0.0-beta](https://www.npmjs.com/package/@iterable/react-native-sdk/v/2.0.0-beta) | [3.5.2](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.5.2) | [6.5.4](https://github.com/Iterable/swift-sdk/releases/tag/6.5.4)
130129
| [1.3.21](https://www.npmjs.com/package/@iterable/react-native-sdk/v/1.3.20) | [3.5.2](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.5.2) | [6.5.4](https://github.com/Iterable/swift-sdk/releases/tag/6.5.4)
131130
| [1.3.20](https://www.npmjs.com/package/@iterable/react-native-sdk/v/1.3.20) | [3.5.2](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.5.2) | [6.5.4](https://github.com/Iterable/swift-sdk/releases/tag/6.5.4)
132131
| [1.3.19](https://www.npmjs.com/package/@iterable/react-native-sdk/v/1.3.19) | [3.5.2](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.5.2) | [6.5.3](https://github.com/Iterable/swift-sdk/releases/tag/6.5.3)

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def kotlin_version = getExtOrDefault("kotlinVersion")
105105
dependencies {
106106
implementation "com.facebook.react:react-android"
107107
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
108-
api "com.iterable:iterableapi:3.6.1"
108+
api "com.iterable:iterableapi:3.6.2"
109109
// api project(":iterableapi") // links to local android SDK repo rather than by release
110110
}
111111

example/.env.example

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,19 @@
99
# 4. Fill in the following fields:
1010
# - Name: A descriptive name for the API key
1111
# - Type: Mobile
12-
# - JWT authentication: Leave **unchecked** (IMPORTANT)
12+
# - JWT authentication: Whether or not you want to use JWT
1313
# 5. Click "Create API Key"
14-
# 6. Copy the generated API key
15-
# 7. Replace the placeholder text next to `ITBL_API_KEY=` with the copied API key
14+
# 6. Copy the generated API key and replace the placeholder text next to
15+
# `ITBL_API_KEY=` with the copied API key
16+
# 7. If you chose to enable JWT authentication, copy the JWT secret and and
17+
# replace the placeholder text next to `ITBL_JWT_SECRET=` with the copied
18+
# JWT secret
1619
ITBL_API_KEY=replace_this_with_your_iterable_api_key
20+
# Your JWT Secret, created when making your API key (see above)
21+
ITBL_JWT_SECRET=replace_this_with_your_jwt_secret
22+
# Is your api token JWT Enabled?
23+
# Must be set to 'true' to enable JWT authentication
24+
ITBL_IS_JWT_ENABLED=true
1725

1826
# Your Iterable user ID or email address
19-
ITBL_ID=replace_this_with_your_user_id_or_email
27+
ITBL_ID=replace_this_with_your_user_id_or_email

example/README.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ _example app directory_. To do so, run the following:
2323

2424
```bash
2525
cd ios
26-
pod install
26+
bundle install
27+
bundle exec pod install
2728
```
2829

2930
Once this is done, `cd` back into the _example app directory_:
@@ -40,12 +41,18 @@ In it, you will find:
4041

4142
```shell
4243
ITBL_API_KEY=replace_this_with_your_iterable_api_key
44+
ITBL_JWT_SECRET=replace_this_with_your_jwt_secret
45+
ITBL_IS_JWT_ENABLED=true
4346
ITBL_ID=replace_this_with_your_user_id_or_email
4447
```
4548

46-
Replace `replace_this_with_your_iterable_api_key` with your _mobile_ Iterable API key,
47-
and replace `replace_this_with_your_user_id_or_email` with the email or user id
48-
that you use to log into Iterable.
49+
- Replace `replace_this_with_your_iterable_api_key` with your **_mobile_
50+
Iterable API key**
51+
- Replace `replace_this_with_your_jwt_secret` with your **JWT Secret** (if you
52+
have a JWT-enabled API key)
53+
- Set `ITBL_IS_JWT_ENABLED` to true if you have a JWT-enabled key, and false if you do not.
54+
- Replace `replace_this_with_your_user_id_or_email` with the **email or user
55+
id** that you use to log into Iterable.
4956

5057
Follow the steps below if you do not have a mobile Iterable API key.
5158

@@ -54,12 +61,12 @@ To add an API key, do the following:
5461
1. Sign into your Iterable account
5562
2. Go to [Integrations > API Keys](https://app.iterable.com/settings/apiKeys)
5663
3. Click "New API Key" in the top right corner
57-
4. Fill in the followsing fields:
64+
4. Fill in the following fields:
5865
- Name: A descriptive name for the API key
5966
- Type: Mobile
60-
- JWT authentication: Leave **unchecked** (IMPORTANT)
67+
- JWT authentication: Check to enable JWT authentication. If enabled, will need to create a [JWT generator](https://support.iterable.com/hc/en-us/articles/360050801231-JWT-Enabled-API-Keys#sample-python-code-for-jwt-generation) to generate the JWT token.
6168
5. Click "Create API Key"
62-
6. Copy the generated API key
69+
6. Copy the generated API key and JWT secret into your _.env_ file
6370

6471

6572
## Step 3: Start the Metro Server

example/android/app/build.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,5 +117,3 @@ dependencies {
117117
implementation jscFlavor
118118
}
119119
}
120-
121-
apply from: file("../../node_modules/react-native-vector-icons/fonts.gradle")
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package com.iterable;
2+
3+
import javax.crypto.Mac;
4+
import javax.crypto.spec.SecretKeySpec;
5+
import java.nio.charset.StandardCharsets;
6+
import java.time.Duration;
7+
import java.util.Base64;
8+
import java.util.Base64.Encoder;
9+
10+
/**
11+
* Utility class to generate JWTs for use with the Iterable API
12+
*
13+
* @author engineering@iterable.com
14+
*/
15+
public class IterableJwtGenerator {
16+
static Encoder encoder = Base64.getUrlEncoder().withoutPadding();
17+
18+
private static final String algorithm = "HmacSHA256";
19+
20+
// Iterable enforces a 1-year maximum token lifetime
21+
private static final Duration maxTokenLifetime = Duration.ofDays(365);
22+
23+
private static long millisToSeconds(long millis) {
24+
return millis / 1000;
25+
}
26+
27+
private static final String encodedHeader = encoder.encodeToString(
28+
"{\"alg\":\"HS256\",\"typ\":\"JWT\"}".getBytes(StandardCharsets.UTF_8)
29+
);
30+
31+
/**
32+
* Generates a JWT from the provided secret, header, and payload. Does not
33+
* validate the header or payload.
34+
*
35+
* @param secret Your organization's shared secret with Iterable
36+
* @param payload The JSON payload
37+
*
38+
* @return a signed JWT
39+
*/
40+
public static String generateToken(String secret, String payload) {
41+
try {
42+
String encodedPayload = encoder.encodeToString(
43+
payload.getBytes(StandardCharsets.UTF_8)
44+
);
45+
String encodedHeaderAndPayload = encodedHeader + "." + encodedPayload;
46+
47+
// HMAC setup
48+
Mac hmac = Mac.getInstance(algorithm);
49+
SecretKeySpec keySpec = new SecretKeySpec(
50+
secret.getBytes(StandardCharsets.UTF_8), algorithm
51+
);
52+
hmac.init(keySpec);
53+
54+
String signature = encoder.encodeToString(
55+
hmac.doFinal(
56+
encodedHeaderAndPayload.getBytes(StandardCharsets.UTF_8)
57+
)
58+
);
59+
60+
return encodedHeaderAndPayload + "." + signature;
61+
62+
} catch (Exception e) {
63+
throw new RuntimeException(e.getMessage());
64+
}
65+
}
66+
67+
/**
68+
* Generates a JWT (issued now, expires after the provided duration).
69+
*
70+
* @param secret Your organization's shared secret with Iterable.
71+
* @param duration The token's expiration time. Up to one year.
72+
* @param email The email to included in the token, or null.
73+
* @param userId The userId to include in the token, or null.
74+
*
75+
* @return A JWT string
76+
*/
77+
public static String generateToken(
78+
String secret, Duration duration, String email, String userId) {
79+
80+
if (duration.compareTo(maxTokenLifetime) > 0)
81+
throw new IllegalArgumentException(
82+
"Duration must be one year or less."
83+
);
84+
85+
if ((userId != null && email != null) || (userId == null && email == null))
86+
throw new IllegalArgumentException(
87+
"The token must include a userId or email, but not both."
88+
);
89+
90+
long now = millisToSeconds(System.currentTimeMillis());
91+
92+
String payload;
93+
if (userId != null)
94+
payload = String.format(
95+
"{ \"userId\": \"%s\", \"iat\": %d, \"exp\": %d }",
96+
userId, now, now + millisToSeconds(duration.toMillis())
97+
);
98+
else
99+
payload = String.format(
100+
"{ \"email\": \"%s\", \"iat\": %d, \"exp\": %d }",
101+
email, now, now + millisToSeconds(duration.toMillis())
102+
);
103+
104+
return generateToken(secret, payload);
105+
}
106+
}

0 commit comments

Comments
 (0)