Skip to content

Commit a70f6d7

Browse files
feat(SDK): Implement setUserJWT API for iOS/Android, update Intercom iOS SDK to 18.2.0
1 parent ae2e1bf commit a70f6d7

File tree

6 files changed

+145
-6
lines changed

6 files changed

+145
-6
lines changed

__tests__/setUserJWT.test.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/**
2+
* Tests for setUserJWT functionality
3+
*/
4+
5+
const { NativeModules } = require('react-native');
6+
const Intercom = require('../src/index').default;
7+
8+
// Mock the native module
9+
jest.mock('react-native', () => ({
10+
NativeModules: {
11+
IntercomModule: {
12+
setUserJwt: jest.fn(),
13+
},
14+
IntercomEventEmitter: {
15+
UNREAD_COUNT_CHANGE_NOTIFICATION:
16+
'IntercomUnreadCountDidChangeNotification',
17+
WINDOW_DID_HIDE_NOTIFICATION: 'IntercomWindowDidHideNotification',
18+
WINDOW_DID_SHOW_NOTIFICATION: 'IntercomWindowDidShowNotification',
19+
},
20+
},
21+
NativeEventEmitter: jest.fn(),
22+
Platform: {
23+
OS: 'ios',
24+
select: jest.fn((config) => config.ios || config.default),
25+
},
26+
}));
27+
28+
describe('setUserJWT', () => {
29+
beforeEach(() => {
30+
jest.clearAllMocks();
31+
});
32+
33+
test('should call native setUserJwt method with correct JWT token', async () => {
34+
const mockJwt =
35+
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';
36+
37+
NativeModules.IntercomModule.setUserJwt.mockResolvedValue(true);
38+
39+
const result = await Intercom.setUserJwt(mockJwt);
40+
41+
expect(NativeModules.IntercomModule.setUserJwt).toHaveBeenCalledWith(
42+
mockJwt
43+
);
44+
expect(result).toBe(true);
45+
});
46+
47+
test('should handle empty JWT token', async () => {
48+
const emptyJwt = '';
49+
50+
NativeModules.IntercomModule.setUserJwt.mockResolvedValue(true);
51+
52+
const result = await Intercom.setUserJwt(emptyJwt);
53+
54+
expect(NativeModules.IntercomModule.setUserJwt).toHaveBeenCalledWith(
55+
emptyJwt
56+
);
57+
expect(result).toBe(true);
58+
});
59+
60+
test('should handle null JWT token', async () => {
61+
const nullJwt = null;
62+
63+
NativeModules.IntercomModule.setUserJwt.mockResolvedValue(true);
64+
65+
const result = await Intercom.setUserJwt(nullJwt);
66+
67+
expect(NativeModules.IntercomModule.setUserJwt).toHaveBeenCalledWith(
68+
nullJwt
69+
);
70+
expect(result).toBe(true);
71+
});
72+
73+
test('should handle rejection from native module', async () => {
74+
const mockJwt = 'invalid-jwt-token';
75+
const mockError = new Error('Invalid JWT token format');
76+
77+
NativeModules.IntercomModule.setUserJwt.mockRejectedValue(mockError);
78+
79+
await expect(Intercom.setUserJwt(mockJwt)).rejects.toThrow(
80+
'Invalid JWT token format'
81+
);
82+
expect(NativeModules.IntercomModule.setUserJwt).toHaveBeenCalledWith(
83+
mockJwt
84+
);
85+
});
86+
87+
test('should handle complex JWT token structure', async () => {
88+
const complexJwt =
89+
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIiwibmFtZSI6IkpvaG4gRG9lIiwiZW1haWwiOiJqb2huLmRvZUBleGFtcGxlLmNvbSIsImlhdCI6MTUxNjIzOTAyMiwiZXhwIjoxNTE2MjQyNjIyLCJhdWQiOiJpbnRlcmNvbS1hcHAiLCJpc3MiOiJteS1hcHAifQ.K1fOjxHcxtRYFfKZPEfUCzUXLp8sSpgPbMa8t0gE6A0';
90+
91+
NativeModules.IntercomModule.setUserJwt.mockResolvedValue(true);
92+
93+
const result = await Intercom.setUserJwt(complexJwt);
94+
95+
expect(NativeModules.IntercomModule.setUserJwt).toHaveBeenCalledWith(
96+
complexJwt
97+
);
98+
expect(result).toBe(true);
99+
});
100+
});

