Repository: auth0/nextjs-auth0
Pull request #791 (2022-08-25 17:13:40)

Return `204` from `/api/auth/me` when logged out [SDK-3564]
<!--
❗ For general support or usage questions, use the Auth0 Community forums or raise a support ticket.

By submitting a pull request to this repository, you agree to the terms within the Auth0 Code of Conduct: https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md.
-->

⚠️ **This PR contains breaking changes**

- [ ] All new/changed/fixed functionality is covered by tests (or N/A)
- [ ] I have added documentation for all new/changed functionality (or N/A)

<!--
❗ All the above items are required. Pull requests with an incomplete or missing checklist will be closed.
-->

### 📋 Changes

Previously the profile API route, by default at `/api/auth/me`, would return a 401 error when the user was not authenticated. While it was technically the right status code for the situation, it showed up in the browser console as an error. 

This PR makes it return a 204 instead. Since 204 is a successful status code, it will not produce a console error.

### 📎 References

Fixes https://github.com/auth0/nextjs-auth0/issues/430 https://github.com/auth0/nextjs-auth0/issues/720

### 🎯 Testing

The unit tests were updated, and also the changes were tested manually using the kitchen sink example.

vercel[bot]: **The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)


<details><summary>1 Ignored Deployment</summary>

| Name | Status | Preview | Updated |
| :--- | :----- | :------ | :------ |
| **nextjs-auth0** | ⬜️ Ignored ([Inspect](https://vercel.com/auth0/nextjs-auth0/952dAWC33VTHGWxkUZ6aVHJRATon)) |  | Aug 25, 2022 at 5:13PM (UTC) |
</details>



Patch:
diff --git a/V2_MIGRATION_GUIDE.md b/V2_MIGRATION_GUIDE.md
index 61f11d89..d23ee0eb 100644
--- a/V2_MIGRATION_GUIDE.md
+++ b/V2_MIGRATION_GUIDE.md
@@ -4,6 +4,7 @@ Guide to migrating from `1.x` to `2.x`
 
 - [`updateUser` has been added](#updateuser-has-been-added)
 - [`getServerSidePropsWrapper` has been removed](#getserversidepropswrapper-has-been-removed)
+- [Profile API route no longer returns a 401](#profile-api-route-no-longer-returns-a-401)
 
 ## `updateUser` has been added
 
@@ -72,3 +73,7 @@ export const getServerSideProps = async (ctx) => {
   }
 };
 ```
+
+## Profile API route no longer returns a 401
+
+Previously the profile API route, by default at `/api/auth/me`, would return a 401 error when the user was not authenticated. While it was technically the right status code for the situation, it showed up in the browser console as an error. This API route will now return a 204 instead. Since 204 is a successful status code, it will not produce a console error.
diff --git a/src/frontend/use-user.tsx b/src/frontend/use-user.tsx
index 5a03f0bf..4b65cb3d 100644
--- a/src/frontend/use-user.tsx
+++ b/src/frontend/use-user.tsx
@@ -37,7 +37,7 @@ export type UserContext = {
  * The `status` property contains the status code of the response. It is `0` when the request fails, e.g. due to being
  * offline.
  *
- * This error is not thrown when the status code of the response is `401`, because that means the user is not
+ * This error is not thrown when the status code of the response is `204`, because that means the user is not
  * authenticated.
  *
  * @category Client
@@ -170,11 +170,8 @@ const userFetcher: UserFetcher = async (url) => {
   } catch {
     throw new RequestError(0); // Network error
   }
-  if (response.ok) {
-    return response.json();
-  } else if (response.status === 401) {
-    return undefined;
-  }
+  if (response.status == 204) return undefined;
+  if (response.ok) return response.json();
   throw new RequestError(response.status);
 };
 
diff --git a/src/handlers/profile.ts b/src/handlers/profile.ts
index 45d0c89d..d748dae6 100644
--- a/src/handlers/profile.ts
+++ b/src/handlers/profile.ts
@@ -46,10 +46,7 @@ export default function profileHandler(
       assertReqRes(req, res);
 
       if (!sessionCache.isAuthenticated(req, res)) {
-        res.status(401).json({
-          error: 'not_authenticated',
-          description: 'The user does not have an active session or is not authenticated'
-        });
+        res.status(204).end();
         return;
       }
 


Test patch:
diff --git a/tests/fixtures/frontend.tsx b/tests/fixtures/frontend.tsx
index 222964b5..f10ff8da 100644
--- a/tests/fixtures/frontend.tsx
+++ b/tests/fixtures/frontend.tsx
@@ -40,8 +40,8 @@ export const fetchUserMock = (): Promise<FetchUserMock> => {
 
 export const fetchUserUnauthorizedMock = (): Promise<FetchUserMock> => {
   return Promise.resolve({
-    ok: false,
-    status: 401,
+    ok: true,
+    status: 204,
     json: () => Promise.resolve(undefined)
   });
 };
diff --git a/tests/frontend/use-user.test.tsx b/tests/frontend/use-user.test.tsx
index 2219b357..443bd0b8 100644
--- a/tests/frontend/use-user.test.tsx
+++ b/tests/frontend/use-user.test.tsx
@@ -123,7 +123,7 @@ describe('hook', () => {
     expect(result.current.isLoading).toEqual(false);
   });
 
-  test('should provide no user when the status code is 401', async () => {
+  test('should provide no user when the status code is 204', async () => {
     (global as any).fetch = fetchUserUnauthorizedMock;
     const { result, waitForValueToChange } = renderHook(() => useUser(), { wrapper: withUserProvider() });
 
diff --git a/tests/handlers/profile.test.ts b/tests/handlers/profile.test.ts
index 48bbe362..32eb6384 100644
--- a/tests/handlers/profile.test.ts
+++ b/tests/handlers/profile.test.ts
@@ -23,7 +23,7 @@ describe('profile handler', () => {
   test('should throw an error when not logged in', async () => {
     const baseUrl = await setup(withoutApi);
 
-    await expect(get(baseUrl, '/api/auth/me')).rejects.toThrow('Unauthorized');
+    await expect(get(baseUrl, '/api/auth/me')).resolves.toBe('');
   });
 
   test('should return the profile when logged in', async () => {
diff --git a/tests/session/update-user.test.ts b/tests/session/update-user.test.ts
index 0ee09035..e659a543 100644
--- a/tests/session/update-user.test.ts
+++ b/tests/session/update-user.test.ts
@@ -27,8 +27,8 @@ describe('update-user', () => {
 
   test('should ignore updates if user is not logged in', async () => {
     const baseUrl = await setup(withoutApi);
-    await expect(get(baseUrl, '/api/auth/me')).rejects.toThrow('Unauthorized');
+    await expect(get(baseUrl, '/api/auth/me')).resolves.toBe('');
     await post(baseUrl, '/api/update-user', { body: { user: { sub: 'foo' } } });
-    await expect(get(baseUrl, '/api/auth/me')).rejects.toThrow('Unauthorized');
+    await expect(get(baseUrl, '/api/auth/me')).resolves.toBe('');
   });
 });