惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Full Disclosure
博客园 - 三生石上(FineUI控件)
MyScale Blog
MyScale Blog
Apple Machine Learning Research
Apple Machine Learning Research
L
LINUX DO - 最新话题
T
The Blog of Author Tim Ferriss
P
Proofpoint News Feed
宝玉的分享
宝玉的分享
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
GbyAI
GbyAI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
Visual Studio Blog
爱范儿
爱范儿
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园_首页
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
月光博客
月光博客
博客园 - 叶小钗
D
Docker
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Tailwind CSS Blog
D
DataBreaches.Net
酷 壳 – CoolShell
酷 壳 – CoolShell
B
Blog RSS Feed
量子位
美团技术团队
Vercel News
Vercel News
Y
Y Combinator Blog
IT之家
IT之家
Martin Fowler
Martin Fowler
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
SegmentFault 最新的问题
腾讯CDC
Recent Announcements
Recent Announcements
Google DeepMind News
Google DeepMind News
罗磊的独立博客
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
G
Google Developers Blog
Microsoft Azure Blog
Microsoft Azure Blog
The Register - Security
The Register - Security
博客园 - 司徒正美
N
Netflix TechBlog - Medium
S
Schneier on Security
博客园 - 聂微东
U
Unit 42
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
雷峰网
雷峰网
Latest news
Latest news

Clerk Blog

Going to production with Clerk Deploy Clerk Init: The fastest way to start a new project Introducing Clerk CLI Middleware-based route protection bypass Postmortem: Clerk System Outage (March 10, 2026) Clerk for the AI era Add API Key support to your SaaS in minutes Postmortem: Clerk System Outage (February 19, 2026) Using Clerk in a React Native app Postmortem: DNS Provider Outage (February 10, 2026) How do I implement passkeys in Next.js? Clerk ranked #4 fastest-growing software vendor on Ramp’s December 2025 list How do I handle JWT verification in Next.js? Committing to Agent Identity: Clerk raises $50m Series C from Menlo and Anthropic’s Anthology Fund What is the best way to handle authentication in Next.js App Router? Postmortem: Database Incident (September 14–18, 2025) How do I add authentication to a Next.js app? Introducing Free Trials in Clerk Billing Postmortem: August 28, 2025 - elevated API latency and errors Introducing Mosaic: Bring Your Brand to Every Authentication Flow Multi-tenant authentication: What you need to know (and how Clerk helps) What are the risks and challenges of multi-tenancy? Resilience in Practice: Regional Failover at Clerk Build a Cross-Platform B2B App with Clerk, Expo, and Supabase Highlights from the MiduDev/Clerk Hackathon Add multi-tenancy to an app built with Clerk, Lovable, and Supabase How to build an AI coding rules app with Clerk, Lovable, and Supabase How to Build Multi-Tenant Authentication with Clerk Choosing the right SaaS architecture: Multi-Tenant vs. Single-Tenant Postmortem: June 26, 2025 service outage How to Design a Multi-Tenant SaaS Architecture What is multi-tenancy and why it matters for B2B SaaS How OAuth Works Synchronize user data from Clerk to Supabase Add subscriptions to your SaaS with Clerk Billing Getting started with Clerk Billing Multi-tenant analytics with Tinybird and Clerk How Huntr Migrated 250K Users to Clerk: A Scalable Auth Solution for Startups How to take Clerk to Production How to take your Clerk application to production A practical guide to testing Clerk Next.js applications Implementing multi-tenancy into a Supabase app with Clerk How Clerk integrates with a Next.js application using Supabase How Clerk integrates with Supabase Build a blog with tRPC, Prisma, Next.js and Clerk How to enrich PostHog events with Clerk user data How to build a secure project management platform with Next.js, Clerk, and Neon Validate your SaaS idea while building an audience Postmortem: February 6, 2025 service outage Implement Role-Based Access Control in Next.js 15 Build a Next.js sign-up form with React Hook Form Build a Next.js login page template How to implement Google authentication in Next.js 15 What is middleware in Next.js? How to customize Next.js metadata How to set environment variables in Node.js Building a React Login Page Template How to implement per-user OAuth scopes with Clerk Using Clerk SSO to access Google Calendar and other service data Streamline enterprise customer onboarding with SAML and Clerk Clerk launches EASIE SSO and eliminates SSO fees How to secure Liveblocks Rooms with Clerk in Next.js Securing Node.js Express APIs with Clerk and React Combining the benefits of session tokens and JWTs Build a task manager with Next.js, Supabase, and Clerk Comparing Clerk Webhooks vs Backend API Automate Neon schema changes with Drizzle and GitHub Actions A guide to reading authenticated user data from Clerk Role based access control with Clerk Organizations Mitigating OAuth’s recently discovered Open Response Type vulnerability Per-user B2B monetization with Stripe and Clerk Organizations Build a team-based task manager with Next.js, Neon, and Clerk Building a Hybrid Sign-Up/Subscribe Form with Stripe Elements Welcoming Colin from Zod as our inaugural Open Source Fellow Build a modern authenticated chat application with Next.js, Ably, and Clerk Build a waitlist with Clerk user metadata How to use Clerk with PostHog Identify in Next.js How to secure API Gateway using JWT and Lambda Authorizers with Clerk What are passkeys and how do they work? Comparing Authentication in React.js vs. Next.js How to Add an Onboarding Flow for your Application with Clerk Create Your Own Custom User Menu with Radix - Part 2 Introducing Webhook Workflows with Inngest & Svix Clerk raises $30M Series B from CRV and Stripe Clerk in 2023: A Year in Review Build a Movie Emoji Quiz App with Remix, Fauna, and Clerk Ultimate Guide to Magic Link Authentication Create Your Own Custom User Menu with Radix Introducing has(), protect(), and <Protect> Updated Pricing: 10,000 MAUs Free, and a new “Pro Plan” Next.js Authentication with Clerk: Streamlined SSR Handling Clerk Webhooks: Data Sync with Convex Exploring Clerk Metadata with Stripe Webhooks The Ultimate Guide to Next.js Authentication Empower Your Support Team With User Impersonation Clerk Webhooks: Getting Started A Complete Guide to Session Management in Next.js The Advanced Guide to Passwordless Authentication in Next.js How We Roll – Chapter 10: Roundup How We Roll – Chapter 9: Infrastructure
How to Authenticate API Requests with Clerk & Express
Nick Parsons · 2023-06-17 · via Clerk Blog

APIs are essential for building powerful applications that can communicate and share data with other systems.

However, with great power comes great responsibility: it's critical to ensure that only authorized users can access your API, and that requests are properly authenticated and verified. Failure to do so can lead to serious security breaches, data leaks, and other vulnerabilities that can compromise the integrity of your application and put your users at risk.

In this tutorial, we'll explore how to use Clerk with Express to authenticate API requests using ClerkExpressWithAuth() and ClerkExpressRequireAuth() middleware, and build a secure and robust backend for your application. Let's get started!

Always authenticate

When developing an API, especially in Express.js or any other framework, it's important to authenticate requests for a number of reasons:

  1. Security: The most important reason is to maintain the security of your application. By authenticating API requests, you ensure that only authorized clients or users can interact with your API. This reduces the potential for malicious actions such as data theft, unauthorized modification, or even denial of service attacks.
  2. Access Control: It allows you to control who can access certain resources and operations in your API. For instance, certain resources might only be available to admin users, while others are available to all authenticated users.
  3. Rate Limiting: When you authenticate a user, you can associate them with a specific usage quota. This can be used to implement rate limiting, preventing any single user from overloading the server with requests.
  4. Data Accuracy: In many cases, your API's operations will be tied to a specific user's data. For example, a "get user profile" endpoint would need to know which user's profile to retrieve. Authentication provides a way to associate requests with users.
  5. Audit and Logs: It allows you to keep track of who did what and when. This is very useful when you need to audit the usage of your system.

Implementing express authentication or Node.js authentication is vital for maintaining the integrity, security, and reliable operation of your APIs.

That being said, there might be some API routes that you intentionally leave unauthenticated for various reasons. For instance, a login or registration route needs to be unauthenticated so that users can authenticate or create an account. Similarly, you might provide some public data through your API that doesn't require authentication.

But you should default to authentication. Consider it a component of building as you plan out epics or sprints on APIs. But adding auth doesn’t have to be particularly challenging. You can build this out yourself with middleware functions, but like a lot of elements in authentication, it’s better to use specialized components.

Let’s go through two of these we have at Clerk, ClerkExpressWithAuth() and ClerkExpressRequireAuth() to see how we can set these up Express authentication and call these endpoints from a client.

You can check out all the code for this tutorial in this repo.

Authenticating Express API endpoints with Clerk

Before we get to the Clerk specifics, it’s good to define two components of API methods in Express (and elsewhere) that are fundamental concepts to how authentication will work: callbacks and middleware.

A callback function is a function that is passed to another function as a parameter and then invoked by that function at a later time. Callbacks are heavily used in Node.js because it's designed to be asynchronous and non-blocking. When performing I/O operations like making HTTP requests, Node.js can start the operation and then continue executing other code without waiting for the operation to complete. When the operation is complete, the callback function is called with the result.

Middleware functions are functions that have access to the request object (req), the response object (res), and the next middleware function in the application’s request-response cycle. Middleware functions can perform tasks like modifying the request or response objects, ending the request-response cycle, or invoking the next middleware function in the stack.

In Express, middleware functions are often used as callbacks to handle HTTP requests. When you define a route in Express.js, you provide a callback function that's called whenever a client makes a request to that route. This callback function is also a middleware, because it has access to the req, res, and next objects.

So, in this sense, middleware functions are a specific type of callback. They're callbacks that are designed to be used in the context of an HTTP request to an Express.js server.

This is what we’re going to do with Clerk. We’re going to use one of two authentication middleware functions as a callback for the request to our API endpoint. Those two middleware functions are:

  1. ClerkExpressWithAuth() is a lax authentication middleware that returns an empty auth object when an unauthenticated request is made.
  2. ClerkExpressRequireAuth() is a strict authentication middleware that raises an error when an unauthenticated request is made.

There are subtle but important differences between these two. Let’s go through them.

Using ClerkExpressWithAuth()

ClerkExpressWithAuth() is lax in that when it fails, it still returns an object, not an error.

Let’s get some code up and running to showcase this function. We’ll create a directory called ‘backend’ and make that the current directory:

With that done, we’ll start installing our dependencies for this code. If you don’t already have it, you’ll also need node as this is the runtime we’re building upon. You can grab the latest build from here.

Then you can run npm init to create a package.json in that directory. With that we can use npm to install:

  • Express, which is the web framework for Node.js we’re going to use. Express is a great option for running node servers because it’s fast, minimal, and unopinionated.
  • dotenv, which is the node package you need to read environmental variables in node.
  • @clerk/clerk-sdk-node is the Node.js SDK for the Clerk user management platform.
  • cors allows us to easily call the endpoint from a client

When they are installed, create a file in your with-auth directory called app.js:

Then create a .env file in the same directory:

This is where you’re going to store your CLERK_API_KEY. You can find this in your dashboard. Because you are building these routes on the backend, you can use your secret key:

Clerk Secret Key

Then open this directory with your IDE. If you are using VS Code, you can just type code . and you’ll get a window ready in that directory.

Add your secret key to your .env file after CLERK_API_KEY=key-goes-here. Add the following code to app.js:

Let’s work through this line by line.

  • Firstly we have all our imports:
    • import "dotenv/config" imports the "dotenv" package and automatically runs its config function. This package reads environmental variables from the .env file and adds them to process.env. Here we need it to access a CLERK_API_KEY environment variable.
    • We import ClerkExpressWithAuth from the "@clerk/clerk-sdk-node" package. This function is middleware for Express.js that handles authentication with Clerk.
    • We import express from the Express.js package
    • import cors from "cors" imports the "cors" package, a package used for enabling Cross Origin Resource Sharing (CORS). We’ll need this to aid calling the endpoint from our client.
  • We then set a constant port to the value of the PORT environment variable if it's set, otherwise it defaults to 3000.
  • const app = express() creates a new Express application. The application is what is going to run our server.
  • app.use(cors()) adds the CORS middleware to the Express application, enabling CORS.
  • app.get(…) defines a route for the path "/protected-endpoint" on the Express app. This route has two middleware functions:
    • ClerkExpressWithAuth: This is the function that checks the authorization of the incoming request. If the request is authenticated, it sets req.auth to an object representing the authenticated user.
    • (req, res) => { res.json(req.auth); console.log(res.json); }: This is an anonymous function that takes the incoming request and outgoing response as arguments. It sends a JSON response with the auth object from the request, and then it logs the JSON response function to the console.
  • The final app.listen(…) part of the code starts the server and makes it listen for incoming connections on the specified port. It logs a message to the console indicating that the server is running and listening on that port.

Let’s run this:

You should now see that message from in your app.listen(…) terminal:

