Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(nextjs): Return 401 Response on protected API routes #1276

Conversation

anagstef
Copy link
Member

@anagstef anagstef commented Jun 2, 2023

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Packages affected

  • @clerk/clerk-js
  • @clerk/clerk-react
  • @clerk/nextjs
  • @clerk/remix
  • @clerk/types
  • @clerk/themes
  • @clerk/localizations
  • @clerk/clerk-expo
  • @clerk/backend
  • @clerk/clerk-sdk-node
  • @clerk/shared
  • @clerk/fastify
  • @clerk/chrome-extension
  • gatsby-plugin-clerk
  • build/tooling/chore

Description

  • npm test runs as expected.
  • npm run build runs as expected.

This commit introduces a new apiRoutes param on authMiddleware.

If apiRoutes is omitted, then the following heuristic is used:

  • If the route path is ['/api/(.*)', '/trpc/(.*)']
  • or Request has Content-Type: application/json
  • or Request method is not-GET,OPTIONS,HEAD,

then this is considered an API route.

After this commit, a 401 JSON Response is returned on the following 3 cases:

  • When the authenticateRequest function returns the Unknown state.
  • When the authenticateRequest function returns the Interstitial state and the route is an API route.
  • When the user is signed out, the route is protected (not public), and the route is an API route. (this one happens inside our default implementation of afterAuth. If it is overwritten, then the user needs to handle this case themselves)

@anagstef anagstef requested review from dimkl and desiprisg June 2, 2023 09:51
@anagstef anagstef self-assigned this Jun 2, 2023
Copy link

@jit-ci jit-ci bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Great news! Jit hasn't found any security issues in your PR. Good Job! 🏆

Copy link
Contributor

@dimkl dimkl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ should we also add the isApiRoute to the auth object ?

packages/nextjs/src/server/authMiddleware.ts Outdated Show resolved Hide resolved
packages/nextjs/src/server/authMiddleware.ts Outdated Show resolved Hide resolved
packages/nextjs/src/server/utils.ts Outdated Show resolved Hide resolved
packages/nextjs/src/server/authMiddleware.ts Outdated Show resolved Hide resolved
@anagstef anagstef force-pushed the stefanos/js-411-api-endpoints-protected-by-authmiddleware-should-return-401 branch 2 times, most recently from 06ea88b to 5909c28 Compare June 6, 2023 15:55
@changeset-bot
Copy link

changeset-bot bot commented Jun 6, 2023

🦋 Changeset detected

Latest commit: 56e8fba

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@clerk/nextjs Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added the nextjs label Jun 6, 2023
@nikosdouvlis
Copy link
Member

!snapshot

@github-actions
Copy link
Contributor

github-actions bot commented Jun 6, 2023

Hey @nikosdouvlis - the snapshot version command generated the following package versions:

Package Version
@clerk/backend 0.21.1-snap.5909c28
@clerk/chrome-extension 0.3.8-snap.5909c28
@clerk/clerk-js 4.45.1-snap.5909c28
eslint-config-custom 0.3.0
@clerk/clerk-expo 0.17.8-snap.5909c28
@clerk/fastify 0.4.6-snap.5909c28
gatsby-plugin-clerk 4.3.7-snap.5909c28
@clerk/localizations 1.17.0
@clerk/nextjs 4.19.2-snap.5909c28
@clerk/clerk-react 4.18.0
@clerk/remix 2.6.6-snap.5909c28
@clerk/clerk-sdk-node 4.10.4-snap.5909c28
@clerk/shared 0.17.2
@clerk/themes 1.7.5
@clerk/types 3.41.0

Tip: use the snippet copy button below to quickly install the required packages.

# @clerk/backend
npm i @clerk/backend@0.21.1-snap.5909c28
# @clerk/chrome-extension
npm i @clerk/chrome-extension@0.3.8-snap.5909c28
# @clerk/clerk-js
npm i @clerk/clerk-js@4.45.1-snap.5909c28
# eslint-config-custom
npm i eslint-config-custom@0.3.0
# @clerk/clerk-expo
npm i @clerk/clerk-expo@0.17.8-snap.5909c28
# @clerk/fastify
npm i @clerk/fastify@0.4.6-snap.5909c28
# gatsby-plugin-clerk
npm i gatsby-plugin-clerk@4.3.7-snap.5909c28
# @clerk/localizations
npm i @clerk/localizations@1.17.0
# @clerk/nextjs
npm i @clerk/nextjs@4.19.2-snap.5909c28
# @clerk/clerk-react
npm i @clerk/clerk-react@4.18.0
# @clerk/remix
npm i @clerk/remix@2.6.6-snap.5909c28
# @clerk/clerk-sdk-node
npm i @clerk/clerk-sdk-node@4.10.4-snap.5909c28
# @clerk/shared
npm i @clerk/shared@0.17.2
# @clerk/themes
npm i @clerk/themes@1.7.5
# @clerk/types
npm i @clerk/types@3.41.0

This commit introduces a new apiRoutes param on authMiddleware.

If apiRoutes is omitted, then a default heuristic is the following:
If the route path is ['/api/(.*)', '/trpc/(.*)'] or Request has Content-Type: application/json or
Request method is not-GET,OPTIONS,HEAD ,
then this is considered an API route.
@anagstef anagstef force-pushed the stefanos/js-411-api-endpoints-protected-by-authmiddleware-should-return-401 branch from 5909c28 to fd6906e Compare June 7, 2023 09:19
@anagstef anagstef force-pushed the stefanos/js-411-api-endpoints-protected-by-authmiddleware-should-return-401 branch from 0641a7c to 4fa3945 Compare June 7, 2023 13:03
packages/nextjs/src/server/authMiddleware.ts Outdated Show resolved Hide resolved
packages/nextjs/src/server/authMiddleware.ts Outdated Show resolved Hide resolved
@@ -40,7 +40,7 @@ export const authenticateRequest = async (req: NextRequest, opts: WithAuthOption
};

export const handleUnknownState = (requestState: RequestState) => {
const response = new NextResponse(null, { status: 401, headers: { 'Content-Type': 'text/html' } });
const response = apiEndpointUnauthorizedNextResponse();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dimkl Is there any way we can get to a UnknownState from a browser?

@anagstef I'd just replace the helper with:

NextResponse.json(null, { status: 401, statusText: 'Unauthorized' });

do we need the payload?

Copy link
Member Author

@anagstef anagstef Jun 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nikosdouvlis The Unknown state is only returned when a request uses the Authorization header. So, if we append the Authorization header in a fetch request, we can get the Unknown state, which is not a case where we would want the Interstitial. (cc @dimkl)

I removed the payload.

@nikosdouvlis nikosdouvlis merged commit 78c31df into main Jun 7, 2023
@nikosdouvlis nikosdouvlis deleted the stefanos/js-411-api-endpoints-protected-by-authmiddleware-should-return-401 branch June 7, 2023 18:48
@github-actions github-actions bot mentioned this pull request Jun 7, 2023
@clerk-cookie clerk-cookie mentioned this pull request Jun 9, 2023
@clerk-cookie
Copy link
Collaborator

This PR has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@clerk clerk locked as resolved and limited conversation to collaborators Jun 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants