Kinde in Cloudflare Pages Function Middleware
I'm using a Cloudflare Pages Function as a middleware to check user authentication before loading any site assets. Using Clerk as an example, it looks kinda like this:
const clerkClient = createClerkClient({secretKey, publishableKey});
const {isSignedIn} = await clerkClient.authenticateRequest(context.request, {jwtKey});
if (!isSignedIn) // ...redirect to auth provider
However, I'm unable to figure out how to do something similar with Kinde. The Kinde node libraries don't work because the Function environment doesn't allow the necessary libraries. I found this post which offers a solution for this, https://kinde.com/blog/engineering/verifying-jwts-in-cloudflare-workers/, but Kinde doesn't pass an authorization or cookie in the request even when I'm signed in, so there is nothing to verify. Is this just because I'm not using a custom domain in Kinde? I'm confused because the underlying React app recognizes me as being signed in, so there must be some mechanism to authenticate the user. For clarity, I also don't have a custom domain in Clerk, but maybe they set cookies by default, I'm not sure.6 Replies
Hi, thanks for your detailed message — you’re exactly right to notice the difference in behavior compared to Clerk, and you’re on the right track.
The key reason you’re not seeing an authorization header or cookie in the request is due to how Kinde handles token storage by default. To protect against CSRF and XSS attacks, Kinde stores tokens in memory, not in cookies or headers:
🔗 Token handling in Kinde React SDK Because of this, middleware (like your Cloudflare Pages Function) won’t see tokens by default. Here are a few ways to address this: ✅ Recommended: Use Kinde Custom Domains Setting up a custom domain allows Kinde to store a secure, httpOnly refresh token in a first-party cookie. This enables your middleware to access the token and verify it. ⚠ For Local Development Only You can use
🔗 Token handling in Kinde React SDK Because of this, middleware (like your Cloudflare Pages Function) won’t see tokens by default. Here are a few ways to address this: ✅ Recommended: Use Kinde Custom Domains Setting up a custom domain allows Kinde to store a secure, httpOnly refresh token in a first-party cookie. This enables your middleware to access the token and verify it. ⚠ For Local Development Only You can use
useInsecureForRefreshToken
in the Kinde React SDK to store the refresh token in localStorage:
This is not recommended for production environments, but can help with local testing.
🔐 JWT Verification in Cloudflare Workers
Once you’re receiving the token (e.g., via custom domain cookies or an Authorization
header you manually attach), you can verify it in a Cloudflare Worker using a library like cloudflare-worker-jwt
or jose
:
Your Kinde JWKS endpoint is:https://<YOUR_DOMAIN>.kinde.com/.well-known/jwks
Let me know if you’d like help setting up the custom domain or verifying tokens in your worker. Happy to walk through it together!Thanks for your reply, that explains things. I'll set up a custom domain then. I don't need help with verifying the token, but I am wondering about redirecting from the CF Function if the token is not valid. With Clerk, I can simply redirect to
https://<clerk-ui-domain>/sign-in
. But Kinde doesn't seem to have a simple sign-in route, and since I can't use the SDK, it looks like I have to redirect to:
https://<your_kinde_subdomain>.kinde.com/oauth2/auth
?response_type=code
&client_id=<your_kinde_client_id>
&redirect_uri=<your_app_redirect_url>
&scope=openid%20profile%20email
&state=abc
Is my understanding correct or is there a simpler URL?
Basically I just want to direct the user to the same page as when using the login
method of the SDKs. Is there a way to do that within a Cloudflare Pages Function without reimplementing the login
function internals?Hi,
Yes, you're absolutely right — since you're not using the SDK, you'll need to manually redirect users to the Kinde authorization URL from your Cloudflare Pages Function when the token is invalid.
You can use a redirect like this:
Just replace the placeholder values with your actual Kinde credentials and redirect URI. You can also optionally include the
prompt
parameter if you want to explicitly trigger a login or signup screen: 👉 Using Kinde without an SDK
This approach effectively replicates the behaviour of the SDK’s login method — so yes, your understanding is spot on.
Let me know how it goes, or if it helps or not!Kinde docs
Using Kinde without an SDK
Our developer tools provide everything you need to get started with Kinde.
Thanks for the confirmation. So replacing the values with my own doesn't work, that URL gives me the following error:
Something went wrong when we tried to authenticate you, and we can’t offer a quick way out. Start a new session and try signing in again. Error code: 1656
But additionally adding the code_challenge
and code_challenge_method
parameters seems to work, at least the URL directs me to the sign-in page. I really wish there was an easier to get there, as in Clerk - like why do I need to specify the redirect_uri? It should be optional and Kinde should default to the homepage callback URL specified in the app. On that note, is there a suggested way of generating the state
parameter? I don't really care about it for this middleware functionality, but the URL doesn't work without it.Thanks for sharing those details — and great to hear that adding
code_challenge
and code_challenge_method
helped move things forward.
While those parameters are required by spec and important for security and proper redirection, I’ve raised your feedback internally so the team is aware of the experience from your side.
Let me know if you need help with anything else in the meantime!Okay so I've added and verified a custom domain, and I can see the cookies set in the browser, but your suggestion still doesn't work. In the request coming to the CF Pages Function middleware, the "Authorization" header is still null. And the cookies still don't seem to be passed correctly, at least there's no token cookie present in the request.
I realized you said "via custom domain cookies or
Authorization
header you manually attach" - I can't manually attach anything, it's a middleware managed by CF that is automatically executed for every request going to the site. Can you please verify your solution?