Repository: octokit/oauth-app.js
Pull request #256 (2021-08-03 08:09:40)

Delete `authentication.clientSecret` from HTTP responses
1. This PR deletes `authentication.clientSecret` from the following endpoints:

    1. create token
    2. create scoped token
    3. check token
    4. reset token
    5. refresh token

2. All above responses now have an `authentication` property. This is a breaking change for `create token`. 
3. All returned `authentication` properties now have `"type"` and `"tokenType"` set.

Thanks.

baoshan: Please review the PR when you have time. I’ll continue working on `auth-oauth-user-client.js` later.

Thanks.

Patch:
diff --git a/package-lock.json b/package-lock.json
index 07112e0..74408de 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13544,11 +13544,6 @@
         "safer-buffer": "^2.0.2",
         "tweetnacl": "~0.14.0"
       },
-      "bin": {
-        "sshpk-conv": "bin/sshpk-conv",
-        "sshpk-sign": "bin/sshpk-sign",
-        "sshpk-verify": "bin/sshpk-verify"
-      },
       "engines": {
         "node": ">=0.10.0"
       }
diff --git a/src/methods/check-token.ts b/src/methods/check-token.ts
index ff878cd..1550f3d 100644
--- a/src/methods/check-token.ts
+++ b/src/methods/check-token.ts
@@ -10,7 +10,7 @@ export async function checkTokenWithState(
   state: State,
   options: CheckTokenOptions
 ): Promise<any> {
-  return await OAuthMethods.checkToken({
+  const result = await OAuthMethods.checkToken({
     // @ts-expect-error not worth the extra code to appease TS
     clientType: state.clientType,
     clientId: state.clientId,
@@ -18,10 +18,17 @@ export async function checkTokenWithState(
     request: state.octokit.request,
     ...options,
   });
+  Object.assign(result.authentication, { type: "token", tokenType: "oauth" });
+  return result;
 }
 
 export interface CheckTokenInterface<TClientType extends ClientType> {
-  (options: CheckTokenOptions): TClientType extends "oauth-app"
+  (options: CheckTokenOptions): (TClientType extends "oauth-app"
     ? Promise<OAuthMethods.CheckTokenOAuthAppResponse>
-    : Promise<OAuthMethods.CheckTokenGitHubAppResponse>;
+    : Promise<OAuthMethods.CheckTokenGitHubAppResponse>) & {
+    authentication: {
+      type: "token";
+      tokenType: "oauth";
+    };
+  };
 }
diff --git a/src/methods/refresh-token.ts b/src/methods/refresh-token.ts
index 55e34fe..b0f7e56 100644
--- a/src/methods/refresh-token.ts
+++ b/src/methods/refresh-token.ts
@@ -11,7 +11,14 @@ export type RefreshTokenOptions = {
 export async function refreshTokenWithState(
   state: State,
   options: RefreshTokenOptions
-): Promise<OAuthMethods.RefreshTokenResponse> {
+): Promise<
+  OAuthMethods.RefreshTokenResponse & {
+    authentication: {
+      type: "token";
+      tokenType: "oauth";
+    };
+  }
+> {
   if (state.clientType === "oauth-app") {
     throw new Error(
       "[@octokit/oauth-app] app.refreshToken() is not supported for OAuth Apps"
@@ -26,15 +33,16 @@ export async function refreshTokenWithState(
     refreshToken: options.refreshToken,
   });
 
+  const authentication = Object.assign(response.authentication, {
+    type: "token" as const,
+    tokenType: "oauth" as const,
+  });
+
   await emitEvent(state, {
     name: "token",
     action: "refreshed",
     token: response.authentication.token,
-    authentication: {
-      type: "token",
-      tokenType: "oauth",
-      ...response.authentication,
-    },
+    authentication: authentication,
     octokit: new state.Octokit({
       authStrategy: createOAuthUserAuth,
       auth: {
@@ -46,9 +54,16 @@ export async function refreshTokenWithState(
     }),
   });
 
-  return response;
+  return { ...response, authentication };
 }
 
 export interface RefreshTokenInterface {
-  (options: RefreshTokenOptions): Promise<OAuthMethods.RefreshTokenResponse>;
+  (options: RefreshTokenOptions): Promise<
+    OAuthMethods.RefreshTokenResponse & {
+      authentication: {
+        type: "token";
+        tokenType: "oauth";
+      };
+    }
+  >;
 }
diff --git a/src/methods/reset-token.ts b/src/methods/reset-token.ts
index a2f51e4..29bf642 100644
--- a/src/methods/reset-token.ts
+++ b/src/methods/reset-token.ts
@@ -12,8 +12,15 @@ export async function resetTokenWithState(
   state: State,
   options: ResetTokenOptions
 ): Promise<
-  | OAuthMethods.ResetTokenOAuthAppResponse
-  | OAuthMethods.ResetTokenGitHubAppResponse
+  (
+    | OAuthMethods.ResetTokenOAuthAppResponse
+    | OAuthMethods.ResetTokenGitHubAppResponse
+  ) & {
+    authentication: {
+      type: "token";
+      tokenType: "oauth";
+    };
+  }
 > {
   const optionsWithDefaults = {
     clientId: state.clientId,
@@ -28,16 +35,16 @@ export async function resetTokenWithState(
       ...optionsWithDefaults,
     });
 
+    const authentication = Object.assign(response.authentication, {
+      type: "token" as const,
+      tokenType: "oauth" as const,
+    });
     await emitEvent(state, {
       name: "token",
       action: "reset",
       token: response.authentication.token,
       scopes: response.authentication.scopes || undefined,
-      authentication: {
-        type: "token",
-        tokenType: "oauth",
-        ...response.authentication,
-      },
+      authentication: authentication,
       octokit: new state.Octokit({
         authStrategy: createOAuthUserAuth,
         auth: {
@@ -50,23 +57,22 @@ export async function resetTokenWithState(
       }),
     });
 
-    return response;
+    return { ...response, authentication };
   }
 
   const response = await OAuthMethods.resetToken({
     clientType: "github-app",
     ...optionsWithDefaults,
   });
-
+  const authentication = Object.assign(response.authentication, {
+    type: "token" as const,
+    tokenType: "oauth" as const,
+  });
   await emitEvent(state, {
     name: "token",
     action: "reset",
     token: response.authentication.token,
-    authentication: {
-      type: "token",
-      tokenType: "oauth",
-      ...response.authentication,
-    },
+    authentication: authentication,
     octokit: new state.Octokit({
       authStrategy: createOAuthUserAuth,
       auth: {
@@ -78,11 +84,25 @@ export async function resetTokenWithState(
     }),
   });
 
-  return response;
+  return { ...response, authentication };
 }
 
 export interface ResetTokenInterface<TClientType extends ClientType> {
   (options: ResetTokenOptions): TClientType extends "oauth-app"
-    ? Promise<OAuthMethods.ResetTokenOAuthAppResponse>
-    : Promise<OAuthMethods.ResetTokenGitHubAppResponse>;
+    ? Promise<
+        OAuthMethods.ResetTokenOAuthAppResponse & {
+          authentication: {
+            type: "token";
+            tokenType: "oauth";
+          };
+        }
+      >
+    : Promise<
+        OAuthMethods.ResetTokenGitHubAppResponse & {
+          authentication: {
+            type: "token";
+            tokenType: "oauth";
+          };
+        }
+      >;
 }
diff --git a/src/methods/scope-token.ts b/src/methods/scope-token.ts
index 18f1e2a..be04d6a 100644
--- a/src/methods/scope-token.ts
+++ b/src/methods/scope-token.ts
@@ -14,7 +14,14 @@ export type ScopeTokenOptions = Omit<
 export async function scopeTokenWithState(
   state: State,
   options: ScopeTokenOptions
-): Promise<OAuthMethods.ScopeTokenResponse> {
+): Promise<
+  OAuthMethods.ScopeTokenResponse & {
+    authentication: {
+      type: "token";
+      tokenType: "oauth";
+    };
+  }
+> {
   if (state.clientType === "oauth-app") {
     throw new Error(
       "[@octokit/oauth-app] app.scopeToken() is not supported for OAuth Apps"
@@ -29,15 +36,15 @@ export async function scopeTokenWithState(
     ...options,
   } as OAuthMethods.ScopeTokenOptions);
 
+  const authentication = Object.assign(response.authentication, {
+    type: "token" as const,
+    tokenType: "oauth" as const,
+  });
   await emitEvent(state, {
     name: "token",
     action: "scoped",
     token: response.authentication.token,
-    authentication: {
-      type: "token",
-      tokenType: "oauth",
-      ...response.authentication,
-    },
+    authentication: authentication,
     octokit: new state.Octokit({
       authStrategy: createOAuthUserAuth,
       auth: {
@@ -49,9 +56,16 @@ export async function scopeTokenWithState(
     }),
   });
 
-  return response;
+  return { ...response, authentication };
 }
 
 export interface ScopeTokenInterface {
-  (options: ScopeTokenOptions): Promise<OAuthMethods.ScopeTokenResponse>;
+  (options: ScopeTokenOptions): Promise<
+    OAuthMethods.ScopeTokenResponse & {
+      authentication: {
+        type: "token";
+        tokenType: "oauth";
+      };
+    }
+  >;
 }
diff --git a/src/middleware/handle-request.ts b/src/middleware/handle-request.ts
index ee1da21..87f7ca4 100644
--- a/src/middleware/handle-request.ts
+++ b/src/middleware/handle-request.ts
@@ -122,21 +122,22 @@ export async function handleRequest(
         );
       }
 
-      const {
-        authentication: { token, scopes },
-      } = await app.createToken({
+      const result = await app.createToken({
         state: oauthState,
         code,
         redirectUrl,
       });
 
+      // @ts-ignore
+      delete result.authentication.clientSecret;
+
       return {
         status: 201,
         headers: {
           "content-type": "application/json",
           "access-control-allow-origin": "*",
         },
-        text: JSON.stringify({ token, scopes }),
+        text: JSON.stringify(result),
       };
     }
 
@@ -153,6 +154,9 @@ export async function handleRequest(
         token,
       });
 
+      // @ts-ignore
+      delete result.authentication.clientSecret;
+
       return {
         status: 200,
         headers: {
@@ -172,9 +176,10 @@ export async function handleRequest(
         );
       }
 
-      const result = await app.resetToken({
-        token,
-      });
+      const result = await app.resetToken({ token });
+
+      // @ts-ignore
+      delete result.authentication.clientSecret;
 
       return {
         status: 200,
@@ -205,6 +210,9 @@ export async function handleRequest(
 
       const result = await app.refreshToken({ refreshToken });
 
+      // @ts-ignore
+      delete result.authentication.clientSecret;
+
       return {
         status: 200,
         headers: {
@@ -229,6 +237,9 @@ export async function handleRequest(
         ...json,
       });
 
+      // @ts-ignore
+      delete result.authentication.clientSecret;
+
       return {
         status: 200,
         headers: {
@@ -275,7 +286,7 @@ export async function handleRequest(
       status: 204,
       headers: { "access-control-allow-origin": "*" },
     };
-  } catch (error) {
+  } catch (error: any) {
     return {
       status: 400,
       headers: {


Test patch:
diff --git a/test/app.test.ts b/test/app.test.ts
index a0df1b3..1100614 100644
--- a/test/app.test.ts
+++ b/test/app.test.ts
@@ -314,6 +314,8 @@ describe("app", () => {
           "clientType": "oauth-app",
           "scopes": undefined,
           "token": "token123",
+          "tokenType": "oauth",
+          "type": "token",
         },
         "data": Object {
           "id": 1,
@@ -377,6 +379,8 @@ describe("app", () => {
             "gist",
           ],
           "token": "token456",
+          "tokenType": "oauth",
+          "type": "token",
         },
         "data": Object {
           "id": 2,
@@ -452,6 +456,8 @@ describe("app", () => {
           "clientType": "oauth-app",
           "scopes": null,
           "token": "token456",
+          "tokenType": "oauth",
+          "type": "token",
         },
         "data": Object {
           "id": 2,
@@ -525,6 +531,8 @@ describe("app", () => {
           "clientSecret": "1234567890abcdef1234567890abcdef12345678",
           "clientType": "github-app",
           "token": "token456",
+          "tokenType": "oauth",
+          "type": "token",
         },
         "data": Object {
           "id": 2,
@@ -605,6 +613,8 @@ describe("app", () => {
           "refreshToken": "r1.token456",
           "refreshTokenExpiresAt": "1970-07-04T00:00:00.000Z",
           "token": "secret456",
+          "tokenType": "oauth",
+          "type": "token",
         },
         "data": Object {
           "access_token": "secret456",
@@ -702,6 +712,8 @@ describe("app", () => {
           "clientSecret": "1234567890abcdef12347890abcdef12345678",
           "clientType": "github-app",
           "token": "token456",
+          "tokenType": "oauth",
+          "type": "token",
         },
         "data": Object {
           "account": Object {
diff --git a/test/cloudflare-handler.test.ts b/test/cloudflare-handler.test.ts
index b67334c..2912054 100644
--- a/test/cloudflare-handler.test.ts
+++ b/test/cloudflare-handler.test.ts
@@ -96,9 +96,13 @@ describe("createCloudflareHandler(app)", () => {
 
   it("GET /api/github/oauth/callback?code=012345&state=mystate123", async () => {
     const appMock = {
-      createToken: jest
-        .fn()
-        .mockResolvedValue({ authentication: { token: "token123" } }),
+      createToken: jest.fn().mockResolvedValue({
+        authentication: {
+          type: "token",
+          tokenType: "oauth",
+          token: "token123",
+        },
+      }),
     };
     const handleRequest = createCloudflareHandler(
       appMock as unknown as OAuthApp
@@ -123,8 +127,9 @@ describe("createCloudflareHandler(app)", () => {
     const appMock = {
       createToken: jest.fn().mockResolvedValue({
         authentication: {
-          token: "token123",
-          scopes: ["repo", "gist"],
+          type: "token",
+          tokenType: "oauth",
+          clientSecret: "secret123",
         },
       }),
     };
@@ -144,8 +149,7 @@ describe("createCloudflareHandler(app)", () => {
 
     expect(response.status).toEqual(201);
     expect(await response.json()).toStrictEqual({
-      token: "token123",
-      scopes: ["repo", "gist"],
+      authentication: { type: "token", tokenType: "oauth" },
     });
 
     expect(appMock.createToken.mock.calls.length).toEqual(1);
@@ -158,7 +162,14 @@ describe("createCloudflareHandler(app)", () => {
 
   it("GET /api/github/oauth/token", async () => {
     const appMock = {
-      checkToken: jest.fn().mockResolvedValue({ id: 1 }),
+      checkToken: jest.fn().mockResolvedValue({
+        data: { id: 1 },
+        authentication: {
+          type: "token",
+          tokenType: "oauth",
+          clientSecret: "secret123",
+        },
+      }),
     };
     const handleRequest = createCloudflareHandler(
       appMock as unknown as OAuthApp
@@ -172,7 +183,10 @@ describe("createCloudflareHandler(app)", () => {
     const response = await handleRequest(request);
 
     expect(response.status).toEqual(200);
-    expect(await response.json()).toStrictEqual({ id: 1 });
+    expect(await response.json()).toStrictEqual({
+      data: { id: 1 },
+      authentication: { type: "token", tokenType: "oauth" },
+    });
 
     expect(appMock.checkToken.mock.calls.length).toEqual(1);
     expect(appMock.checkToken.mock.calls[0][0]).toStrictEqual({
@@ -183,9 +197,12 @@ describe("createCloudflareHandler(app)", () => {
   it("PATCH /api/github/oauth/token", async () => {
     const appMock = {
       resetToken: jest.fn().mockResolvedValue({
-        id: 2,
-        token: "token456",
-        scopes: ["repo", "gist"],
+        data: { id: 1 },
+        authentication: {
+          type: "token",
+          tokenType: "oauth",
+          clientSecret: "secret123",
+        },
       }),
     };
     const handleRequest = createCloudflareHandler(
@@ -200,9 +217,8 @@ describe("createCloudflareHandler(app)", () => {
 
     expect(response.status).toEqual(200);
     expect(await response.json()).toStrictEqual({
-      id: 2,
-      token: "token456",
-      scopes: ["repo", "gist"],
+      data: { id: 1 },
+      authentication: { type: "token", tokenType: "oauth" },
     });
 
     expect(appMock.resetToken.mock.calls.length).toEqual(1);
@@ -215,7 +231,11 @@ describe("createCloudflareHandler(app)", () => {
     const appMock = {
       scopeToken: jest.fn().mockResolvedValue({
         data: { id: 1 },
-        authentication: { token: "scopedtoken456" },
+        authentication: {
+          type: "token",
+          tokenType: "oauth",
+          clientSecret: "secret123",
+        },
       }),
     };
     const handleRequest = createCloudflareHandler(
@@ -233,11 +253,13 @@ describe("createCloudflareHandler(app)", () => {
     });
     const response = await handleRequest(request);
 
+    expect(response.status).toEqual(200);
     expect(response.status).toEqual(200);
     expect(await response.json()).toMatchInlineSnapshot(`
       Object {
         "authentication": Object {
-          "token": "scopedtoken456",
+          "tokenType": "oauth",
+          "type": "token",
         },
         "data": Object {
           "id": 1,
@@ -262,7 +284,14 @@ describe("createCloudflareHandler(app)", () => {
 
   it("PATCH /api/github/oauth/refresh-token", async () => {
     const appMock = {
-      refreshToken: jest.fn().mockResolvedValue({ ok: true }),
+      refreshToken: jest.fn().mockResolvedValue({
+        data: { id: 1 },
+        authentication: {
+          type: "token",
+          tokenType: "oauth",
+          clientSecret: "secret123",
+        },
+      }),
     };
     const handleRequest = createCloudflareHandler(
       appMock as unknown as OAuthApp
@@ -275,7 +304,10 @@ describe("createCloudflareHandler(app)", () => {
     });
     const response = await handleRequest(request);
 
-    expect(await response.json()).toStrictEqual({ ok: true });
+    expect(await response.json()).toStrictEqual({
+      data: { id: 1 },
+      authentication: { type: "token", tokenType: "oauth" },
+    });
     expect(response.status).toEqual(200);
 
     expect(appMock.refreshToken.mock.calls.length).toEqual(1);
@@ -287,9 +319,12 @@ describe("createCloudflareHandler(app)", () => {
   it("PATCH /api/github/oauth/token", async () => {
     const appMock = {
       resetToken: jest.fn().mockResolvedValue({
-        id: 2,
-        token: "token456",
-        scopes: ["repo", "gist"],
+        data: { id: 1 },
+        authentication: {
+          type: "token",
+          tokenType: "oauth",
+          clientSecret: "secret123",
+        },
       }),
     };
     const handleRequest = createCloudflareHandler(
@@ -304,9 +339,8 @@ describe("createCloudflareHandler(app)", () => {
 
     expect(response.status).toEqual(200);
     expect(await response.json()).toStrictEqual({
-      id: 2,
-      token: "token456",
-      scopes: ["repo", "gist"],
+      data: { id: 1 },
+      authentication: { type: "token", tokenType: "oauth" },
     });
 
     expect(appMock.resetToken.mock.calls.length).toEqual(1);
diff --git a/test/node-middleware.test.ts b/test/node-middleware.test.ts
index 85fdd81..b2c6db7 100644
--- a/test/node-middleware.test.ts
+++ b/test/node-middleware.test.ts
@@ -126,9 +126,13 @@ describe("createNodeMiddleware(app)", () => {
 
   it("GET /api/github/oauth/callback?code=012345&state=mystate123", async () => {
     const appMock = {
-      createToken: jest
-        .fn()
-        .mockResolvedValue({ authentication: { token: "token123" } }),
+      createToken: jest.fn().mockResolvedValue({
+        authentication: {
+          type: "token",
+          tokenType: "oauth",
+          token: "token123",
+        },
+      }),
     };
 
     const server = createServer(
@@ -157,8 +161,9 @@ describe("createNodeMiddleware(app)", () => {
     const appMock = {
       createToken: jest.fn().mockResolvedValue({
         authentication: {
-          token: "token123",
-          scopes: ["repo", "gist"],
+          type: "token",
+          tokenType: "oauth",
+          clientSecret: "secret123",
         },
       }),
     };
@@ -185,8 +190,7 @@ describe("createNodeMiddleware(app)", () => {
 
     expect(response.status).toEqual(201);
     expect(await response.json()).toStrictEqual({
-      token: "token123",
-      scopes: ["repo", "gist"],
+      authentication: { type: "token", tokenType: "oauth" },
     });
 
     expect(appMock.createToken.mock.calls.length).toEqual(1);
@@ -199,7 +203,14 @@ describe("createNodeMiddleware(app)", () => {
 
   it("GET /api/github/oauth/token", async () => {
     const appMock = {
-      checkToken: jest.fn().mockResolvedValue({ id: 1 }),
+      checkToken: jest.fn().mockResolvedValue({
+        data: { id: 1 },
+        authentication: {
+          type: "token",
+          tokenType: "oauth",
+          clientSecret: "secret123",
+        },
+      }),
     };
 
     const server = createServer(
@@ -220,7 +231,10 @@ describe("createNodeMiddleware(app)", () => {
     server.close();
 
     expect(response.status).toEqual(200);
-    expect(await response.json()).toStrictEqual({ id: 1 });
+    expect(await response.json()).toStrictEqual({
+      data: { id: 1 },
+      authentication: { type: "token", tokenType: "oauth" },
+    });
 
     expect(appMock.checkToken.mock.calls.length).toEqual(1);
     expect(appMock.checkToken.mock.calls[0][0]).toStrictEqual({
@@ -231,9 +245,12 @@ describe("createNodeMiddleware(app)", () => {
   it("PATCH /api/github/oauth/token", async () => {
     const appMock = {
       resetToken: jest.fn().mockResolvedValue({
-        id: 2,
-        token: "token456",
-        scopes: ["repo", "gist"],
+        data: { id: 1 },
+        authentication: {
+          type: "token",
+          tokenType: "oauth",
+          clientSecret: "secret123",
+        },
       }),
     };
 
@@ -257,9 +274,8 @@ describe("createNodeMiddleware(app)", () => {
 
     expect(response.status).toEqual(200);
     expect(await response.json()).toStrictEqual({
-      id: 2,
-      token: "token456",
-      scopes: ["repo", "gist"],
+      data: { id: 1 },
+      authentication: { type: "token", tokenType: "oauth" },
     });
 
     expect(appMock.resetToken.mock.calls.length).toEqual(1);
@@ -271,11 +287,11 @@ describe("createNodeMiddleware(app)", () => {
   it("POST /api/github/oauth/token/scoped", async () => {
     const appMock = {
       scopeToken: jest.fn().mockResolvedValue({
-        data: {
-          id: 1,
-        },
+        data: { id: 1 },
         authentication: {
-          token: "scopedtoken456",
+          type: "token",
+          tokenType: "oauth",
+          clientSecret: "secret123",
         },
       }),
     };
@@ -305,14 +321,15 @@ describe("createNodeMiddleware(app)", () => {
 
     expect(response.status).toEqual(200);
     expect(await response.json()).toMatchInlineSnapshot(`
-      Object {
-        "authentication": Object {
-          "token": "scopedtoken456",
-        },
-        "data": Object {
-          "id": 1,
-        },
-      }
+    Object {
+      "authentication": Object {
+        "tokenType": "oauth",
+        "type": "token",
+      },
+      "data": Object {
+        "id": 1,
+      },
+    }
     `);
 
     expect(appMock.scopeToken.mock.calls.length).toEqual(1);
@@ -333,7 +350,12 @@ describe("createNodeMiddleware(app)", () => {
   it("PATCH /api/github/oauth/refresh-token", async () => {
     const appMock = {
       refreshToken: jest.fn().mockResolvedValue({
-        ok: true,
+        data: { id: 1 },
+        authentication: {
+          type: "token",
+          tokenType: "oauth",
+          clientSecret: "secret123",
+        },
       }),
     };
 
@@ -359,7 +381,8 @@ describe("createNodeMiddleware(app)", () => {
     server.close();
 
     expect(await response.json()).toStrictEqual({
-      ok: true,
+      data: { id: 1 },
+      authentication: { type: "token", tokenType: "oauth" },
     });
     expect(response.status).toEqual(200);
 
@@ -371,9 +394,12 @@ describe("createNodeMiddleware(app)", () => {
   it("PATCH /api/github/oauth/token", async () => {
     const appMock = {
       resetToken: jest.fn().mockResolvedValue({
-        id: 2,
-        token: "token456",
-        scopes: ["repo", "gist"],
+        data: { id: 1 },
+        authentication: {
+          type: "token",
+          tokenType: "oauth",
+          clientSecret: "secret123",
+        },
       }),
     };
 
@@ -397,9 +423,8 @@ describe("createNodeMiddleware(app)", () => {
 
     expect(response.status).toEqual(200);
     expect(await response.json()).toStrictEqual({
-      id: 2,
-      token: "token456",
-      scopes: ["repo", "gist"],
+      data: { id: 1 },
+      authentication: { type: "token", tokenType: "oauth" },
     });
 
     expect(appMock.resetToken.mock.calls.length).toEqual(1);