Skip to content

Commit 508a1a3

Browse files
wrangler login put custom callback host and port into the auth URL (#9095)
Fixes #9065
1 parent cdc88d8 commit 508a1a3

File tree

3 files changed

+62
-6
lines changed

3 files changed

+62
-6
lines changed

.changeset/tough-bats-live.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
wrangler login put custom callback host and port into the auth URL

packages/wrangler/src/__tests__/user.test.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,46 @@ describe("User", () => {
107107
expect(std.out).toMatchInlineSnapshot(`
108108
"Attempting to login via OAuth...
109109
Temporary login server listening on 0.0.0.0:8976
110-
Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2Flocalhost%3A8976%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20d1%3Awrite%20pages%3Awrite%20zone%3Aread%20ssl_certs%3Awrite%20ai%3Awrite%20queues%3Awrite%20pipelines%3Awrite%20secrets_store%3Awrite%20offline_access&state=MOCK_STATE_PARAM&code_challenge=MOCK_CODE_CHALLENGE&code_challenge_method=S256
110+
Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2F0.0.0.0%3A8976%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20d1%3Awrite%20pages%3Awrite%20zone%3Aread%20ssl_certs%3Awrite%20ai%3Awrite%20queues%3Awrite%20pipelines%3Awrite%20secrets_store%3Awrite%20offline_access&state=MOCK_STATE_PARAM&code_challenge=MOCK_CODE_CHALLENGE&code_challenge_method=S256
111+
Successfully logged in."
112+
`);
113+
expect(readAuthConfigFile()).toEqual<UserAuthConfig>({
114+
api_token: undefined,
115+
oauth_token: "test-access-token",
116+
refresh_token: "test-refresh-token",
117+
expiration_time: expect.any(String),
118+
scopes: ["account:read"],
119+
});
120+
});
121+
122+
it("should login a user when `wrangler login` is run with custom callbackPort param", async () => {
123+
mockOAuthServerCallback("success");
124+
125+
let counter = 0;
126+
msw.use(
127+
http.post(
128+
"*/oauth2/token",
129+
async () => {
130+
counter += 1;
131+
132+
return HttpResponse.json({
133+
access_token: "test-access-token",
134+
expires_in: 100000,
135+
refresh_token: "test-refresh-token",
136+
scope: "account:read",
137+
});
138+
},
139+
{ once: true }
140+
)
141+
);
142+
143+
await runWrangler("login --callback-port=8787");
144+
145+
expect(counter).toBe(1);
146+
expect(std.out).toMatchInlineSnapshot(`
147+
"Attempting to login via OAuth...
148+
Temporary login server listening on localhost:8787
149+
Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2Flocalhost%3A8787%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20d1%3Awrite%20pages%3Awrite%20zone%3Aread%20ssl_certs%3Awrite%20ai%3Awrite%20queues%3Awrite%20pipelines%3Awrite%20secrets_store%3Awrite%20offline_access&state=MOCK_STATE_PARAM&code_challenge=MOCK_CODE_CHALLENGE&code_challenge_method=S256
111150
Successfully logged in."
112151
`);
113152
expect(readAuthConfigFile()).toEqual<UserAuthConfig>({

packages/wrangler/src/user/user.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,9 @@ export function validateScopeKeys(
386386
return scopes.every((scope) => scope in DefaultScopes);
387387
}
388388

389-
const CALLBACK_URL = "http://localhost:8976/oauth/callback";
389+
function getCallbackUrl(host = "localhost", port = 8976) {
390+
return `http://${host}:${port}/oauth/callback`;
391+
}
390392

391393
let LocalState: State = {
392394
...getAuthTokens(),
@@ -663,7 +665,12 @@ function isReturningFromAuthServer(query: ParsedUrlQuery): boolean {
663665
return true;
664666
}
665667

666-
async function getAuthURL(scopes: string[], clientId: string): Promise<string> {
668+
async function getAuthURL(
669+
scopes: string[],
670+
clientId: string,
671+
callbackHost: string,
672+
callbackPort: number
673+
): Promise<string> {
667674
const { codeChallenge, codeVerifier } = await generatePKCECodes();
668675
const stateQueryParam = generateRandomState(RECOMMENDED_STATE_LENGTH);
669676

@@ -676,7 +683,7 @@ async function getAuthURL(scopes: string[], clientId: string): Promise<string> {
676683
return generateAuthUrl({
677684
authUrl: getAuthUrlFromEnv(),
678685
clientId,
679-
callbackUrl: CALLBACK_URL,
686+
callbackUrl: getCallbackUrl(callbackHost, callbackPort),
680687
scopes,
681688
stateQueryParam,
682689
codeChallenge,
@@ -790,7 +797,7 @@ async function exchangeAuthCodeForAccessToken(): Promise<AccessContext> {
790797
const params = new URLSearchParams({
791798
grant_type: `authorization_code`,
792799
code: authorizationCode ?? "",
793-
redirect_uri: CALLBACK_URL,
800+
redirect_uri: getCallbackUrl(),
794801
client_id: getClientIdFromEnv(),
795802
code_verifier: codeVerifier,
796803
});
@@ -957,7 +964,12 @@ export async function getOauthToken(options: {
957964
callbackHost: string;
958965
callbackPort: number;
959966
}): Promise<AccessContext> {
960-
const urlToOpen = await getAuthURL(options.scopes, options.clientId);
967+
const urlToOpen = await getAuthURL(
968+
options.scopes,
969+
options.clientId,
970+
options.callbackHost,
971+
options.callbackPort
972+
);
961973
let server: http.Server;
962974
let loginTimeoutHandle: ReturnType<typeof setTimeout>;
963975
const timerPromise = new Promise<AccessContext>((_, reject) => {

0 commit comments

Comments
 (0)