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

推荐订阅源

博客园_首页
阮一峰的网络日志
阮一峰的网络日志
S
Secure Thoughts
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Threat Research - Cisco Blogs
P
Privacy & Cybersecurity Law Blog
The Hacker News
The Hacker News
H
Heimdal Security Blog
W
WeLiveSecurity
L
LINUX DO - 热门话题
Hacker News: Ask HN
Hacker News: Ask HN
WordPress大学
WordPress大学
The Last Watchdog
The Last Watchdog
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
D
DataBreaches.Net
I
Intezer
Webroot Blog
Webroot Blog
C
Cisco Blogs
AWS News Blog
AWS News Blog
博客园 - 聂微东
T
The Blog of Author Tim Ferriss
V
Vulnerabilities – Threatpost
罗磊的独立博客
Google DeepMind News
Google DeepMind News
N
Netflix TechBlog - Medium
Schneier on Security
Schneier on Security
宝玉的分享
宝玉的分享
博客园 - 叶小钗
PCI Perspectives
PCI Perspectives
D
Docker
Scott Helme
Scott Helme
NISL@THU
NISL@THU
J
Java Code Geeks
B
Blog RSS Feed
Google Online Security Blog
Google Online Security Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
The Exploit Database - CXSecurity.com
AI
AI
美团技术团队
Cloudbric
Cloudbric
月光博客
月光博客
P
Proofpoint News Feed
T
Tailwind CSS Blog
Google DeepMind News
Google DeepMind News
小众软件
小众软件
www.infosecurity-magazine.com
www.infosecurity-magazine.com
The Cloudflare Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org

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
Clerk and Create T3 Turbo
James Perkins · 2022-12-28 · via Clerk Blog

T3-Turbo is one of the easiest ways to get both Type safety while using Next.js and Expo. The biggest missing feature is the ability to share authentication between your applications.

This guide shows you how to integrate Clerk into T3-Turbo so you can have user management for everyone.

Assumptions

There are a few assumptions here when working through this guide.

  • You understand TRPC and its functionality.
  • You are familiar with Expo.
  • You have a working knowledge of Turborepo

Setup

Create your free Clerk account

You need a free Clerk account to use everything in this guide, so head to https://dashboard.clerk.com and sign up for your free account.

Create a new application in the dashboard

You will need to create a new application, name it and select Discord as a social sign-in.

Clerk T3 Turbo guide illustration

Clerk T3 Turbo guide illustration

Update .env to use your keys

Under the dashboard, you will need your API keys and create a copy of the .env.example as .env

Clerk T3 Turbo guide illustration

Adding global env to Turbo

We want to have our env available in many parts of our application. You can add the following to our turbo.json .

Update Next.js package.json

We need to be able to access the .env when working in development, so replace the dev script with the following:

Updating our Next.js application

First, we will work on our Next.js application, whose only change is adding Clerk, so we have powerful user authentication.

Install

Now that the Clerk package has been installed in our Next.js application, we need to wrap our application in the <ClerkProvider>, which gives us access to the authentication state throughout our application.

Open up your _app.tsx file and modify the code.

Add Middleware.ts

Clerk uses Next.js middleware to allow your application to keep track of authentication behind the scenes.

You will notice the matcher at the bottom, which ensures that middleware doesn’t run on every request. This will scope it to TRPC + API routes leaving your images and static files alone.

Embedding our UI components

Clerk provides highly customizable components from Sign-up to Organization management. They require zero form creation or state management, making them easy to implement. Each component will use the Next.js optional catch all route. This allows you to redirect the user inside your application using OAuth providers.

Sign in

Sign up

Updating index.tsx

The final step for Next.js is to update our index.tsx to use Clerk. Once we update this page, users will have a way to sign in, sign out and see data from TRPC in the future.

We need to import a prebuilt component from Clerk and a hook that allow us to access the current auth state.

import { useAuth, UserButton } from "@clerk/nextjs";

What is useAuth?

The useAuth hook is a convenient way to access the current auth state. This hook provides the minimal information needed for data-loading, such as the user id and helper methods to manage the current active session.

What is UserButton?

Initially popularized by Google, users have come to expect that little photo of themselves in the top-right of the page – it’s the access point to manage their account, switch accounts, or sign out.

The <UserButton/> component renders this familiar user button UI. It renders a clickable user avatar - when clicked, the full UI opens as a popup. Here is an example

Clerk T3 Turbo guide illustration

Updating AuthShowcase

The AuthShowCase component in the index.tsx file needs to be updated to use the useAuth() hook, allow the user to sign in, and show our UserButton if the user is signed in.

Now we can update our secret message from { enabled: !!session?.user } to { enabled: isSignedIn }

