Skip to content

Commit 252093f

Browse files
authored
fix: migrate FCM channel authentication from ApiKey to ServiceToken based (#13826)
* fix: migrate FCM channel authentication from ApiKey to ServiceToken based * fix: explicitly set DefaultAuthenticationMethod
1 parent 33da5c7 commit 252093f

2 files changed

Lines changed: 26 additions & 25 deletions

File tree

packages/amplify-category-notifications/src/__tests__/channel-fcm.test.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ jest.mock('@aws-amplify/amplify-cli-core', () => {
1717
};
1818
});
1919

20-
const apiKey = 'ApiKey-abc123';
20+
const serviceJSONFilePath = '/my/service/account/jsonFile.json';
21+
const serviceAccountJson = '{ "valid": { "service": "accountJson"}}';
22+
jest.mock('fs-extra', () => ({
23+
readFile: () => Promise.resolve(serviceAccountJson),
24+
existsSync: () => true,
25+
}));
2126
jest.mock('@aws-amplify/amplify-prompts');
2227
const prompterMock = prompter as jest.Mocked<typeof prompter>;
2328

@@ -97,7 +102,7 @@ describe('channel-FCM', () => {
97102
test('configure', async () => {
98103
mockChannelEnabledOutput.Enabled = true;
99104
prompterMock.yesOrNo.mockResolvedValueOnce(true);
100-
prompterMock.input.mockResolvedValueOnce(apiKey);
105+
prompterMock.input.mockResolvedValueOnce(serviceJSONFilePath);
101106

102107
const mockContextObj = mockContext(mockChannelEnabledOutput, mockPinpointClient);
103108
await channelFCM.configure(mockContextObj).then(() => {
@@ -118,28 +123,22 @@ describe('channel-FCM', () => {
118123
});
119124

120125
test('enable', async () => {
121-
prompterMock.input.mockResolvedValueOnce(apiKey);
126+
prompterMock.input.mockResolvedValueOnce(serviceJSONFilePath);
122127
const mockContextObj = mockContext(mockChannelEnabledOutput, mockPinpointClient);
123128
const data = await channelFCM.enable(mockContextObj, 'successMessage');
124-
expect(mockPinpointClient.updateGcmChannel).toBeCalled();
125-
expect(data).toEqual(mockPinpointResponseData(true, ChannelAction.ENABLE));
126-
});
127-
128-
test('enable with newline', async () => {
129-
prompterMock.input.mockResolvedValueOnce(`${apiKey}\n`);
130-
const data = await channelFCM.enable(mockContext(mockChannelEnabledOutput, mockPinpointClient), 'successMessage');
131129
expect(mockPinpointClient.updateGcmChannel).toBeCalledWith({
132130
ApplicationId: undefined,
133131
GCMChannelRequest: {
134-
ApiKey: apiKey,
132+
ServiceJson: serviceAccountJson,
133+
DefaultAuthenticationMethod: 'TOKEN',
135134
Enabled: true,
136135
},
137136
});
138137
expect(data).toEqual(mockPinpointResponseData(true, ChannelAction.ENABLE));
139138
});
140139

141140
test('enable unsuccessful', async () => {
142-
prompterMock.input.mockResolvedValueOnce(apiKey);
141+
prompterMock.input.mockResolvedValueOnce(serviceJSONFilePath);
143142

144143
const context = mockContextReject(mockServiceOutput, mockPinpointClientReject);
145144
const errCert: AmplifyFault = await getError(async () => channelFCM.enable(context as unknown as $TSContext, 'successMessage'));

packages/amplify-category-notifications/src/channel-fcm.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { printer, prompter } from '@aws-amplify/amplify-prompts';
33
import ora from 'ora';
44
import { ChannelAction, ChannelConfigDeploymentType, IChannelAPIResponse } from './channel-types';
55
import { buildPinpointChannelResponseSuccess } from './pinpoint-helper';
6+
import { validateFilePath } from './validate-filepath';
7+
import fs from 'fs-extra';
68

79
const channelName = 'FCM';
810
const spinner = ora('');
@@ -42,19 +44,19 @@ export const enable = async (context: $TSContext, successMessage: string | undef
4244
if (context.exeInfo.pinpointInputParams?.[channelName]) {
4345
answers = validateInputParams(context.exeInfo.pinpointInputParams[channelName]);
4446
} else {
45-
let channelOutput: $TSAny = {};
46-
if (context.exeInfo.serviceMeta.output[channelName]) {
47-
channelOutput = context.exeInfo.serviceMeta.output[channelName];
48-
}
4947
answers = {
50-
ApiKey: await prompter.input('Server Key', { initial: channelOutput.ApiKey, transform: (input) => input.trim() }),
48+
ServiceJson: await fs.readFile(
49+
await prompter.input('The service account file path (.json): ', { validate: validateFilePath }),
50+
'utf8',
51+
),
5152
};
5253
}
5354

5455
const params = {
5556
ApplicationId: context.exeInfo.serviceMeta.output.Id,
5657
GCMChannelRequest: {
5758
...answers,
59+
DefaultAuthenticationMethod: 'TOKEN',
5860
Enabled: true,
5961
},
6062
};
@@ -78,10 +80,10 @@ export const enable = async (context: $TSContext, successMessage: string | undef
7880
};
7981

8082
const validateInputParams = (channelInput: $TSAny): $TSAny => {
81-
if (!channelInput.ApiKey) {
83+
if (!channelInput.ServiceJson) {
8284
throw new AmplifyError('UserInputError', {
83-
message: 'Server Key is missing for the FCM channel',
84-
resolution: 'Server Key for the FCM channel',
85+
message: 'ServiceJson is missing for the FCM channel',
86+
resolution: 'Provide the JSON from your Firebase service account json file',
8587
});
8688
}
8789
return channelInput;
@@ -97,18 +99,18 @@ export const disable = async (context: $TSContext): Promise<$TSAny> => {
9799
if (context.exeInfo.pinpointInputParams?.[channelName]) {
98100
answers = validateInputParams(context.exeInfo.pinpointInputParams[channelName]);
99101
} else {
100-
let channelOutput: $TSAny = {};
101-
if (context.exeInfo.serviceMeta.output[channelName]) {
102-
channelOutput = context.exeInfo.serviceMeta.output[channelName];
103-
}
104102
answers = {
105-
ApiKey: await prompter.input('Server Key', { initial: channelOutput.ApiKey, transform: (input) => input.trim() }),
103+
ServiceJson: await fs.readFile(
104+
await prompter.input('The service account file path (.json): ', { validate: validateFilePath }),
105+
'utf8',
106+
),
106107
};
107108
}
108109
const params = {
109110
ApplicationId: context.exeInfo.serviceMeta.output.Id,
110111
GCMChannelRequest: {
111112
...answers,
113+
DefaultAuthenticationMethod: 'TOKEN',
112114
Enabled: false,
113115
},
114116
};

0 commit comments

Comments
 (0)