Great! You have a working endpoint. Let’s call that endpoint (http://localhost:3000/protected-endpoint) from Postman to see what it returns:

As we said above, ClerkExpressWithAuth() returns “an empty auth object when unauthenticated.” Now, you have a conundrum—you need an authenticated user to check this really works. To do that, we’ll create a quick React frontend client that calls /protected-endpoint after authenticating a user.

Keep that app running and open up another terminal. If it opens up in the same directory, make sure you cd .. up a level (you don’t want to create your frontend React app in a subdirectory of your backend—headaches will ensue).

We’ll first install create-react-app to help us (funnily enough) create a react app:

Then run npx create-react-app my-app where my-app is the name of your app. Here we’ll go with auth-frontend:

Then we’ll cd frontend to get into that directory and open with our IDE (again using code . if using VS Code).

Again, we’re going to add Clerk to this project, this time using@clerk/clerk-react, which is the Clerk React SDK.

We’ll also want to install isomorphic-fetch and es6-promise to polyfill the Fetch API for browsers that don't support it:

Like with the backend, you are going to need your Clerk API key. This time though you are going to use your public key as we’re authorizing a frontend client:

Clerk Publishable Key

Create a .env file and then add that key to it like this: REACT_APP_CLERK_PUBLISHABLE_KEY=key-goes-here.

Now go to the src/App.js file, remove the boilerplate entirely and add this code:

We won’t go through this line by line because we’ve taken it entirely, with one exception, from our docs on getting started with React. Head there to learn more about Clerk and React.

That one exception is that we’ve swapped out the <Welcome /> component in the documentation within the <SignedIn></SignedIn> component for an <Auth /> component. Within the src directory add auth.js and add this code:

We will go through this line by line as it shows how you can pass that authentication token to the API endpoint.

  • import fetch from "isomorphic-fetch" imports the fetch function from the isomorphic-fetch package.
  • The next line imports the React default export and the useState and useEffect named exports from the react package. useState is a React Hook that lets you add React state to function components, and useEffect lets you perform side effects in function components.
  • The final import is for the useAuth hook from the @clerk/clerk-react package. This hook provides access to Clerk's auth-related functionality.
  • The Auth function component is then declared. Four pieces of state are created using the useState hook: data, loading, and error for storing API response data, the loading state, and any error messages, respectively. The getToken function is extracted from the useAuth hook to allow authentication token retrieval.
  • We then create a useEffect hook to define a side effect that fetches data from an API when the component is first mounted and whenever the getToken function changes.
  • Within the useEffect hook, the fetchData function tries to retrieve a token, then sends a GET request to our /protected-endpoint. If the request fails, it sets the error state and stops loading. If it succeeds, it sets the data state to the response data, and stops loading.
    • The critical part of this is the line Authorization: Bearer ${token}. Here, we’re passing the authorization token from our now-signed-in-user to our /protected-endpoint to use in its own authentication.
  • In the rendering part of the Auth component, it checks if the loading state is true, and if so, returns a "Loading..." message. If there's an error, it displays the error message. Otherwise, it displays the data fetched from /protected-endpoint.
  • Finally we export the Auth component as the default export of this module. This allows the Auth component to be imported and used in other parts of the application.

And thus we import that Auth and call it within the SignedIn function so we can use the authorization token and pass it to /protected-endpoint. Within /protected-endpoint, the ClerkExpressWithAuth middleware will check whether it is a valid token, and, if so, return a full auth object:

Now, on the backend we have our sessionId and userId and claims to use as needed and we know our user is authenticated and allowed to use this API endpoint!

Using ClerkExpressRequireAuth()

ClerkExpressRequireAuth works slightly different when a user is unauthenticated. Whereas ClerkExpressWithAuth just returned an empty auth object, ClerkExpressRequireAuth returns an error.

Swap out your code in your express app.js for this below:

Most of this code is the same as the ClerkExpressWithAuth example above. The differences are:

  • We’re importing the ClerkExpressRequireAuth from the Clerk Node.js SDK
  • We’re calling that ClerkExpressRequireAuth middleware within our app.get() function.
  • We now have an error-handling middleware function. If an error occurs in any middleware function that is run before this one (here the ClerkExpressRequireAuth), this function will be called. It logs the stack trace of the error and sends a response with the HTTP status code 401, indicating that the client must authenticate to get the requested response, along with the message Unauthenticated!.

And lo and behold, if you call this in Postman you’ll get a 401 and this message:

This is safer as we aren’t even sharing the structure of our auth object.

If we now call this within our React app though, we do get our auth object because we are authenticated:

And with that, you can now authenticate any API endpoint in your Express apps.

Fast, authenticated endpoints

With Express and Clerk you can get authenticated, production-ready APIs up in a matter of just a few minutes. There is more code in our client that for our endpoint. Using ClerkExpressWithAuth() or ClerkExpressRequireAuth() you can protect any endpoint and add express authentication or node authentication without the hassle of building it yourself.

This is what you need with authentication—you want it done quickly. That way it’ll actually get done rather than sitting in your backlog queue for months until a dev can get to it. Or an attacker can get to your unprotected endpoints.

Next steps? Check out the code for this tutorial here. Check out Clerk here and more about using Clerk for express and node authentication here, and how to take these security elements even further with the options. Learn how to set up Clerk within your client to make user management super simple here.