Hosted authentication opens Clerk's Account Portal in a browser authentication session. Your users can complete any sign-in or sign-up method enabled for your Clerk application, and the Clerk SDK activates the resulting session in your native app.
The browser doesn't retain a separate active session after Clerk transfers the session to your app.
Hosted authentication is the fastest way to add sign-in and sign-up to a native app. The browser session opens over your app, so users stay in your app for the whole flow. Choose it when you want Clerk to host and maintain the authentication UI and you don't need that UI built from native components.
For authentication that renders with native components instead of a browser session, use Clerk's Expo native components or iOS and Android views. To control every step of the UI and authentication flow, build a custom flow.
In the Clerk Dashboard, navigate to the Native applications page, enable the Native API, and add your app. Production instances validate the callback against the registered bundle identifier or package name, so add your app before you create a production build.
Account Portal runs in a browser, so social sign-in uses each provider's web OAuth flow rather than the native one. On production instances, Sign in with Apple needs an Apple Services ID and key set up through the Apple social connection.
The default callback uses the bundle identifier or package name from your Expo configuration. In Expo Go, Expo supplies a development callback instead. Keep the @clerk/expoconfig plugin in your app configuration and rebuild the native project after you change either identifier.
Call startHostedAuth() from an asynchronous task. The following example opens Account Portal when a user selects Sign in:
importClerkKitimportSwiftUIstructSignInButton:View {@Environment(Clerk.self)privatevar clerkvar body: some View {Button("Sign in") {Task {do {tryawait clerk.auth.startHostedAuth() } catch {// Handle the error in your app. } } } }}
The iOS SDK uses <bundle-identifier>://callback as the default callback.
Call startHostedAuth() from a coroutine. The following example opens Account Portal when a user selects Sign in:
Users can dismiss the browser authentication session before they finish. Each SDK reports cancellation differently:
Expo
iOS
Android
startHostedAuth() resolves with a null session ID when the user dismisses the browser. Authentication errors throw.
try {const { createdSessionId,authSessionResult } =awaitstartHostedAuth()if (!createdSessionId) {// The user dismissed the browser.// authSessionResult?.type is 'cancel' or 'dismiss'. }} catch (error) {// Authentication failed.}
startHostedAuth() throws when the user dismisses the browser or authentication fails:
do {tryawait clerk.auth.startHostedAuth()} catch {// The user dismissed the browser, or authentication failed.}
startHostedAuth() returns a failure when the user dismisses the browser or authentication fails:
import com.clerk.api.network.serialization.ClerkResultwhen (val result = Clerk.auth.startHostedAuth()) {is ClerkResult.Success -> {// The session is active. }is ClerkResult.Failure -> {// The user dismissed the browser, or authentication failed. }}
Check that the bundle identifier or package name in your app matches the entry on the Clerk Dashboard's Native applications page.
For Expo apps on Android, also confirm that @clerk/expo is present in the plugins array in app.json. Rebuild the native project after you add the plugin or change the Android package name.
The provider's screen appears and accepts the user, then sign-in stops without an error.
The provider is missing its credentials. Production instances require you to supply your own for each social provider. Check the provider's custom credentials on the Clerk Dashboard's SSO connections page. For Apple, that's an Apple Services ID and key, set up through the Apple social connection.