Skip to main content

Clerk Changelog

Changelog April 21, 2023

Category
Company
Published

A new change password flow, bulk invites for organizations, hosted pages in the dashboard!

Change password flow

We introduced a new Change password flow this week, that allows the user to change their password and log out all sessions via our user profile component.

Bulk Organization invitations

You can now bulk invite users to an organization via Clerk's API allowing you to invite a whole team quickly.

You can specify a different role for each invited organization member. New organization invitations get a "pending" status until they are revoked by an organization administrator or accepted by the invitee.

The request body supports passing an optional redirect_url parameter for each invitation. When the invited user clicks the link to accept the invitation, they will be redirected to the provided URL.

Use this parameter to implement a custom invitation acceptance flow. You must specify the ID of the user that will send the invitation with the inviter_user_id parameter.

Each invitation can have a different inviter user. Inviter users must be members with administrator privileges in the organization. Only "admin" members can create organization invitations.

Below is a simplified version

curl -XPOST -H "Content-type: application/json" -d '[
  {
    "email_address": "string",
    "inviter_user_id": "string",
    "role": "admin",
    "public_metadata": {},
    "private_metadata": {},
    "redirect_url": "string"
  }
]' 'https://api.clerk.com/v1/organizations/{organization_id}/invitations/bulk'

Check out our backend API reference for more details: https://clerk.com/docs/reference/backend-api/tag/Organization-Invitations#operation/CreateOrganizationInvitationBulk

Hosted Pages

We have added a dedicated section for our hosted pages in the Clerk dashboard. You can find them under customization, this will give you links to preview hosted pages as well as a way to customize some of the look and feel.

Community shoutouts

This week I'd like to highlight a few community creators who created some informative videos on using Clerk!

First up we have Hamed Bahram who created a video on protecting your e-commerce website using Clerk, this 30 minute tutorial shows the power of Clerk from client to server.

Secondly Elias Wambugu who's channel is know as The Source Code gives you a introduction into Clerk with React in just 10 minutes!

Contributor
James Perkins

Changelog April 7, 2023

Category
Company
Published

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.

Expo 48 Support

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.

Before

import { useSignUp, useSignIn } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'

import * as AuthSession from 'expo-auth-session'

const SignInWithOAuth = () => {
  const { isLoaded, signIn, setSession } = useSignIn()
  const { signUp } = useSignUp()
  if (!isLoaded) return null

  const handleSignInWithDiscordPress = async () => {
    try {
      const redirectUrl = AuthSession.makeRedirectUri({
        path: '/oauth-native-callback',
      })

      await signIn.create({
        strategy: 'oauth_discord',
        redirectUrl,
      })

      const {
        firstFactorVerification: { externalVerificationRedirectURL },
      } = signIn

      if (!externalVerificationRedirectURL)
        throw 'Something went wrong during the OAuth flow. Try again.'

      const authResult = await AuthSession.startAsync({
        authUrl: externalVerificationRedirectURL.toString(),
        returnUrl: redirectUrl,
      })

      if (authResult.type !== 'success') {
        throw 'Something went wrong during the OAuth flow. Try again.'
      }

      // Get the rotatingTokenNonce from the redirect URL parameters
      const { rotating_token_nonce: rotatingTokenNonce } = authResult.params

      await signIn.reload({ rotatingTokenNonce })

      const { createdSessionId } = signIn

      if (createdSessionId) {
        // If we have a createdSessionId, then auth was successful
        await setSession(createdSessionId)
      } else {
        // If we have no createdSessionId, then this is a first time sign-in, so
        // we should process this as a signUp instead
        // Throw if we're not in the right state for creating a new user
        if (!signUp || signIn.firstFactorVerification.status !== 'transferable') {
          throw 'Something went wrong during the Sign up OAuth flow. Please ensure that all sign up requirements are met.'
        }

        console.log(
          "Didn't have an account transferring, following through with new account sign up",
        )

        // Create user
        await signUp.create({ transfer: true })
        await signUp.reload({
          rotatingTokenNonce: authResult.params.rotating_token_nonce,
        })
        await setSession(signUp.createdSessionId)
      }
    } catch (err) {
      console.log(JSON.stringify(err, null, 2))
      console.log('error signing in', err)
    }
  }

  return (
    <View className="rounded-lg border-2 border-gray-500 p-4">
      <Button title="Sign in with Discord" onPress={handleSignInWithDiscordPress} />
    </View>
  )
}

