Apr 07, 2023
James Perkins
Expo 48 support, Improving our components, Runtime keys for Next.js...
This week, the team has been improving the DX of Clerk and introducing some important features.
Clerk now has full support for Expo 48 with this change we introduced a brand new hook called useOAuth
this hook dramatically improves the developer experience. Here are two examples of the code to handle Discord OAuth, both handle account transfers.
1import { useSignUp, useSignIn } from "@clerk/clerk-expo";2import React from "react";3import { Button, View } from "react-native";45import * as AuthSession from "expo-auth-session";67const SignInWithOAuth = () => {8const { isLoaded, signIn, setSession } = useSignIn();9const { signUp } = useSignUp();10if (!isLoaded) return null;1112const handleSignInWithDiscordPress = async () => {13try {14const redirectUrl = AuthSession.makeRedirectUri({15path: "/oauth-native-callback",16});1718await signIn.create({19strategy: "oauth_discord",20redirectUrl,21});2223const {24firstFactorVerification: { externalVerificationRedirectURL },25} = signIn;2627if (!externalVerificationRedirectURL)28throw "Something went wrong during the OAuth flow. Try again.";2930const authResult = await AuthSession.startAsync({31authUrl: externalVerificationRedirectURL.toString(),32returnUrl: redirectUrl,33});3435if (authResult.type !== "success") {36throw "Something went wrong during the OAuth flow. Try again.";37}3839// Get the rotatingTokenNonce from the redirect URL parameters40const { rotating_token_nonce: rotatingTokenNonce } = authResult.params;4142await signIn.reload({ rotatingTokenNonce });4344const { createdSessionId } = signIn;4546if (createdSessionId) {47// If we have a createdSessionId, then auth was successful48await setSession(createdSessionId);49} else {50// If we have no createdSessionId, then this is a first time sign-in, so51// we should process this as a signUp instead52// Throw if we're not in the right state for creating a new user53if (54!signUp ||55signIn.firstFactorVerification.status !== "transferable"56) {57throw "Something went wrong during the Sign up OAuth flow. Please ensure that all sign up requirements are met.";58}5960console.log(61"Didn't have an account transferring, following through with new account sign up",62);6364// Create user65await signUp.create({ transfer: true });66await signUp.reload({67rotatingTokenNonce: authResult.params.rotating_token_nonce,68});69await setSession(signUp.createdSessionId);70}71} catch (err) {72console.log(JSON.stringify(err, null, 2));73console.log("error signing in", err);74}75};7677return (78<View className="rounded-lg border-2 border-gray-500 p-4">79<Button80title="Sign in with Discord"81onPress={handleSignInWithDiscordPress}82/>83</View>84);85};8687export default SignInWithOAuth;
1import { useOAuth } from "@clerk/clerk-expo";2import React from "react";3import { Button, View } from "react-native";4import { useWarmUpBrowser } from "../hooks/useWarmUpBrowser";56const SignInWithOAuth = () => {7useWarmUpBrowser();89const { startOAuthFlow } = useOAuth({ strategy: "oauth_discord" });1011const handleSignInWithDiscordPress = React.useCallback(async () => {12try {13const { createdSessionId, signIn, signUp, setActive } =14await startOAuthFlow();15if (createdSessionId) {16setActive({ session: createdSessionId });17} else {18// Modify this code to use signIn or signUp to set this missing requirements you set in your dashboard.19throw new Error("There are unmet requirements, modifiy this else to handle them")2021}22} catch (err) {23console.log(JSON.stringify(err, null, 2));24console.log("error signing in", err);25}26}, []);2728return (29<View className="rounded-lg border-2 border-gray-500 p-4">30<Button31title="Sign in with Discord"32onPress={handleSignInWithDiscordPress}33/>34</View>35);36}3738export default SignInWithOAuth;
At this point we believe that our authentication offering is better than Expo's direct offer! If you are ready to get started with Expo and Clerk, check out our documentation
Many of our users offer email,username and phone as a way for their users to authenticate. In the past we would have a single input for all of the options and the user would have to type in their phone number including the country code which made it difficult
We now offer a way to switch the input allow the user to see a familiar phone input.
We can now support keys at runtime for users who may have multiple projects under a single monorepo or want fine grain usage of keys.
1export default withClerkMiddleware((request: NextRequest) => {2// pass the secret key to getAuth3const { userId } = getAuth(req,{4secretKey: "CLERK_SECRET_KEY"5});67if (!userId) {8// redirect the users to /pages/sign-in/[[...index]].ts910const signInUrl = new URL("/sign-in", request.url);11signInUrl.searchParams.set("redirect_url", request.url);12return NextResponse.redirect(signInUrl);13}14return NextResponse.next();15},{16// pass the keys to Middleware17secretKey: "CLERK_SECRET_KEY",18});
The <CreateOrganization/> component now exposes the slug field for you to input the slug you want when an organization is created. It is still optional and by default will use the name of the organization.
We now have support for localization in Dutch thanks to a Clerk user who translated our components.
1import { ClerkProvider } from "@clerk/nextjs";2import { nlNL } from "@clerk/localizations";3import type { AppProps } from "next/app";45function MyApp({ Component, pageProps }: AppProps) {6return (7<ClerkProvider localization={nlNL} {...pageProps}>8<Component {...pageProps} />9</ClerkProvider>10);11}1213export default MyApp;
Start completely free for up to 10,000 monthly active users and up to 100 monthly active orgs. No credit card required.
Learn more about our transparent per-user costs to estimate how much your company could save by implementing Clerk.
The latest news and updates from Clerk, sent to your inbox.