android/src/main/java/com/intercom/reactnative/IntercomErrorCodes.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ public class IntercomErrorCodes {
44
public static final String UNIDENTIFIED_REGISTRATION = "101";
55
public static final String IDENTIFIED_REGISTRATION = "102";
66
public static final String SET_USER_HASH = "103";
7-
public static final String UPDATE_USER_HASH = "104";
8-
public static final String LOG_EVENT_HASH = "105";
9-
public static final String LOGOUT = "106";
10-
public static final String SET_LOG_LEVEL = "107";
11-
public static final String GET_UNREAD_CONVERSATION = "108";
7+
public static final String SET_USER_JWT = "104";
8+
public static final String UPDATE_USER_HASH = "105";
9+
public static final String LOG_EVENT_HASH = "106";
10+
public static final String LOGOUT = "107";
11+
public static final String SET_LOG_LEVEL = "108";
12+
public static final String GET_UNREAD_CONVERSATION = "109";
1213
public static final String DISPLAY_MESSENGER = "201";
1314
public static final String DISPLAY_MESSENGER_COMPOSER = "202";
1415
public static final String DISPLAY_CONTENT = "203";

android/src/main/java/com/intercom/reactnative/IntercomModule.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,18 @@ public void setUserHash(String userHash, Promise promise) {
179179
}
180180
}
181181

182+
@ReactMethod
183+
public void setUserJwt(String userJwt, Promise promise) {
184+
try {
185+
Intercom.client().setUserJwt(userJwt);
186+
promise.resolve(true);
187+
} catch (Exception err) {
188+
Log.e(NAME, "setUserJwt error:");
189+
Log.e(NAME, err.toString());
190+
promise.reject(IntercomErrorCodes.SET_USER_JWT, err.toString());
191+
}
192+
}
193+
182194
@ReactMethod
183195
public void updateUser(ReadableMap params, Promise promise) {
184196
UserAttributes userAttributes = IntercomHelpers.buildUserAttributes(params);

intercom-react-native.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ Pod::Spec.new do |s|
2020
s.pod_target_xcconfig = { "DEFINES_MODULE" => "YES" }
2121

2222
s.dependency "React-Core"
23-
s.dependency "Intercom", '~> 18.6.1'
23+
s.dependency "Intercom", '~> 18.2.0'
2424
end

ios/IntercomModule.m

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ @implementation IntercomModule
1212
NSString *UNIDENTIFIED_REGISTRATION = @"101";
1313
NSString *IDENTIFIED_REGISTRATION = @"102";
1414
NSString *SET_USER_HASH = @"103";
15+
NSString *SET_USER_JWT = @"106";
1516
NSString *UPDATE_USER = @"104";
1617
NSString *LOG_EVENT = @"105";
1718
NSString *UNREAD_CONVERSATION_COUNT = @"107";
@@ -154,6 +155,17 @@ - (NSData *)dataFromHexString:(NSString *)string {
154155
}
155156
};
156157

158+
RCT_EXPORT_METHOD(setUserJwt:(NSString *)userJwt
159+
resolver:(RCTPromiseResolveBlock)resolve
160+
rejecter:(RCTPromiseRejectBlock)reject) {
161+
@try {
162+
[Intercom setUserJwt:userJwt];
163+
resolve(@(YES));
164+
} @catch (NSException *exception) {
165+
reject(SET_USER_JWT, @"Error in setUserJwt", [self exceptionToError:exception :SET_USER_JWT :@"setUserJwt"]);
166+
}
167+
};
168+
157169

158170
#pragma mark - Events
159171

src/index.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,19 @@ export type IntercomType = {
139139
*/
140140
setUserHash(hash: string): Promise<boolean>;
141141

142+
/**
143+
* Sets a JWT token for the user, necessary for using the Messenger
144+
* when Messenger Security is enforced. This is an improvement to Identity Verification.
145+
*
146+
* Secure your Messenger to make sure that bad actors can't impersonate your users,
147+
* see their conversation history or make unauthorised updates to data.
148+
*
149+
* This should be called before any user login takes place.
150+
*
151+
* @param jwt A JWT token signed with your app's secret key.
152+
*/
153+
setUserJwt(jwt: string): Promise<boolean>;
154+
142155
/**
143156
* Update a user in Intercom with data specified in {@link UserAttributes}.
144157
* Full details of the data data attributes that can be stored on a user can be found in {@link UserAttributes}.
@@ -303,6 +316,7 @@ const Intercom: IntercomType = {
303316
IntercomModule.loginUserWithUserAttributes(userAttributes),
304317
logout: () => IntercomModule.logout(),
305318
setUserHash: (hash) => IntercomModule.setUserHash(hash),
319+
setUserJwt: (jwt) => IntercomModule.setUserJwt(jwt),
306320
updateUser: (userAttributes) => IntercomModule.updateUser(userAttributes),
307321
isUserLoggedIn: () => IntercomModule.isUserLoggedIn(),
308322
fetchLoggedInUserAttributes: () =>

0 commit comments

Comments
 (0)