Skip to main content

Clerk Changelog

Changes to allowlist and blocklist on sign in

Category
Dashboard
Published
Allowlist and blocklist on sign in screenshot

For new applications created after August 5, 2025, the allowlist and blocklist will only apply to sign ups. Previously, these lists affected both sign ups and sign ins. For existing applications, your settings remain unchanged, but you can opt in to the new behavior anytime from the Clerk Dashboard under Settings > User & Authentication > Restrictions.

Why the change?

The allowlist and blocklist are designed to control who can create accounts, not manage existing users. Because blocking sign ins does not affect existing sessions, it was a half-measure to blocking access and often caused confusion. It also made challenging to block access to identifiers moving forward, without affecting existing accounts. If you need to completely revoke a user's access, you should use the ban feature instead, which will immediately end their active sessions and prevent them from signing in again.

Contributor
Tom Milewski

Share this article

Android SDK Beta

Category
Android
Published

Our new Android SDK is here to ensure that your users enjoy a smooth, integrated sign-in experience, on any Android device.

In a world where users prefer different devices and often switch between them, having a consistent and convenient authentication experience across platforms is more important than ever.

Our Expo SDK has long enabled the creation of universal applications for Android, iOS, and the web using a single React codebase. However, we recognize that some customers prefer native SDKs for optimized performance, direct access to platform-specific features, and seamless integration with other native components.

That's why we’re excited to introduce Clerk Android (Beta)! The Clerk Android SDK is a toolkit designed to integrate Clerk’s authentication and user management services with applications made for the Android ecosystem. Built with Kotlin, the SDK adheres to modern standards, delivering the idiomatic and consistent developer experience you expect from Clerk.

Clerk Android is launching in beta today, with support for building fully custom sign-up and sign-in flows for Android devices. Along with the release, we're also sharing reference documentation and a quickstart to get you started.

Now, on to some highlights of the Clerk Android SDK...

Jetpack Compose

The Clerk Android SDK was built with Jetpack Compose in mind, allowing you to harness it's declarative approach to user interface on all Android platforms.

MainActivity.kt
@Composable
fun MainActivity() {
  Column {
    if(Clerk.user != null) {
      Text("Hello, ${Clerk.user.id}")
    } else {
      Text("You are signed out")
    }
  }
}

Coroutines

The Clerk Android SDK makes use of the latest in coroutines, allowing your code to be as readable and expressive as possible.

// Create a new sign up
scope.launch {
  val signUp = SignUp.create(SignUp.CreateParams.Standard(emailAddress = "newuser@clerk.com", password = "••••••••••"))

  // Send an email with a one time code
  // to verify the user's email
  signUp.prepareVerification(SignUp.PrepareVerificationParams.EmailCode)
}

Social Connections (OAuth)

Authenticate with your favorite social providers in just a few lines of code.

scope.launch {
  SignIn.authenticateWithRedirect(SignIn.AuthenticateWithRedirectParams.OAuth(provider = OAuthProvider.GOOGLE))
}

Session Management

Let the Clerk Android SDK take care of managing your user's authentication state so you can get back to building your app.