export default SignInWithOAuth

After

import { useOAuth } from '@clerk/clerk-expo'
import React from 'react'
import { Button, View } from 'react-native'
import { useWarmUpBrowser } from '../hooks/useWarmUpBrowser'

const SignInWithOAuth = () => {
  useWarmUpBrowser()

  const { startOAuthFlow } = useOAuth({ strategy: 'oauth_discord' })

  const handleSignInWithDiscordPress = React.useCallback(async () => {
    try {
      const { createdSessionId, signIn, signUp, setActive } = await startOAuthFlow()
      if (createdSessionId) {
        setActive({ session: createdSessionId })
      } else {
        // Modify this code to use signIn or signUp to set this missing requirements you set in your dashboard.
        throw new Error('There are unmet requirements, modifiy this else to handle them')
      }
    } catch (err) {
      console.log(JSON.stringify(err, null, 2))
      console.log('error signing in', err)
    }
  }, [])

  return (
    <View className="rounded-lg border-2 border-gray-500 p-4">
      <Button title="Sign in with Discord" onPress={handleSignInWithDiscordPress} />
    </View>
  )
}

export 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

Improving our components

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.

@clerk/nextjs runtime key support

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.

export default withClerkMiddleware(
  (request: NextRequest) => {
    // pass the secret key to getAuth
    const { userId } = getAuth(req, {
      secretKey: 'CLERK_SECRET_KEY',
    })

    if (!userId) {
      // redirect the users to /pages/sign-in/[[...index]].ts

      const signInUrl = new URL('/sign-in', request.url)
      signInUrl.searchParams.set('redirect_url', request.url)
      return NextResponse.redirect(signInUrl)
    }
    return NextResponse.next()
  },
  {
    // pass the keys to Middleware
    secretKey: 'CLERK_SECRET_KEY',
  },
)

Create your organization with a slug

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.

Dutch language support

We now have support for localization in Dutch thanks to a Clerk user who translated our components.

import { ClerkProvider } from '@clerk/nextjs'
import { nlNL } from '@clerk/localizations'
import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <ClerkProvider localization={nlNL} {...pageProps}>
      <Component {...pageProps} />
    </ClerkProvider>
  )
}

export default MyApp
Contributor
James Perkins

Changelog March 31, 2023

Category
Company
Published

Improved Web Vitals, Official Chrome Extension Support, OIDC Provider beta, Cross-Origin Embedder Policy Support

Improved Web Vitals

This week we rolled out major changes to how Clerk's Javascript bundle is split and downloaded. Chances are you didn't notice anything, but your production application should be seeing ~10 points higher performance on pagespeed.web.dev than last week.

Official Chrome Extension Support

Use Clerk and React to building a Chrome extension. We've launched @clerk/chrome-extension on NPM, and a starter repository on GitHub to help kick off your next extension project.

OIDC Provider (beta)

With Clerk, your application can now serve as an Open ID Connect (OIDC) provider. Please reach out through Discord if you'd like to join the beta.

OIDC is a subset of OAuth2. In the future, Clerk will also enable your application to serve as a OAuth2 provider, including supporting grant flows with custom scopes.

Cross-Origin Embedder Policy Support for Profile Images

Clerk profile images are now served with the Access-Control-Allow-Origin: * header to enable embeds in applications with cross-origin embedder policies.

Contributor
Colin Sidoti

Changelog March 24, 2023

Category
Company
Published

Series A announcement, improved email templates and dashboard improvements

We raised $15m in our Series A led by Madrona

We are extremely excited to announce our Series A, this series A will allow us to continue focusing on the product you love and elevate user authentication for developers. If you want all the details check out our blog post written by Colin

Improved Email templates

Our email templates prior to this weeks release would delivery the user agent as part of the identifier at the bottom. We have updated this to now include the IP, and the location to make it easier for your end users to identify if they did request a login.

Organizations Dashboard Updates

We have added the organizations that a user belongs to, to the user's profile in the dashboard, allowing you to add additional organizations, and remove them as needed.

Community feature

This week Theo released a new video on creating the a fullstack Next.js application using TRPC, Typescript, Tailwind, Prisma and of course Clerk!

