Skip to content

Commit 280d897

Browse files
authored
feat: add a customProvider option to the sdk JwtBearerAuth class (#5105)
## Explanation This PR adds the possibility to use a `customProvider` for the `JwtBearerAuth` class. This is added both as a constructor option, and as a method to set the custom provider as a later point in time, using the `setCustomProvider` method. ## 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 --> ## Changelog <!-- If you're making any consumer-facing changes, list those changes here as if you were updating a changelog, using the template below as a guide. (CATEGORY is one of BREAKING, ADDED, CHANGED, DEPRECATED, REMOVED, or FIXED. For security-related issues, follow the Security Advisory process.) Please take care to name the exact pieces of the API you've added or changed (e.g. types, interfaces, functions, or methods). If there are any breaking changes, make sure to offer a solution for consumers to follow once they upgrade to the changes. Finally, if you're only making changes to development scripts or tests, you may replace the template below with "None". --> ### `@metamask/profile-sync-controller` - **ADDED**: `customProvider` option for the sdk `JwtBearerAuth` class ## Checklist - [ ] I've updated the test suite for new or updated code as appropriate - [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [ ] I've highlighted breaking changes using the "BREAKING" category above as appropriate - [ ] I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes
1 parent 0875256 commit 280d897

File tree

5 files changed

+78
-25
lines changed

5 files changed

+78
-25
lines changed

packages/profile-sync-controller/src/sdk/__fixtures__/test-utils.ts

+19
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import type { Eip1193Provider } from 'ethers';
2+
13
import { Env, Platform } from '../../shared/env';
24
import { JwtBearerAuth } from '../authentication';
35
import type {
46
AuthSigningOptions,
57
AuthStorageOptions,
68
} from '../authentication-jwt-bearer/types';
79
import { AuthType } from '../authentication-jwt-bearer/types';
10+
import { SNAP_ORIGIN } from '../utils/messaging-signing-snap-requests';
811

912
// Alias mocking variables with ANY to test runtime safety.
1013
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -42,13 +45,15 @@ const mockAuthOptions = () => {
4245
* @param mockPublicKey - provide the mock public key
4346
* @param authOptionsOverride - overrides
4447
* @param authOptionsOverride.signing - override auth signing
48+
* @param authOptionsOverride.customProvider - override custom provider
4549
* @returns Auth instance
4650
*/
4751
export function arrangeAuth(
4852
type: `${AuthType}`,
4953
mockPublicKey: string,
5054
authOptionsOverride?: {
5155
signing?: AuthSigningOptions;
56+
customProvider?: Eip1193Provider;
5257
},
5358
) {
5459
const authOptionsMock = mockAuthOptions();
@@ -67,6 +72,7 @@ export function arrangeAuth(
6772
type: AuthType.SRP,
6873
},
6974
{
75+
customProvider: authOptionsOverride?.customProvider,
7076
storage: {
7177
getLoginResponse: authOptionsMock.mockGetLoginResponse,
7278
setLoginResponse: authOptionsMock.mockSetLoginResponse,
@@ -103,3 +109,16 @@ export function arrangeAuth(
103109

104110
throw new Error('Unable to arrange auth mock for invalid auth type');
105111
}
112+
113+
/**
114+
* Mock utility - creates a mock provider
115+
* @returns mock provider
116+
*/
117+
export const arrangeMockProvider = () => {
118+
const mockRequest = jest.fn().mockResolvedValue({ [SNAP_ORIGIN]: {} });
119+
const mockProvider: Eip1193Provider = {
120+
request: mockRequest,
121+
};
122+
123+
return { mockProvider, mockRequest };
124+
};

packages/profile-sync-controller/src/sdk/authentication-jwt-bearer/flow-srp.ts

+25-8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { Eip1193Provider } from 'ethers';
2+
13
import { ValidationError } from '../errors';
24
import { getMetaMaskProviderEIP6963 } from '../utils/eip-6963-metamask-provider';
35
import {
@@ -32,37 +34,49 @@ const getDefaultEIP6963Provider = async () => {
3234
return provider;
3335
};
3436

35-
const defaultEIP6963SigningOptions: AuthSigningOptions = {
37+
const getDefaultEIP6963SigningOptions = (
38+
customProvider?: Eip1193Provider,
39+
): AuthSigningOptions => ({
3640
getIdentifier: async (): Promise<string> => {
37-
const provider = await getDefaultEIP6963Provider();
41+
const provider = customProvider ?? (await getDefaultEIP6963Provider());
3842
return await MESSAGE_SIGNING_SNAP.getPublicKey(provider);
3943
},
4044
signMessage: async (message: string): Promise<string> => {
41-
const provider = await getDefaultEIP6963Provider();
45+
const provider = customProvider ?? (await getDefaultEIP6963Provider());
4246
if (!message.startsWith('metamask:')) {
4347
throw new ValidationError('message must start with "metamask:"');
4448
}
4549
const formattedMessage = message as `metamask:${string}`;
4650
return await MESSAGE_SIGNING_SNAP.signMessage(provider, formattedMessage);
4751
},
48-
};
52+
});
4953

5054
export class SRPJwtBearerAuth implements IBaseAuth {
5155
#config: AuthConfig;
5256

5357
#options: Required<JwtBearerAuth_SRP_Options>;
5458

59+
#customProvider?: Eip1193Provider;
60+
5561
constructor(
5662
config: AuthConfig & { type: AuthType.SRP },
57-
options: JwtBearerAuth_SRP_Options,
63+
options: JwtBearerAuth_SRP_Options & { customProvider?: Eip1193Provider },
5864
) {
5965
this.#config = config;
66+
this.#customProvider = options.customProvider;
6067
this.#options = {
6168
storage: options.storage,
62-
signing: options.signing ?? defaultEIP6963SigningOptions,
69+
signing:
70+
options.signing ??
71+
getDefaultEIP6963SigningOptions(this.#customProvider),
6372
};
6473
}
6574

75+
setCustomProvider(provider: Eip1193Provider) {
76+
this.#customProvider = provider;
77+
this.#options.signing = getDefaultEIP6963SigningOptions(provider);
78+
}
79+
6680
async getAccessToken(): Promise<string> {
6781
const session = await this.#getAuthSession();
6882
if (session) {
@@ -92,7 +106,8 @@ export class SRPJwtBearerAuth implements IBaseAuth {
92106
}
93107

94108
async isSnapConnected(): Promise<boolean> {
95-
const provider = await getMetaMaskProviderEIP6963();
109+
const provider =
110+
this.#customProvider ?? (await getDefaultEIP6963Provider());
96111
if (!provider) {
97112
return false;
98113
}
@@ -102,7 +117,9 @@ export class SRPJwtBearerAuth implements IBaseAuth {
102117
}
103118

104119
async connectSnap(): Promise<string> {
105-
const provider = await getDefaultEIP6963Provider();
120+
const provider =
121+
this.#customProvider ?? (await getDefaultEIP6963Provider());
122+
106123
const res = await connectSnap(provider);
107124
return res;
108125
}

packages/profile-sync-controller/src/sdk/authentication.test.ts

+23-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
arrangeAuthAPIs,
66
} from './__fixtures__/mock-auth';
77
import type { MockVariable } from './__fixtures__/test-utils';
8-
import { arrangeAuth } from './__fixtures__/test-utils';
8+
import { arrangeAuth, arrangeMockProvider } from './__fixtures__/test-utils';
99
import { JwtBearerAuth } from './authentication';
1010
import type { LoginResponse, Pair } from './authentication-jwt-bearer/types';
1111
import {
@@ -143,6 +143,28 @@ describe('Authentication - constructor()', () => {
143143
);
144144
}).toThrow(UnsupportedAuthTypeError);
145145
});
146+
147+
it('supports using a custom provider as a constructor option', async () => {
148+
const { auth } = arrangeAuth('SRP', MOCK_SRP, {
149+
customProvider: arrangeMockProvider().mockProvider,
150+
});
151+
152+
await auth.connectSnap();
153+
const isSnapConnected = await auth.isSnapConnected();
154+
155+
expect(isSnapConnected).toBe(true);
156+
});
157+
158+
it('supports using a custom provider set at a later point in time', async () => {
159+
const { auth } = arrangeAuth('SRP', MOCK_SRP);
160+
161+
auth.setCustomProvider(arrangeMockProvider().mockProvider);
162+
163+
await auth.connectSnap();
164+
const isSnapConnected = await auth.isSnapConnected();
165+
166+
expect(isSnapConnected).toBe(true);
167+
});
146168
});
147169

148170
describe('Authentication - SRP Flow - getAccessToken() & getUserProfile()', () => {

packages/profile-sync-controller/src/sdk/authentication.ts

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { Eip1193Provider } from 'ethers';
2+
13
import type { Env } from '../shared/env';
24
import { SIWEJwtBearerAuth } from './authentication-jwt-bearer/flow-siwe';
35
import { SRPJwtBearerAuth } from './authentication-jwt-bearer/flow-srp';
@@ -44,6 +46,11 @@ export class JwtBearerAuth implements SIWEInterface, SRPInterface {
4446
throw new UnsupportedAuthTypeError('unsupported auth type');
4547
}
4648

49+
setCustomProvider(provider: Eip1193Provider) {
50+
this.#assertSRP(this.#type, this.#sdk);
51+
this.#sdk.setCustomProvider(provider);
52+
}
53+
4754
async getAccessToken(): Promise<string> {
4855
return await this.#sdk.getAccessToken();
4956
}

packages/profile-sync-controller/src/sdk/utils/messaging-signing-snap-requests.test.ts

+4-16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import type { Eip1193Provider } from 'ethers';
2-
3-
import type { MockVariable } from '../__fixtures__/test-utils';
1+
import {
2+
arrangeMockProvider,
3+
type MockVariable,
4+
} from '../__fixtures__/test-utils';
45
import type { Snap } from './messaging-signing-snap-requests';
56
import {
67
MESSAGE_SIGNING_SNAP,
@@ -83,16 +84,3 @@ describe('MESSAGE_SIGNING_SNAP.signMessage() tests', () => {
8384
expect(mockRequest).toHaveBeenCalled();
8485
});
8586
});
86-
87-
/**
88-
* Mock utility - creates a mock provider
89-
* @returns mock provider
90-
*/
91-
function arrangeMockProvider() {
92-
const mockRequest = jest.fn();
93-
const mockProvider: Eip1193Provider = {
94-
request: mockRequest,
95-
};
96-
97-
return { mockProvider, mockRequest };
98-
}

0 commit comments

Comments
 (0)