Now the final change is to use isSignedIn in our return statement to conditionally show the secret message and UserButton component or show a sign-in link. We can do that by replacing {session?.user && ( with isSignedIn and underneath, providing the false statement using !isSignedIn this is where we can place a Link to our mounted /sign-in page.

The UserButton component allows users to manage their accounts, including signing out or updating their profile and password or linking a new account through OAuth providers. I added some customization to make the UserButton larger.

The final step is to add a login text that pushes the user to the mounted sign-in page.

Below is the final AuthShowcase.

Now that the Next.js work is done, we should update our TRPC API to use Clerk instead of NextAuth, so we can test this work and get ready to update Expo.

Updating API package to use Clerk

Currently, the API package has TRPC context, and middleware uses Auth.js (previously NextAuth). We can replace this with Clerk so we can use it both with Expo and Next.js.

Updating TRPC context

The context is found at packages/api/src/context.ts. In this package, we will add the ability to detect the user being signed in and retrieve the full User object. First, we must remove the auth package import and add getAuth , clerkClient, SignedInAuthObject and SignedOutAuthObject as a type.

What is getAuth ?

The getAuth() helper retrieves the authentication state and can be used anywhere within a next.js server. It provides information needed for data-loading, such as the user id and can be used to protect your API routes.

Updating createContext function

For the createContext function, we want to pass around the user object anywhere in our application. For this, we can create an async function called getUser that retrieves the userId and subsequently retrieves the user data.

Now we can retrieve a user, and if not, we will return null we can pass this to our createContextInner in case you need it for testing without a request object.

Updating TRPC middleware

The TRPC middleware found in /packages/api/src/trpc.ts needs a small update to the isAuthed function. The if statement becomes !ctx.auth.userId, and the return becomes auth: ctx.auth

Our Next.js application can be tested with TRPC, including the secret message that uses protected routes. Give it a test.

Updating our Expo application

The Expo application currently doesn’t support authentication; the good news is Clerk supports Expo with our @clerk/expo package.

Install @clerk/expo package and secure-store

pnpm install @clerk/clerk-expo expo-secure-store --filter @acme/expo

Create a Token Cache

We need a token cache here, which is why we installed expo-secure-store that allows you to store key pair values on the device. Create a new file under /src/utils/ named cache.ts and paste in the following code:

I won’t explain this code above as it’s an expo-specific package, but this allows us to store the JWT securely and not in memory.

Add <ClerkProvider>

Similar to our Next.js application, we need to wrap up our _app.tsx in the <ClerkProvider> to allow access to auth state anywhere in the application. What is different here is we need use our newly created TokenCache, and we need to provide the Clerk frontend API directly to the <ClerkProvider />

Protecting pages

Our Expo package provides an easy way to gate content using SignedIn and SignedOut, which will gate the content depending on the user's current state.

Implementing a way to sign in.

With Clerk Expo, you must implement your pages to sign in or sign up as a user. We will use Discord, but you can use any social or standard sign-in you want. First, we need to install expo-auth-session to handle sessions.

pnpm install expo-auth-sessions --filter @acme/expo

Creating a Sign In component

Create a folder called components and then create a file called SignInWithOAuth.tsx. This will be our component that you can easily extend to use more providers or swap out Discord for something else.

Here we are using another helper, which allows you to sign in as a user and set the session after the fact. We need to make sure Clerk is fully loaded before we attempt a sign in so we can use the isLoaded as part of the useSignIn helper.

Now we need to create our function that will run when a user taps the button to sign in:

Next we need to tell where to redirect to after a successful or unsuccessful login attempt via Discord,expo-auth-session provides a helper to make a redirect, which is called makeRedirectUri, and set it to /oauth-native-callback

At this point, we can start our sign in attempt using signIn.create passing in our strategy, which is oauth_discord, and our newly created redirectUrl

The SignIn object holds all the state of the current sign in and provides helper methods to navigate and complete the sign in process. You can read about this in our documentation, as you may want to use the different sign in methods in the future.

The next part of the sign in is to retrieve the external redirect URL and use AuthSession. This will give us the ability to know if the OAuth was successful or not.

You may notice that we have an eslint to disable the checks on the next line. There is an assumption in this example that it will always be successful, but you can use the following AuthSession documentation to implement anything you may want to handle.

We now need to retrieve rotatingTokenNonce and reload our signIn object. This will allow us to get the sessionId and sign the user in.

Finally we can retrieve the createdSessionId from the signIn object and set that to our current session. This will let us know that the user is signed in with a valid session.

Finally we can add a catch for anything that might go wrong that we aren’t handling and return the error.

Our sign in method is now complete, so we can create a simple UI that, on touch, will attempt a sign in.

Our Sign In component is now complete below is the full code. We will use this for a Sign Up component for anyone who doesn’t have an account yet for our application.

Create a Sign Up component

The good news is that the sign in component and the sign up component is very similar and 99% of the code we created can be reused and swapped for useSignUp hook. To save you from reading more content, here is the code.

Creating a Sign in, Sign Up screen

We now need to use our components in our application. Under the screens folder, create a new file called signInSignUp.tsx and paste the following code. We are displaying the components we created so the code below is generic React Native code.

Updating _app.tsx

We can now update our SignedOut control component to use the SignInSignUpScreen so if a user doesn’t have a valid session and is not signed in, they will be able to sign in.

Updating TRPC client

The TRPC client found under utils/trpc needs a very small update. As part of TRPC, you can provide headers as part of httpBatchLink . We can get the JWT token by using getToken, which is part of the useAuth hook.

First, add the import import { useAuth } from "@clerk/clerk-expo"; , then, inside our TRPCProvider, add the getToken code before the client.

Then finally, add the Authorization header to our httpBatchLink

This will allow you to send a valid token with your requests to the TRPC backend. Below is the full code:

Final Updates to our TRPC API

The final update here is to update the post router to use a protectedProcedure for creation so that when a user uses the Expo application, they will need to be logged in to create a new post. Open the post.ts under /packages/api/src/router and update the create to use protectedProcedure .

Next Steps

Now you have a working T3 Turbo application that has authentication both in Next.js and Expo with protected routes. Here are some next steps you might want to implement:

  • Additional login methods for Expo ( more social logins or email and password screen)
  • Use one of our integrations to use a database, such as Neon, Supabase, or Firebase.
  • Join our Discord