If you want to learn how to build a modern application with the best tools in under three hours this video is for you!

Contributor
James Perkins

Changelog March 17, 2023

Category
Company
Published

You can find us at clerk.com, sign in with Linear, add scopes to users, beta docs updates

You can find us at clerk.com

You may have noticed, or maybe you didn't! We now are on clerk.com versus our old domain clerk.dev. This migration was a team effort all around as we made sure no one was interrupted as we moved to our new home.

Currently our clerk.dev website is redirecting to clerk.com, however in the future we want to do something with the domain. If you have any ideas, we loved to hear them!

Add additional OAuth scopes

We understand sometimes you need to elevate user scopes after a user is in your application, and sometimes it's based on the users roles or subscription status. This week we introduced a way to to request additional OAuth scopes, and show the user that attention is needed. Below are some examples of how to implement it.

User Button

If you are using our <UserButton/> component you can pass in the userProfileProps along with the provider and the additional scopes.

<UserButton
  userProfileProps={{
    additionalOAuthScopes: {
      twitch: ['user:read:follows'],
    },
  }}
/>

User Profile

If you are mounting the <UserProfile/> in your application you can pass the same props

<UserProfile
  additionalOAuthScopes={{
    twitch: ['user:read:follows'],
  }}
/>

Below is what a user will see when the need to reauthorize your new scopes.

Using the useUser hook

If you are using hooks and building our your own UIs you can use the useUser hook to make the user reauthorize.

const handleClick = async () => {
  if (!isLoaded || !isSignedIn) {
    return null
  }
  user.verifiedExternalAccounts
    .find((oauth) => oauth.provider === 'twitch')
    .reauthorize({
      additionalScopes: ['user:read:follows'],
      redirectUrl: '/protected',
    })
    .then((res) => {
      // open the URL in a new tab generated by Twitch
      window.open(res.verification?.externalVerificationRedirectURL)
    })
    .catch((err) => {
      console.log(err)
    })
}

Sign in with Linear

This had to be one of our biggest requested OAuth providers in the last few weeks, and it's finally here. You can now have your users log in using their linear account. Just enable it in the dashboard and start building!

Sign in with Spotify

We have supported Spotify for a while but it was something we manually enabled as it doesn't support our usual developer shared credentials. We have now opened this up so anyone with their own Spotify credentials can use it.

Beta Documentation Updates

I have been writing non stop since we last spoke, we have had great feedback from the community and that feedback has been rolled into the documentation.

Just today I introduced the Expo quickstart guide, this quickstart guide covers:

  • Using ClerkProvider
  • Custom sign up (email and password) with email verification.
  • Custom sign in (email and password)
  • OAuth with transfers (sign in or sign up with a single click
  • How to sign a user out
  • Using a token cache
  • Read session & user data

You can check out all the new updates at https://clerk.com/docs

Contributor
James Perkins

Changelog March 3, 2023

Category
Company
Published

Organizations improvements, new Ruby SDK and Next.js route handler support

Happy Changelog Friday, the team has been working hard on improving our Organizations offering and SDKs.

Organizations improvements

Create an organization

You can now create organizations right from the Clerk dashboard and assign an owner from your user pool. This was a highly requested features and we are excited to be able to launch this.

Organizations Settings has moved

We moved Organizations settings to the top level of the Clerk Dashboard to make it easier to enable and update maximum members limit

Updated Ruby SDK

The updated Ruby SDK has fixes, changes to core functionality and new features that were needed. The most important are:

  • Fix: Proper caching of JWKS responses All requests to the Backend API now use application/json payloads. This also fixes particular calls to endpoints like the user.update request when passing in backup codes

  • Added: The API key can now be set using the CLERK_SECRET_KEY environment variable [#28]

You can check out the release by update your Ruby SDK to Version: 2.9.0

Next.js 13.2 route handler support

In the 13.2 release of Next.js they introduced route handlers, and Clerk can now support them using our helpers currentUser and auth. Below is an example of a route handler.

import { currentUser } from '@clerk/nextjs/app-beta'

export async function GET() {
  const user = await currentUser()
  if (!user) {
    return new Response('Hello, world!')
  }

  return new Response(`Hello, ${user.firstName}!`)
}
Contributor
James Perkins