Skip to content

Commit adc7b1b

Browse files
authored
fix (edge)!: Drop support for v1.0 API authentication (#32)
BREAKING CHANGE: Drop support for v1.0 edge authentication.
1 parent 2a0a53e commit adc7b1b

File tree

8 files changed

+51
-179
lines changed

8 files changed

+51
-179
lines changed

.github/workflows/validate.yml

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
name: Validate
2-
on: [push, workflow_call, pull_request]
2+
on:
3+
workflow_dispatch:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
38

49
jobs:
5-
verify:
6-
name: Verify Code
10+
checks:
11+
name: Checks
712
runs-on: ubuntu-22.04
813
steps:
914
- uses: actions/checkout@v4
@@ -18,15 +23,14 @@ jobs:
1823
- run: pnpm test
1924
- run: node bin/publish-extension.cjs --help
2025

21-
e2e-test:
22-
name: E2E Publish Test
26+
e2e-tests:
27+
name: E2E Tests
2328
runs-on: ubuntu-22.04
2429
# If PR is from a fork, secrets aren't available, so skip this job.
2530
if: github.event.pull_request.head.repo.fork != true
2631
steps:
2732
- uses: actions/checkout@v4
2833
- uses: pnpm/action-setup@v4
29-
3034
- uses: actions/setup-node@v4
3135
with:
3236
node-version: 20
@@ -45,29 +49,6 @@ jobs:
4549
FIREFOX_JWT_SECRET: ${{ secrets.TEST_FIREFOX_JWT_SECRET }}
4650
FIREFOX_CHANNEL: unlisted
4751
EDGE_PRODUCT_ID: ${{ secrets.TEST_EDGE_PRODUCT_ID }}
48-
EDGE_API_VERSION: '1.1'
49-
EDGE_CLIENT_ID: ${{ secrets.TEST_EDGE_CLIENT_ID_1_1 }}
52+
EDGE_CLIENT_ID: ${{ secrets.TEST_EDGE_CLIENT_ID }}
5053
EDGE_API_KEY: ${{ secrets.TEST_EDGE_API_KEY }}
5154
EDGE_SKIP_SUBMIT_REVIEW: 'true'
52-
53-
e2e-test-edge-1_0:
54-
name: E2E Publish Test (Edge v1.0)
55-
runs-on: ubuntu-22.04
56-
# If PR is from a fork, secrets aren't available, so skip this job.
57-
if: github.event.pull_request.head.repo.fork != true
58-
steps:
59-
- uses: actions/checkout@v4
60-
- uses: pnpm/action-setup@v4
61-
62-
- uses: actions/setup-node@v4
63-
with:
64-
node-version: 20
65-
cache: pnpm
66-
- run: pnpm install
67-
- run: ./scripts/dev.sh edge
68-
env:
69-
EDGE_PRODUCT_ID: ${{ secrets.TEST_EDGE_PRODUCT_ID }}
70-
EDGE_CLIENT_ID: ${{ secrets.TEST_EDGE_CLIENT_ID_1_0 }}
71-
EDGE_CLIENT_SECRET: ${{ secrets.TEST_EDGE_CLIENT_SECRET }}
72-
EDGE_ACCESS_TOKEN_URL: ${{ secrets.TEST_EDGE_ACCESS_TOKEN_URL }}
73-
EDGE_SKIP_SUBMIT_REVIEW: 'true'

src/cli.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,19 @@ cli.option(
8585
);
8686
cli.option(
8787
'--edge-api-version [edgeApiVersion]',
88-
'API version (1.0 or 1.1) to use',
88+
'API version (1.0 or 1.1) to use (DEPRECATED: 1.0 is no longer available, so 1.1 is always used)',
8989
);
9090
cli.option(
9191
'--edge-api-key [edgeApiKey]',
9292
'API key used for authorizing requests to Microsofts addon API v1.1',
9393
);
9494
cli.option(
9595
'--edge-client-secret [edgeClientSecret]',
96-
'Client secret used for authorizing requests to Microsofts addon API v1.0',
96+
'DEPRECATED: Client secret used for authorizing requests to Microsofts addon API v1.0 (no longer available)',
9797
);
9898
cli.option(
9999
'--edge-access-token-url [edgeAccessTokenUrl]',
100-
'Access token URL used for authorizing requests to Microsofts addon API v1.0',
100+
'DEPRECATED: Access token URL used for authorizing requests to Microsofts addon API v1.0 (no longer available)',
101101
);
102102
cli.option(
103103
'--edge-skip-submit-review',
@@ -130,7 +130,6 @@ function configFromFlags(flags: any): InlineConfig {
130130
zip: flags.edgeZip,
131131
productId: flags.edgeProductId,
132132
clientId: flags.edgeClientId,
133-
apiVersion: flags.edgeApiVersion,
134133
apiKey: flags.edgeApiKey,
135134
clientSecret: flags.edgeClientSecret,
136135
accessTokenUrl: flags.edgeAccessTokenUrl,

src/config.test.ts

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ describe('resolveConfig', () => {
4444
productId: 'productId',
4545
clientId: 'clientId',
4646
apiKey: 'apiKey',
47-
apiVersion: '1.1',
47+
accessTokenUrl: 'accessTokenUrl',
48+
clientSecret: 'clientSecret',
4849
skipSubmitReview: true,
4950
zip: 'zip',
5051
},
@@ -85,7 +86,8 @@ describe('resolveConfig', () => {
8586
process.env.EDGE_PRODUCT_ID = 'EDGE_PRODUCT_ID';
8687
process.env.EDGE_CLIENT_ID = 'EDGE_CLIENT_ID';
8788
process.env.EDGE_API_KEY = 'EDGE_API_KEY';
88-
process.env.EDGE_API_VERSION = '1.1';
89+
process.env.EDGE_CLIENT_SECRET = 'EDGE_CLIENT_SECRET';
90+
process.env.EDGE_ACCESS_TOKEN_URL = 'EDGE_ACCESS_TOKEN_URL';
8991
const edgeSkipSubmitReview = true;
9092
process.env.EDGE_SKIP_SUBMIT_REVIEW = String(edgeSkipSubmitReview);
9193

@@ -115,37 +117,8 @@ describe('resolveConfig', () => {
115117
productId: process.env.EDGE_PRODUCT_ID,
116118
clientId: process.env.EDGE_CLIENT_ID,
117119
apiKey: process.env.EDGE_API_KEY,
118-
apiVersion: process.env.EDGE_API_VERSION,
119-
skipSubmitReview: edgeSkipSubmitReview,
120-
},
121-
};
122-
123-
const actual = resolveConfig({});
124-
expect(actual).toEqual(expected);
125-
});
126-
127-
it('should support deprecated Edge API config', () => {
128-
const dryRun = true;
129-
process.env.DRY_RUN = String(dryRun);
130-
131-
process.env.EDGE_ZIP = 'EDGE_ZIP';
132-
process.env.EDGE_PRODUCT_ID = 'EDGE_PRODUCT_ID';
133-
process.env.EDGE_CLIENT_ID = 'EDGE_CLIENT_ID';
134-
process.env.EDGE_CLIENT_SECRET = 'EDGE_CLIENT_SECRET';
135-
process.env.EDGE_ACCESS_TOKEN_URL = 'EDGE_ACCESS_TOKEN_URL';
136-
// process.env.EDGE_API_VERSION = '1.0'; // Not set, should default to 1.0
137-
const edgeSkipSubmitReview = true;
138-
process.env.EDGE_SKIP_SUBMIT_REVIEW = String(edgeSkipSubmitReview);
139-
140-
const expected: InternalConfig = {
141-
dryRun,
142-
edge: {
143-
zip: process.env.EDGE_ZIP,
144-
productId: process.env.EDGE_PRODUCT_ID,
145-
clientId: process.env.EDGE_CLIENT_ID,
146-
clientSecret: process.env.EDGE_CLIENT_SECRET,
147120
accessTokenUrl: process.env.EDGE_ACCESS_TOKEN_URL,
148-
apiVersion: '1.0',
121+
clientSecret: process.env.EDGE_CLIENT_SECRET,
149122
skipSubmitReview: edgeSkipSubmitReview,
150123
},
151124
};
@@ -196,7 +169,6 @@ describe('resolveConfig', () => {
196169
},
197170
edge: {
198171
...config.edge,
199-
apiVersion: '1.0',
200172
skipSubmitReview: false,
201173
},
202174
};

src/config.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { z } from 'zod';
22
import { ChromeWebStoreOptions } from './chrome';
3-
import { EdgeAddonStoreOptions, EdgeAddonStoreOptionsStrict } from './edge';
3+
import { EdgeAddonStoreOptions } from './edge';
44
import { FirefoxAddonStoreOptions } from './firefox';
55
import { DeepPartial } from './utils/types';
66

@@ -72,8 +72,6 @@ export function resolveConfig(
7272
zip: edgeZip,
7373
productId: config.edge?.productId ?? stringEnv('EDGE_PRODUCT_ID'),
7474
clientId: config.edge?.clientId ?? stringEnv('EDGE_CLIENT_ID'),
75-
apiVersion:
76-
config.edge?.apiVersion ?? stringEnv('EDGE_API_VERSION') ?? '1.0',
7775
apiKey: config.edge?.apiKey ?? stringEnv('EDGE_API_KEY'),
7876
clientSecret:
7977
config.edge?.clientSecret ?? stringEnv('EDGE_CLIENT_SECRET'),
@@ -147,7 +145,7 @@ export const InternalConfig = z.object({
147145
dryRun: z.boolean(),
148146
chrome: ChromeWebStoreOptions.optional(),
149147
firefox: FirefoxAddonStoreOptions.optional(),
150-
edge: EdgeAddonStoreOptionsStrict.optional(),
148+
edge: EdgeAddonStoreOptions.optional(),
151149
});
152150
export type InternalConfig = z.infer<typeof InternalConfig>;
153151

@@ -179,7 +177,6 @@ interface CustomEnv {
179177
/** @deprecated since Edge API v1.1 release */
180178
EDGE_ACCESS_TOKEN_URL: string | undefined;
181179
EDGE_API_KEY: string | undefined;
182-
EDGE_API_VERSION: '1.0' | '1.1' | undefined;
183180
EDGE_SKIP_SUBMIT_REVIEW: string | undefined;
184181
}
185182

src/edge/edge-addon-store.ts

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,19 @@ import { Store } from '../utils/store';
55
import { z } from 'zod';
66
import { ensureZipExists } from '../utils/fs';
77

8-
const EdgeAddonBaseOptions = z.object({
8+
export const EdgeAddonStoreOptions = z.object({
99
zip: z.string().min(1),
1010
productId: z.string().min(1).trim(),
1111
clientId: z.string().min(1).trim(),
1212
skipSubmitReview: z.boolean().default(false),
13-
});
14-
15-
const EdgeAddonStore1_0Options = {
16-
apiVersion: z.literal('1.0').default('1.0'),
17-
clientSecret: z.string().min(1).trim(),
18-
accessTokenUrl: z.string().min(1).trim(),
19-
};
20-
const EdgeAddonStore1_1Options = {
21-
apiVersion: z.literal('1.1'),
2213
apiKey: z.string().min(1).trim(),
23-
};
24-
25-
export const EdgeAddonStoreOptions = EdgeAddonBaseOptions.extend({
26-
...EdgeAddonStore1_0Options,
27-
...EdgeAddonStore1_1Options,
28-
apiVersion: z.enum(['1.0', '1.1']).default('1.0'),
14+
/** @deprecated: API v1.0 authorization field no longer in use. */
15+
clientSecret: z.string().optional(),
16+
/** @deprecated: API v1.0 authorization field no longer in use. */
17+
accessTokenUrl: z.string().optional(),
2918
});
3019

31-
// Zod does not support calling .partial() on discriminated unions, so we have
32-
// to create two types. One containing all options and one discriminated union
33-
// between versions.
34-
export const EdgeAddonStoreOptionsStrict = EdgeAddonBaseOptions.and(
35-
z.discriminatedUnion('apiVersion', [
36-
z.object(EdgeAddonStore1_0Options),
37-
z.object(EdgeAddonStore1_1Options),
38-
]),
39-
);
40-
41-
export type EdgeAddonStoreOptions = z.infer<typeof EdgeAddonStoreOptionsStrict>;
20+
export type EdgeAddonStoreOptions = z.infer<typeof EdgeAddonStoreOptions>;
4221

4322
export class EdgeAddonStore implements Store {
4423
private api: EdgeApi;

src/edge/edge-api.ts

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,8 @@ import { fetch } from '../utils/fetch';
44
export type EdgeApiOptions = {
55
productId: string;
66
clientId: string;
7-
} & (
8-
| {
9-
apiVersion: '1.0';
10-
clientSecret: string;
11-
accessTokenUrl: string;
12-
}
13-
| {
14-
apiVersion: '1.1';
15-
apiKey: string;
16-
}
17-
);
7+
apiKey: string;
8+
};
189

1910
export interface EdgeTokenDetails {
2011
access_token: string;
@@ -46,30 +37,10 @@ export class EdgeApi {
4637
* Docs: https://learn.microsoft.com/en-us/microsoft-edge/extensions-chromium/publish/api/using-addons-api#sample-request
4738
*/
4839
getToken(): Promise<EdgeTokenDetails> {
49-
// Edge API requires an API key instead of an access token since version 1.1
50-
if (this.options.apiVersion !== '1.0') {
51-
return Promise.resolve({
52-
access_token: this.options.apiKey,
53-
expires_in: 0,
54-
token_type: 'ApiKey',
55-
});
56-
}
57-
58-
const form = new URLSearchParams();
59-
form.set('client_id', this.options.clientId);
60-
form.set(
61-
'scope',
62-
'https://api.addons.microsoftedge.microsoft.com/.default',
63-
);
64-
form.set('client_secret', this.options.clientSecret);
65-
form.set('grant_type', 'client_credentials');
66-
67-
return fetch(this.options.accessTokenUrl, {
68-
method: 'POST',
69-
body: form,
70-
headers: {
71-
'Content-Type': 'application/x-www-form-urlencoded',
72-
},
40+
return Promise.resolve({
41+
access_token: this.options.apiKey,
42+
expires_in: 0,
43+
token_type: 'ApiKey',
7344
});
7445
}
7546

src/init.ts

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -262,43 +262,13 @@ async function initEdge(
262262
previousOptions?.clientId,
263263
);
264264
entries.push(['EDGE_CLIENT_ID', clientId]);
265-
const apiVersion = await prompt<string>(
266-
'Enter the API version you will use:',
267-
{
268-
type: 'select',
269-
options: ['1.1', '1.0'],
270-
},
271-
previousOptions?.apiVersion,
265+
266+
const apiKey = await prompt<string>(
267+
'Enter your API key:',
268+
{ type: 'text' },
269+
previousOptions?.apiKey,
272270
);
273-
entries.push(['EDGE_API_VERSION', apiVersion]);
274-
275-
if (apiVersion === '1.1') {
276-
const apiKey = await prompt<string>(
277-
'Enter your API key:',
278-
{ type: 'text' },
279-
previousOptions?.apiVersion === '1.1'
280-
? previousOptions.apiKey
281-
: undefined,
282-
);
283-
entries.push(['EDGE_API_KEY', apiKey]);
284-
} else {
285-
const clientSecret = await prompt<string>(
286-
'Enter your client secret:',
287-
{ type: 'text' },
288-
previousOptions?.apiVersion === '1.0'
289-
? previousOptions?.clientSecret
290-
: undefined,
291-
);
292-
const accessTokenUrl = await prompt<string>(
293-
'Enter your access token URL:',
294-
{ type: 'text' },
295-
previousOptions?.apiVersion === '1.0'
296-
? previousOptions?.accessTokenUrl
297-
: undefined,
298-
);
299-
entries.push(['EDGE_CLIENT_SECRET', clientSecret]);
300-
entries.push(['EDGE_ACCESS_TOKEN_URL', accessTokenUrl]);
301-
}
271+
entries.push(['EDGE_API_KEY', apiKey]);
302272

303273
const submitForReview = await prompt<boolean>(
304274
'When uploading, automatically submit new update for review?',

src/submit.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,22 @@ export async function submit(config: InlineConfig): Promise<SubmitResults> {
1717
consola.warn('Dry run, skipping submission');
1818
}
1919

20-
if (internalConfig.edge?.apiVersion === '1.0') {
20+
if (
21+
internalConfig.edge?.clientSecret ||
22+
internalConfig.edge?.accessTokenUrl
23+
) {
2124
consola.warn(
2225
[
23-
'Edge API v1.0 will stop working Jan 1, 2025. To upgrade to v1.1:',
24-
' 1. Pass the new CLI flag (`--edge-api-version 1.1`) or set the environment variable (`EDGE_API_VERSION=1.1`) to opt into the new version',
25-
' 2. Replace the client secret/access token URL with an API key (`--edge-api-key` flag or `EDGE_API_KEY` environment variable)',
26-
' 3. Stop passing in a client secret and access token URL',
27-
'Or run `publish-extension init` and re-initialize the edge store for API v1.1.',
26+
'Edge API v1.0 was deprecated Jan 1, 2025. v1.1 of the API requires different authentication. To upgrade:',
27+
' 1. Remove the `--edge-client-secret` or `EDGE_CLIENT_SECRET` environment variable',
28+
' 2. Remove the `--edge-access-token-url` or `EDGE_ACCESS_TOKEN_URL` environment variable',
29+
' 3. Follow the instructions below to add the `--edge-api-key` flag or `EDGE_API_KEY` environment variable',
30+
'Or run `publish-extension init` and re-initialize the edge store.',
2831
'',
2932
'To generate an API key:',
30-
'1. Visit https://partner.microsoft.com/en-us/dashboard/microsoftedge/publishapi',
31-
'2. Enable the v1.1 API if necessary.',
32-
'3. Create an new API key',
33+
' 1. Visit https://partner.microsoft.com/en-us/dashboard/microsoftedge/publishapi',
34+
' 2. Enable the v1.1 API if necessary',
35+
' 3. Create an new API key',
3336
'',
3437
'Refer to Microsoft API reference for more details: https://learn.microsoft.com/en-us/microsoft-edge/extensions-chromium/publish/api/using-addons-api?tabs=v1-1#overview-of-using-the-update-rest-api',
3538
].join('\n'),

0 commit comments

Comments
 (0)