MainActivity.kt
@Composable
fun MainActivity() {
  Column {
    if(Clerk.session != null) {
      Text(Clerk.session.id)
    } else {
      Text("No session")
    }
  }

Building towards GA

As an official Clerk SDK, you can expect responsive support, even while in beta. Your feedback is critical during this testing period to ensure Clerk Android is the best it can be. If you have questions or want to talk to other users who are trying out the beta, join the Clerk Discord community.

Please note the SDK is currently in beta. Certain features - notably pre-built components, organizations, and magic links - are not yet implemented, but we're working on it. The full SDK is available on GitHub.

The API will likely undergo breaking changes until the 1.0.0 release.

Contributor
Sam Wolfand

Share this article

Prebuilt iOS Components

Category
iOS
Published

Ready-to-use authentication components for iOS apps.

We're excited to introduce prebuilt UI components that make it incredibly easy to add authentication flows to your iOS applications.

These new SwiftUI components provide complete authentication experiences out of the box, eliminating the need to build custom sign-in and user management interfaces from scratch. With just a few lines of code, you can now add authentication and user management to your iOS app that matches iOS design standards and includes advanced features like multi-factor authentication, social sign-in, and comprehensive user profile management.

AuthView - Complete Authentication Flow

The AuthView component provides a comprehensive authentication experience supporting both sign-in and sign-up flows, multi-factor authentication, password reset, account recovery and more.

The AuthView renders a comprehensive authentication interface that handles both user sign-in and sign-up flows.
HomeView.swift
import SwiftUI
import Clerk

struct HomeView: View {
  @Environment(\.clerk) private var clerk
  @State private var authIsPresented = false

  var body: some View {
    ZStack {
      if clerk.user != nil {
          UserButton()
            .frame(width: 36, height: 36)
      } else {
        Button("Sign in") {
          authIsPresented = true
        }
      }
    }
    .sheet(isPresented: $authIsPresented) {
      AuthView()
    }
  }
}

UserButton - Profile Access Made Simple

The UserButton component displays the current user's profile image in a circular button and opens the full user profile when tapped.

The UserButton component is a circular button that displays the signed-in user's profile image.
HomeView.swift
.toolbar {
  ToolbarItem(placement: .navigationBarTrailing) {
    if clerk.user != nil {
      UserButton()
        .frame(width: 36, height: 36)
    }
  }
}

UserProfileView - Comprehensive Account Management

The UserProfileView component provides a complete interface for users to manage their accounts, including personal information, security settings, account switching, and sign-out functionality.

The UserProfileView component renders a comprehensive user profile interface that displays user information and provides account management options.
ProfileView.swift
import SwiftUI
import Clerk

struct ProfileView: View {
  @Environment(\.clerk) private var clerk

  var body: some View {
    if clerk.user != nil {
      UserProfileView(isDismissable: false)
    }
  }
}

ClerkTheme - Customization

The new theming system allows you to customize the appearance of all Clerk components to match your app's design.

App.swift
import SwiftUI
import Clerk

@main
struct MyApp: App {
  var body: some Scene {
    WindowGroup {
      ContentView()
        .environment(\.clerkTheme, customTheme)
    }
  }
}

let customTheme = ClerkTheme(
  colors: .init(
    primary: Color(.brandPrimary)
  ),
  fonts: .init(
    fontFamily: "Avenir"
  ),
  design: .init(
    borderRadius: 12
  )
)

Light and Dark Mode Support

All Clerk iOS components automatically support both light and dark mode appearance, adapting seamlessly to the user's system preferences.

Light Mode Dark Mode

Getting Started

To get started follow the Quickstart Guide and see the components docs:

Note: Prebuilt iOS components are available on iOS platforms only (iOS, iPadOS, macCatalyst).

Feedback

We're excited to see what you build with these new components! Share your feedback and join the conversation in our Discord community.

Contributor
Mike Pitre

Share this article

Verified domains are now accessible through both the Clerk Dashboard and the Backend API

Now you can see all the organization domains your organizations have set up, visit the Dashboard and head to the Verified Domains tab in the Organization section of the Dashboard.

Verified domains tab

Additionally, you can access this data via Organization Domains in the Clerk Backend API.

Contributors
Iago Dahlem
Nicolas Lopes

Share this article

Protection against user enumeration

Category
Dashboard
Published

Opt in to enhanced protection against user enumeration attacks in the Dashboard

At Clerk, our priority is to provide customers with safe, secure, and easy-to-deploy tools for user management and authentication. When it comes to authentication, each stage of the sign in or sign up flow is designed to minimize friction and get people using your application.

For example, if a user attempts to sign in with an identifier that does not match an existing account on your Clerk application, we inform the user that this identifier doesn't match an existing account. This immediate feedback fits the expectations of ordinary users, who may not remember how or whether they have signed up for your application.

Some of our customers also have a need to protect against user enumeration – when a malicious actor takes advantage of the fact that the error message discloses whether an account exists for a given identifier (like an email or phone number) to create a list of all of the accounts that exist within an application. We already offer all our customers protection against such attacks using a variety of rate limiting techniques.

However, some customers would prefer to remove the ability to determine whether an account exists entirely. Some examples of apps that might fall in this category are financial institutions concerned about targeted phishing attacks, or any website for which an existing account being associated with a given email or phone number is intended to be private to that user, such as perhaps a dating app. To accommodate these needs, we are excited to announce that a set of enhanced protections against user enumeration attacks can now be enabled in the Clerk Dashboard, under the Attack Protection page.

Clerk Dashboard Enumeration Protection feature

With Enumeration Protection enabled, users attempting to sign in or sign up will no longer receive feedback that reveals if their identifier matches an existing account. Instead, they will be advanced to the next stage of the sign in or sign up flow, but attempts to complete the sign in or sign up will be rejected if the account does not exist, in the same way they would be if the credential in the next step, for example, a password, was incorrect. This makes it such that Clerk's response is the same whether or not a user account already exists, enhancing your application's protection against user enumeration attacks.

User security is our priority, and we are happy to bring these opt-in, enhanced protections against user enumeration attacks to our customers who need them.

Contributors
Daniel Moerner
Austin Calvelage

Share this article

Five new React hooks that give developers complete control over building custom billing experiences, from plan selection to checkout completion.

Building on our recent billing button components, we're introducing a set of React hooks that enable you to build fully custom billing flows. These hooks provide direct access to billing data and functionality, giving you complete control over the user experience.

Control the checkout flow

You can now build your own checkout flow with Clerk Billing for both users and organizations. Leverage the useCheckout() hook to create a custom checkout experience. Choose between prompting users to enter their payment details or pay with a saved payment method.

Below you can see a simple example of a custom checkout flow that is using the <PaymentElement /> component where users can enter their payment details.

'use client'
import {
  CheckoutProvider,
  useCheckout,
  PaymentElementProvider,
  PaymentElement,
  usePaymentElement,
} from '@clerk/nextjs/experimental'

export default function CheckoutPage() {
  return (
    <CheckoutProvider for="user" planId="cplan_xxx" planPeriod="month">
      <CustomCheckout />
    </CheckoutProvider>
  )
}

function CustomCheckout() {
  const { checkout } = useCheckout()
  const { plan } = checkout

  return (
    <div className="checkout-container">
      <span>Subscribe to {plan.name}</span>

      <PaymentElementProvider checkout={checkout}>
        <PaymentSection />
      </PaymentElementProvider>
    </div>
  )
}

function PaymentSection() {
  const { checkout } = useCheckout()
  const { isConfirming, confirm } = checkout
  const { isFormReady, submit } = usePaymentElement()
  const isButtonDisabled = !isFormReady || isConfirming

  const subscribe = async () => {
    const { data } = await submit()
    await confirm(data)
  }

  return (
    <>
      <PaymentElement fallback={<div>Loading payment element...</div>} />
      <button disabled={isButtonDisabled} onClick={subscribe}>
        {isConfirming ? 'Processing...' : 'Complete Purchase'}
      </button>
    </>
  )
}

To enable users to pay with a saved payment method, you can use the usePaymentMethods() hook to display a list of saved payment methods.

import { usePaymentMethods } from '@clerk/nextjs/experimental'

function PaymentMethodSelector() {
  const { data: methods, isLoading } = usePaymentMethods()

  return (
    <div className="payment-methods">
      <h3>Select Payment Method</h3>
      {methods?.map((method) => (
        <button key={method.id} className="payment-method-option">
          {method.cardType} ending in {method.last4}
        </button>
      ))}
    </div>
  )
}

Design your own pricing table

usePlans() fetches your instance's configured plans, perfect for building custom pricing tables or plan selection interfaces.

import { usePlans } from '@clerk/nextjs/experimental'

function CustomPricingTable() {
  const { data: plans, isLoading } = usePlans({
    for: 'user',
    pageSize: 10,
  })

  if (isLoading) return <div>Loading plans...</div>

  return (
    <div className="pricing-grid">
      {plans?.map((plan) => (
        <div key={plan.id} className="plan-card">
          <h3>{plan.name}</h3>
          <p>{plan.description}</p>
          <p>
            {plan.currency} {plan.amountFormatted}/month
          </p>
          <ul>
            {plan.features.map((feature) => (
              <li key={feature.id}>{feature.name}</li>
            ))}
          </ul>
        </div>
      ))}
    </div>
  )
}

Display subscription details

Usage of the useSubscription hook

Access current subscription details to build custom account management interfaces and display billing status.

import { useSubscription } from '@clerk/nextjs/experimental'

function SubscriptionStatus() {
  const { data: subscription, isLoading } = useSubscription()

  if (!subscription) return <div>No active subscription</div>

  return (
    <div className="subscription-status">
      <h3>Current Plan: {subscription.plan.name}</h3>
      <p>Status: {subscription.status}</p>
      <p>Next billing: {subscription.nextPayment.date.toLocaleDateString()}</p>
    </div>
  )
}

Note

These hooks are currently exported as experimental while we continue to refine the API based on developer feedback.

Contributor
Pantelis Eleftheriadis

Share this article