Skip to content

Commit 7a9e620

Browse files
feat: SubscriptionController: trigger token refresh (#6374)
## Explanation Add a "triggerAuthTokenRefresh" method to the SubscriptionController, which allows to trigger a refresh of the access token, for example, after the subscription status has changed. <!-- Thanks for your contribution! Take a moment to answer these questions so that reviewers have the information they need to properly understand your changes: * What is the current state of things and why does it need to change? * What is the solution your changes offer and how does it work? * Are there any changes whose purpose might not obvious to those unfamiliar with the domain? * If your primary goal was to update one package but you found you had to update another one along the way, why did you do so? * If you had to upgrade a dependency, why did you do so? --> ## References <!-- Are there any issues that this pull request is tied to? Are there other links that reviewers should consult to understand these changes better? Are there client or consumer pull requests to adopt any breaking changes? For example: * Fixes #12345 * Related to #67890 --> ## Checklist - [x] I've updated the test suite for new or updated code as appropriate - [x] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [x] I've communicated my changes to consumers by [updating changelogs for packages I've changed](https://github.com/MetaMask/core/tree/main/docs/contributing.md#updating-changelogs), highlighting breaking changes as necessary - [ ] I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes
1 parent 640c2e4 commit 7a9e620

File tree

3 files changed

+46
-17
lines changed

3 files changed

+46
-17
lines changed

packages/subscription-controller/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
- `cancelSubscription`: Cancel user active subscription.
1515
- `startShieldSubscriptionWithCard`: start shield subscription via card (with trial option) ([#6300](https://github.com/MetaMask/core/pull/6300))
1616
- Add `getPricing` method ([#6356](https://github.com/MetaMask/core/pull/6356))
17+
- Added `triggerAccessTokenRefresh` to trigger an access token refresh ([#6374](https://github.com/MetaMask/core/pull/6374))
1718

1819
[Unreleased]: https://github.com/MetaMask/core/

packages/subscription-controller/src/SubscriptionController.test.ts

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,10 @@ function createCustomSubscriptionMessenger(props?: {
6060
AllowedEvents['type']
6161
>({
6262
name: controllerName,
63-
allowedActions: ['AuthenticationController:getBearerToken'],
63+
allowedActions: [
64+
'AuthenticationController:getBearerToken',
65+
'AuthenticationController:performSignOut',
66+
],
6467
allowedEvents: props?.overrideEvents ?? [
6568
'AuthenticationController:stateChange',
6669
],
@@ -80,31 +83,26 @@ function createCustomSubscriptionMessenger(props?: {
8083
* @param overrideMessengers.messenger - messenger to override
8184
* @returns series of mocks to actions that can be called
8285
*/
83-
function mockSubscriptionMessenger(overrideMessengers?: {
86+
function createMockSubscriptionMessenger(overrideMessengers?: {
8487
baseMessenger: Messenger<AllowedActions, AllowedEvents>;
8588
messenger: SubscriptionControllerMessenger;
8689
}) {
8790
const { baseMessenger, messenger } =
8891
overrideMessengers ?? createCustomSubscriptionMessenger();
8992

93+
const mockPerformSignOut = jest.fn();
94+
baseMessenger.registerActionHandler(
95+
'AuthenticationController:performSignOut',
96+
mockPerformSignOut,
97+
);
98+
9099
return {
91100
baseMessenger,
92101
messenger,
102+
mockPerformSignOut,
93103
};
94104
}
95105

96-
/**
97-
* Creates a mock subscription messenger for testing.
98-
*
99-
* @returns The mock messenger and related mocks.
100-
*/
101-
function createMockSubscriptionMessenger(): {
102-
messenger: SubscriptionControllerMessenger;
103-
baseMessenger: Messenger<AllowedActions, AllowedEvents>;
104-
} {
105-
return mockSubscriptionMessenger();
106-
}
107-
108106
/**
109107
* Creates a mock subscription service for testing.
110108
*
@@ -140,6 +138,7 @@ type WithControllerCallback<ReturnValue> = (params: {
140138
initialState: SubscriptionControllerState;
141139
messenger: SubscriptionControllerMessenger;
142140
mockService: ReturnType<typeof createMockSubscriptionService>['mockService'];
141+
mockPerformSignOut: jest.Mock;
143142
}) => Promise<ReturnValue> | ReturnValue;
144143

145144
type WithControllerOptions = Partial<SubscriptionControllerOptions>;
@@ -158,7 +157,7 @@ async function withController<ReturnValue>(
158157
...args: WithControllerArgs<ReturnValue>
159158
) {
160159
const [{ ...rest }, fn] = args.length === 2 ? args : [{}, args[0]];
161-
const { messenger } = createMockSubscriptionMessenger();
160+
const { messenger, mockPerformSignOut } = createMockSubscriptionMessenger();
162161
const { mockService } = createMockSubscriptionService();
163162

164163
const controller = new SubscriptionController({
@@ -172,6 +171,7 @@ async function withController<ReturnValue>(
172171
initialState: controller.state,
173172
messenger,
174173
mockService,
174+
mockPerformSignOut,
175175
});
176176
}
177177

@@ -546,4 +546,14 @@ describe('SubscriptionController', () => {
546546
});
547547
});
548548
});
549+
550+
describe('triggerAuthTokenRefresh', () => {
551+
it('should trigger auth token refresh', async () => {
552+
await withController(async ({ controller, mockPerformSignOut }) => {
553+
controller.triggerAccessTokenRefresh();
554+
555+
expect(mockPerformSignOut).toHaveBeenCalledWith();
556+
});
557+
});
558+
});
549559
});

packages/subscription-controller/src/SubscriptionController.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ export type SubscriptionControllerActions =
5454
| SubscriptionControllerGetStateAction;
5555

5656
export type AllowedActions =
57-
AuthenticationController.AuthenticationControllerGetBearerToken;
57+
| AuthenticationController.AuthenticationControllerGetBearerToken
58+
| AuthenticationController.AuthenticationControllerPerformSignOut;
5859

5960
// Events
6061
export type SubscriptionControllerStateChangeEvent = ControllerStateChangeEvent<
@@ -214,12 +215,19 @@ export class SubscriptionController extends BaseController<
214215
: subscription,
215216
);
216217
});
218+
219+
this.triggerAccessTokenRefresh();
217220
}
218221

219222
async startShieldSubscriptionWithCard(request: StartSubscriptionRequest) {
220223
this.#assertIsUserNotSubscribed({ products: request.products });
221224

222-
return await this.#subscriptionService.startSubscriptionWithCard(request);
225+
const response =
226+
await this.#subscriptionService.startSubscriptionWithCard(request);
227+
228+
this.triggerAccessTokenRefresh();
229+
230+
return response;
223231
}
224232

225233
#assertIsUserNotSubscribed({ products }: { products: ProductType[] }) {
@@ -232,6 +240,16 @@ export class SubscriptionController extends BaseController<
232240
}
233241
}
234242

243+
/**
244+
* Triggers an access token refresh.
245+
*/
246+
triggerAccessTokenRefresh() {
247+
// We perform a sign out to clear the access token from the authentication
248+
// controller. Next time the access token is requested, a new access token
249+
// will be fetched.
250+
this.messagingSystem.call('AuthenticationController:performSignOut');
251+
}
252+
235253
#assertIsUserSubscribed(request: { subscriptionId: string }) {
236254
if (
237255
!this.state.subscriptions.find(

0 commit comments

Comments
 (0)