You must configure your application instance through the Clerk Dashboard for the enterprise connection(s) that you want to use. Visit the appropriate guide for your platform to learn how to configure your instance.
Examples for this SDK aren't available yet. For now, try adapting the available example to fit your SDK.
The following example will both sign up and sign in users, eliminating the need for a separate sign-up page. However, if you want to have separate sign-up and sign-in pages, the sign-up and sign-in flows are equivalent, meaning that all you have to do is swap out the SignIn object for the SignUp object using the useSignUp() hook.
Starts the authentication process by calling SignIn.sso(params). This method requires the following params:
redirectUrl: The URL that the browser will be redirected to once the user authenticates with the identity provider if no additional requirements are needed, and a session has been created.
redirectCallbackUrl: The URL that the browser will be redirected to once the user authenticates with the identity provider if additional requirements are needed.
Creates a route at the URL that the redirectCallbackUrl param points to. The following example re-uses the /sign-in route, which should be written to handle when a sign-in attempt is in a non-complete status such as needs_second_factor.
app/sign-in/page.tsx
'use client'import*as React from'react'import { useSignIn } from'@clerk/nextjs'exportdefaultfunctionPage() {const { signIn,errors,fetchStatus } =useSignIn()constsignInWithEnterpriseSSO=async (formData:FormData) => {constemail=formData.get('email') asstringconst { error } =awaitsignIn.sso({ identifier: email, strategy:'enterprise_sso',// The URL that the user will be redirected to if additional requirements are needed redirectCallbackUrl:'/sign-in', redirectUrl:'/sign-in/tasks',// Learn more about session tasks at https://clerk.com/docs/guides/development/custom-flows/overview#session-tasks })if (error) {// See https://clerk.com/docs/guides/development/custom-flows/error-handling// for more info on error handlingconsole.error(JSON.stringify(error,null,2))return }if (signIn.status ==='needs_second_factor') {// See https://clerk.com/docs/guides/development/custom-flows/authentication/multi-factor-authentication } elseif (signIn.status ==='needs_client_trust') {// See https://clerk.com/docs/guides/development/custom-flows/authentication/client-trust } else {// Check why the sign-in is not completeconsole.error('Sign-in attempt not complete:', signIn) } }return ( <> <formaction={signInWithEnterpriseSSO}> <inputid="email"type="email"name="email"placeholder="Enter email address" /> <buttontype="submit"disabled={fetchStatus ==='fetching'}> Sign in with Enterprise SSO </button> </form> {/* For your debugging purposes. You can just console.log errors, but we put them in the UI for convenience */} {errors && <p>{JSON.stringify(errors,null,2)}</p>} </> )}
The following example will both sign up and sign in users, eliminating the need for a separate sign-up page.
The following example:
Uses the useSSO()Expo Icon hook to access the startSSOFlow() method.
Calls the startSSOFlow() method with the strategy param set to enterprise_sso and the identifier param set to the user's email address that they provided. The optional redirect_url param is also set in order to redirect the user once they finish the authentication flow.
If authentication is successful, the setActive() method is called to set the active session with the new createdSessionId. You may need to check for session tasks that are required for the user to complete after signing up.
If authentication is not successful, you can handle the missing requirements, such as MFA, using the signIn or signUp object returned from startSSOFlow(), depending on if the user is signing in or signing up. These objects include properties, like status, that can be used to determine the next steps. See the respective linked references for more information.
app/(auth)/sign-in.tsx
import React, { useEffect, useState } from'react'import*as WebBrowser from'expo-web-browser'import*as AuthSession from'expo-auth-session'import { useSSO } from'@clerk/expo'import { View, Button, TextInput, Platform } from'react-native'exportconstuseWarmUpBrowser= () => {useEffect(() => {// Preloads the browser for Android devices to reduce authentication load time// See: https://docs.expo.dev/guides/authentication/#improving-user-experienceif (Platform.OS!=='android') returnvoidWebBrowser.warmUpAsync()return () => {// Cleanup: closes browser when component unmountsvoidWebBrowser.coolDownAsync() } }, [])}// Handle any pending authentication sessionsWebBrowser.maybeCompleteAuthSession()exportdefaultfunctionPage() {useWarmUpBrowser()const [email,setEmail] =useState('')// Use the `useSSO()` hook to access the `startSSOFlow()` methodconst { startSSOFlow } =useSSO()constonPress=async () => {try {// Start the authentication process by calling `startSSOFlow()`const { createdSessionId,setActive,signIn,signUp } =awaitstartSSOFlow({ strategy:'enterprise_sso', identifier: email,// For web, defaults to current path// For native, you must pass a scheme, like AuthSession.makeRedirectUri({ scheme, path })// For more info, see https://docs.expo.dev/versions/latest/sdk/auth-session/#authsessionmakeredirecturioptions redirectUrl:AuthSession.makeRedirectUri(), })// If sign in was successful, set the active sessionif (createdSessionId) {setActive!({ session: createdSessionId,navigate:async ({ session, decorateUrl }) => {if (session?.currentTask) {// Handle pending session tasks// See https://clerk.com/docs/guides/development/custom-flows/authentication/session-tasksconsole.log(session?.currentTask)return }consturl=decorateUrl('/')if (url.startsWith('http')) {window.location.href = url } else {router.push(url) } }, }) } else {// If there is no `createdSessionId`,// there are missing requirements, such as MFA// Use the `signIn` or `signUp` returned from `startSSOFlow`// to handle next steps } } catch (err) {// See https://clerk.com/docs/guides/development/custom-flows/error-handling// for more info on error handlingconsole.error(JSON.stringify(err,null,2)) } }return ( <View> <TextInputvalue={email}onChangeText={setEmail}placeholder="Enter email"placeholderTextColor="#666666" /> <Buttontitle="Sign in with SAML"onPress={onPress} /> </View> )}
EnterpriseSSOView.swift
importSwiftUIimportClerkKitstructEnterpriseSSOView:View {@Environment(Clerk.self)privatevar clerk@Stateprivatevar email =""var body: some View {TextField("Enter email", text: $email)Button("Sign in with Enterprise SSO") {Task { awaitsignInWithEnterpriseSSO(email: email) } }}}extensionEnterpriseSSOView {funcsignInWithEnterpriseSSO(email: String) async {do {let result =tryawait clerk.auth.signInWithEnterpriseSSO(emailAddress: email)// Enterprise SSO can complete as either a sign-in or sign-up// Clerk returns a TransferFlowResult to cover both casesswitch result {case .signIn(let signIn):switch signIn.status {case .complete:dump(clerk.session)default:dump(signIn.status) }case .signUp(let signUp):switch signUp.status {case .complete:dump(clerk.session)default:dump(signUp.status) } } } catch {// See https://clerk.com/docs/guides/development/custom-flows/error-handling// for more info on error handlingdump(error) }}}
EnterpriseSSOView.kt
EnterpriseSSOActivity.kt
EnterpriseSSOView.kt
import android.util.Logimport androidx.lifecycle.ViewModelimport androidx.lifecycle.viewModelScopeimport com.clerk.api.Clerkimport com.clerk.api.network.serialization.errorMessageimport com.clerk.api.network.serialization.onFailureimport com.clerk.api.network.serialization.onSuccessimport com.clerk.api.signin.SignInimport com.clerk.api.signup.SignUpimport com.clerk.api.sso.ResultTypeimport kotlinx.coroutines.flow.MutableStateFlowimport kotlinx.coroutines.flow.asStateFlowimport kotlinx.coroutines.flow.combineimport kotlinx.coroutines.flow.launchInimport kotlinx.coroutines.launchclassEnterpriseSSOViewModel : ViewModel() {privateval _uiState =MutableStateFlow<UiState>(UiState.Loading)val uiState = _uiState.asStateFlow()init {combine(Clerk.isInitialized, Clerk.userFlow) { isInitialized, user -> _uiState.value=when {!isInitialized -> UiState.Loading user !=null-> UiState.Authenticatedelse-> UiState.SignedOut } }.launchIn(viewModelScope)}funsignInWithEnterpriseSSO(email: String) { viewModelScope.launch { Clerk.auth.signInWithEnterpriseSso { this.email = email }.onSuccess {// Enterprise SSO can complete as either a sign-in or sign-up.when (it.resultType) { ResultType.SIGN_IN -> {if (it.signIn?.status == SignIn.Status.COMPLETE) { _uiState.value= UiState.Authenticated } else {// If the status is not complete, check why. User may need to// complete further steps. } } ResultType.SIGN_UP -> {if (it.signUp?.status == SignUp.Status.COMPLETE) { _uiState.value= UiState.Authenticated } else {// If the status is not complete, check why. User may need to// complete further steps. } } } }.onFailure {// See https://clerk.com/docs/guides/development/custom-flows/error-handling// for more info on error handling Log.e("EnterpriseSSO", it.errorMessage, it.throwable) } }}sealedinterfaceUiState {dataobjectLoading : UiStatedataobjectSignedOut : UiStatedataobjectAuthenticated : UiState}}