11 Getting Started with Authentication SDK

The Authentication SDKs provide a complete set of tools for managing user sign-in, session persistence, and identity verification in Oracle Backend for Firebase applications. This chapter gets you started with prerequisites and email/password sign-in, then points you to pre-built UI, user management operations, and email verification and password reset for common account flows, followed by third-party identity providers, linking social accounts, and persistence settings.

11.1 Prerequisites

Before you start, make sure you have these in place.

Add the SDK for Your Platform

Choose one platform and add the Oracle Backend for Firebase Authentication SDK for that platform:

Enable Authentication

Enable authentication in your Oracle Backend for Firebase project: Enabling Authentication for a Project

11.2 Getting Started

After you initialize your Oracle Backend for Firebase app with the SDK configuration from the Console UI, create an Auth instance for your platform.

import { getAuth } from 'fusabase/auth';

const auth = getAuth(app);
import fusabase from 'fusabase-ns';

const app = fusabase.app(); // Or use the instance returned from initializeApp.
const auth = fusabase.auth(app);
import com.oracle.database.fusabase.auth.FusabaseAuth;

final FusabaseAuth mAuth = FusabaseAuth.getInstance();
import FusabaseCore
import FusabaseAuth

FusabaseApp.configure()
let auth = FusabaseAuth.auth()
final auth = FusabaseAuth.instance;

11.3 Pre-built UI

Use the prebuilt Auth UI to add a ready-to-use sign-in experience to a web app. It renders sign-in and sign-up screens, wires up provider flows, and supports an optional post-sign-in redirect.

What You Get

  • An embedded sign-in and sign-up UI rendered in your page

  • Provider sign-in flows handled for Google, Facebook, GitHub, and email/password

  • A simple callback for post-sign-in logic

Before You Begin

11.3.1 Using Pre-built UI

To get started quickly on the web, the Oracle Backend for Firebase SDK provides a pre-built Auth UI to be used on a web application.

Step 1: Create an AuthUI Instance

Import the UI package for the JS API you are using, then create an AuthUI instance with your initialized auth object.

import { authUI } from 'fusabase/ui';
import {
  EmailAuthProvider,
  FacebookAuthProvider,
  GithubAuthProvider,
  GoogleAuthProvider,
} from 'fusabase/auth';

const ui = new authUI.AuthUI(auth);

// Mount into a container (selector or HTMLElement)
ui.start('#auth-container', {
  signInOptions: [
    GoogleAuthProvider.PROVIDER_ID, // 'google'
    FacebookAuthProvider.PROVIDER_ID, // 'facebook'
    GithubAuthProvider.PROVIDER_ID, // 'github'
    EmailAuthProvider.PROVIDER_ID, // 'password' (shows email/password login/register)
  ],
  callbacks: {
    // Return true to allow redirect; false to prevent it
    signInSuccessWithAuthResult: (authResult, redirectUrl) => {
      console.log(
        'Signed in:',
        authResult.user.uid,
        'redirect to:',
        redirectUrl
      );
      return true;
    },
  },
  // If provided and callback returns true, UI will navigate to this URL
  signInSuccessUrl: '/home',
});
import { authUI } from 'fusabase-ns/ui';
import { auth } from 'fusabase-ns/auth';

const ui = new authUI.AuthUI(auth);

// Mount into a container (selector or HTMLElement)
ui.start('#auth-container', {
  signInOptions: [
    auth.EmailAuthProvider.PROVIDER_ID,
    auth.GoogleAuthProvider.PROVIDER_ID,
    auth.FacebookAuthProvider.PROVIDER_ID,
    auth.GithubAuthProvider.PROVIDER_ID,
  ],
  signInSuccessUrl: '/home',
  callbacks: {
    // Return false to prevent automatic redirect
    signInSuccessWithAuthResult: (result, redirectUrl) => true,
  },
});

Step 2: Configure Sign-in Options

Update signInOptions to match the providers you enabled in the Console. Include only the methods your app supports.

Supported provider IDs in the prebuilt UI:

  • EmailAuthProvider.PROVIDER_ID

  • GoogleAuthProvider.PROVIDER_ID

  • FacebookAuthProvider.PROVIDER_ID

  • GithubAuthProvider.PROVIDER_ID

Step 3: Render the UI

Create a container element in your page and start the UI:

<!-- HTML starts -->
<div id="auth-container"></div>
<!-- HTML ends -->

// JS starts
ui.start('#auth-container', {
  /* config */
});
// JS ends

Step 4: Handle Sign-In Success

Use the signInSuccessWithAuthResult callback to run your own logic after a user signs in. Return true to allow the redirect, or false if you want to handle navigation yourself.

callbacks: {
  signInSuccessWithAuthResult: (authResult, redirectUrl) => {
    console.log('Signed in:', authResult.user.uid);
    return true;
  },
},

Step 5: Redirect after Sign-In

Use signInSuccessUrl to send the user to a page after a successful sign-in.

signInSuccessUrl: '/home'

Customize the UI

The prebuilt UI renders into your container element, so you can style it with your app's CSS and layout. Keep the container in your app shell so your branding and navigation remain visible.

What the UI Handles

  • New user registration (email/password)

  • Sign-in (email/password and supported social providers)

  • Popup-based provider sign-in flows

Verify Results

Load your sign-in page. You should see the providers you enabled in the Console, and a successful sign-in should trigger your callback and optional redirect.

Troubleshooting

  • If a provider does not appear, make sure it is enabled in the Console and included in signInOptions.

  • If sign-in fails, confirm your app domain is listed in Authorized domains.

11.4 User Management Operations

User Registration with Email and Password

Password-based authentication allows users to sign up with an email and password. This is the most common method for applications that require secure, credential-based access.

Before using these methods, make sure you've set up authentication in the Console.

import { createUserWithEmailAndPassword } from "fusabase/auth";

// Register user
createUserWithEmailAndPassword(auth, email, password)
     .then((userCredential) => {
        console.log("User registered:", userCredential.user.email);
     })
     .catch((error) => {
        console.error("Error:", error.message);
     });
import fusabase from 'fusabase-ns';

// Register user
const auth = fusabase.auth();

auth
  .createUserWithEmailAndPassword(email, password)
  .then((userCredential) => {
    console.log('User registered:', userCredential.user.email);
  })
  .catch((error) => {
    console.error('Error:', error.message);
  });
import android.util.Log;

import com.oracle.mobile.fusabase.auth.FusabaseAuth;
import com.oracle.mobile.fusabase.auth.FusabaseUser;

FusabaseAuth mAuth = FusabaseAuth.getInstance();

mAuth.createUserWithEmailAndPassword(email, password)
    .addOnCompleteListener(this, task -> {
        if (task.isSuccessful()) {
            FusabaseUser user = mAuth.getCurrentUser();
            Log.d(TAG, "User registered: " + user.getEmail());
        } else {
            Log.w(TAG, "Registration failed", task.getException());
        }
    });
import FusabaseAuth

let mAuth = FusabaseAuth.auth()

auth.createUser(withEmail: email, password: password) { result, error in
    if let error = error {
        // Registration failed
        print("Registration failed: \(error.localizedDescription)")
        return
    }
    
    if let result = result {
        // Registration successful
        let user = result.user
        print("User registered: \(user.email ?? "No email")")
        
        // Or access via auth.currentUser
        if let currentUser = auth.currentUser {
            print("Current user: \(currentUser.email ?? "No email")")
        }
    }
}
try {
  final userCredential = await auth.createUserWithEmailAndPassword(
    email,
    password,
  );
  print('Registered: ${userCredential.user.uid}');
} catch (e) {
  print('Registration failed: $e');
}

Sign In a User with Email and Password

This code initializes the Auth instance, then signs in a user with email and password (signInWithEmailAndPassword(email, password)). If successful, the user object is returned; otherwise, an error is logged.

import { signInWithEmailAndPassword } from 'fusabase/auth';

// Sign in user
signInWithEmailAndPassword(auth, email, password)
  .then((userCredential) => {
    console.log('User signed in:', userCredential.user.email);
  })
  .catch((error) => {
    console.error('Error:', error.message);
  });
import fusabase from 'fusabase-ns';

// Sign in user
const auth = fusabase.auth();

auth
  .signInWithEmailAndPassword(email, password)
  .then((userCredential) => {
    console.log('User signed in:', userCredential.user.email);
  })
  .catch((error) => {
    console.error('Error:', error.message);
  });
import com.oracle.mobile.fusabase.auth.FusabaseAuth;
import com.oracle.mobile.fusabase.auth.FusabaseUser;
import android.util.Log;

FusabaseAuth mAuth = FusabaseAuth.getInstance();
               
mAuth.signInWithEmailAndPassword(email, password)
	.addOnCompleteListener(this, task -> {
    	if (task.isSuccessful()) {
        	FusabaseUser user = mAuth.getCurrentUser();
        	Log.d(TAG, "User signed in successfully");
    	} else {
        	Log.w(TAG, "Sign In failed", task.getException());
    	}
});
import FusabaseAuth

let mAuth = FusabaseAuth.auth()

mAuth.signIn(withEmail: email, password: password) { result, error in
    if let error = error {
        // Sign In failed
        print("Sign In failed: \(error.localizedDescription)")
        return
    }
    
    if let result = result {
        // Sign In successful
        let user = result.user
        print("User signed in successfully")
        
        // Or access via auth.currentUser (equivalent to mAuth.getCurrentUser())
        if let currentUser = mAuth.currentUser {
            print("Current user: \(currentUser.email ?? "No email")")
        }
    }
}
try {
  final userCredential = await auth.signInWithEmailAndPassword(
    email,
    password
  );
  print('Signed in: ${userCredential.user.uid}');
} catch (e) {
  print('Sign in failed: $e');
}

Get Signed-In User Profile Information

The following example retrieves the currently signed‑in user’s profile information.

const user = auth.currentUser;
if (user !== null) {
  // The user object has basic properties such as display name, email, etc.
  const displayName = user.displayName;
  const email = user.email;
  const emailVerified = user.emailVerified;
  const uid = user.uid;
}

Note:

currentUser property might be null because the Auth object has not finished initializing. Best practice is to use an observer as follows:

import { onAuthStateChanged } from "fusabase/auth";
onAuthStateChanged(auth, user => {
	if(user !== null) console.log('Current User: ', user);
});
const user = fusabase.auth().currentUser;
if (user !== null) {
  // The user object has basic properties such as display name, email, etc.
  const displayName = user.displayName;
  const email = user.email;
  const emailVerified = user.emailVerified;
  const uid = user.uid;
}

Note:

currentUser property might be null because the Auth object has not finished initializing. Best practice is to use an observer as follows:
fusabase.auth().onAuthStateChanged(user => {
	if(user !== null) console.log('Current User: ', user);
});
import com.oracle.mobile.fusabase.auth.FusabaseAuth;
import com.oracle.mobile.fusabase.auth.FusabaseUser;

FusabaseAuth mAuth = FusabaseAuth.getInstance();

FusabaseUser user = mAuth.getCurrentUser();
if (user != null) {
    // Provider ID (authentication method used)
    String providerId = user.getProviderId();

    // UID specific to the provider
    String uid = user.getUid();

    // Name, email address, and profile photo URL
    String name = user.getDisplayName();
    String email = user.getEmail();
    Boolean emailVerified = user.isEmailVerified();
            
} 

Note:

getCurrentUser() might be null because the Auth object has not finished initializing. Best practice is to use an observer as:

mAuth.addAuthStateListener((tAuth) -> {
    Log.d(TAG, "User signed in: " + tAuth.getCurrentUser().getEmail());
});
import FusabaseAuth

let mAuth = FusabaseAuth.auth()

if let user = mAuth.currentUser {
    
    let providerId = user.providerID
    
    let uid = user.uid
    
    let name = user.displayName
    let email = user.email
    let emailVerified = user.isEmailVerified
}

Note:

currentUser might be null because the Auth object has not finished initializing. Best practice is to use an observer as:

handle = FusabaseAuth.auth().addStateDidChangeListener { auth, user in
  // ...
}
final user = auth.currentUser;
if (user != null) {
   // UID specific to the provider
   final uid = user.uid;

   // Name, email address, and profile photo URL
   final name = user.displayName;
   final emailAddress = user.email;
}

Note:

currentUser might be null because the Auth object has not finished initializing. Best practice is to use an observer as:

auth.authStateChanges().listen((User? user) {
    if (user != null) {
      print(user.uid);
    }
});

Update User Profile Information

Client SDKs allow changing basic user profile information like displayName or photoURL The following example updates the display name, photo, or other attributes of the authenticated user.

import { updateProfile } from 'fusabase/auth';
await updateProfile(user, { displayName: 'John Doe', photoURL: 'https://example.com/photo.jpg' });
const user = auth.currentUser;

user.updateProfile({
  displayName: "John Doe",
  photoURL: "https://example.com/profile.jpg"
})
import com.oracle.mobile.fusabase.auth.FusabaseAuth;
import com.oracle.mobile.fusabase.auth.FusabaseUser;
import com.oracle.mobile.fusabase.auth.UserProfileChangeRequest;
import com.oracle.mobile.fusabase.task.Task;
import com.oracle.mobile.fusabase.task.OnCompleteListener;
import android.util.Log;
import androidx.annotation.NonNull;

FusabaseAuth mAuth = FusabaseAuth.getInstance();
FusabaseUser user = mAuth.getCurrentUser();

if (user != null) {
    UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
            .setDisplayName("John Doe")
            .build();
            
    user.updateProfile(profileUpdates)
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "User profile updated.");
                    } else {
                        Log.w(TAG, "Profile update failed", task.getException());
                    }
                }
            });
}
import FusabaseAuth
let mAuth = FusabaseAuth.auth()
    
if let user = mAuth.currentUser {
        let profileUpdates = user.createProfileChangeRequest()
        profileUpdates.displayName = "John Doe"
        
        try await profileUpdates.commitChanges()
        print("User profile updated.")
}
final user = auth.currentUser;

await user.updatePassword('oldPass', 'newPass');

Update Self-Password

Client SDKs allow changing user password by providing the old user password, for the users signing in through Email / Password.

import { updatePassword } from 'fusabase/auth';

const user = auth.currentUser;
await updatePassword(user, 'oldPass', 'newPass');
const user = auth.currentUser;

user.updatePassword('oldPass', 'newPass');

Note:

Only possible if signed in using Email / Password. The Android SDK uses the cached password from the last sign-in to perform this update.

import android.util.Log;

import androidx.annotation.NonNull;

import com.oracle.mobile.fusabase.auth.FusabaseAuth;
import com.oracle.mobile.fusabase.auth.FusabaseUser;
import com.oracle.mobile.fusabase.task.OnCompleteListener;
import com.oracle.mobile.fusabase.task.Task;

FusabaseAuth mAuth = FusabaseAuth.getInstance();

FusabaseUser user = mAuth.getCurrentUser();
if (user != null) {
    String newPassword = "newSecurePassword123";

    user.updatePassword(newPassword)
        .addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                if (task.isSuccessful()) {
                    Log.d(TAG, "User password updated.");
                } else {
                    Log.w(TAG, "Password update failed", task.getException());
                }
            }
        });
}

Note:

Only possible if signed in using Email / Password.

import FusabaseAuth

let mAuth = FusabaseAuth.auth()
    
if let user = mAuth.currentUser {
   try await user.updatePassword(to: newPassword)
   print("User password updated.")
}
final user = auth.currentUser;

await user.updatePassword('oldPass', 'newPass');

11.5 Email Verification and Reset Password

The Authentication SDK provides built‑in methods to help developers manage critical user account flows such as verifying email addresses and resetting forgotten passwords. These operations ensure that only valid users gain access to applications and that account recovery is secure and seamless.

Both features can be implemented using Oracle Backend for Firebase. By integrating these flows, developers can enforce Oracle’s password policy, comply with project‑level SMTP configurations, and deliver a reliable authentication experience without building custom logic from scratch.

See Also:

Defining Password Policies for more information about setting password policies

Prerequisites

  • Authentication Service is Enabled: Email verification and reset password are available only if the Authentication service is active for your project.

  • Password-Based Login is Configured: Email verification and password reset apply only to users registered through email/password authentication.

  • SMTP is Set Up: You must configure an SMTP server in the Oracle Backend for Firebase Console for sending verification emails.

    • SMTP host, port, username, and password must be provided.

    • Ensure that the SMTP credentials have permission to send emails from the domain you specify.

  • Password Policy is Configured A password policy must be defined in the Console (minimum length, maximum length, special characters, uppercase/lowercase requirements). This policy applies to email/password accounts.

See Also:

Send Email Verification to a User

import { sendEmailVerification } from "fusabase/auth";

sendEmailVerification(auth.currentUser)
  .then(() => {
    // Email verification sent!
    // ...
  });
auth.currentUser.sendEmailVerification()
  .then(() => {
    // Email verification sent!
    // ...
  });
import android.util.Log;

import androidx.annotation.NonNull;

import com.oracle.mobile.fusabase.auth.FusabaseAuth;
import com.oracle.mobile.fusabase.auth.FusabaseUser;
import com.oracle.mobile.fusabase.task.OnCompleteListener;
import com.oracle.mobile.fusabase.task.Task;

FusabaseAuth mAuth = FusabaseAuth.getInstance();

FusabaseUser currentUser = mAuth.getCurrentUser();
if (currentUser != null) {
    currentUser
        .sendEmailVerification()
        .addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                if (task.isSuccessful()) {
                    Log.d("FusabaseAuth", "Email verification sent.");
                } else {
                    Log.w(
                        "FusabaseAuth",
                        "Email verification failed",
                        task.getException()
                    );
                }
            }
        });
}
import FusabaseAuth

let mAuth = FusabaseAuth.auth()

if let user = mAuth.currentUser {
    try await user.sendEmailVerification()
    print("Email sent.")
}
final user = auth.currentUser;
await user?.sendEmailVerification();

Send Reset Password by Email

import { sendPasswordResetEmail, verifyPasswordResetCode, confirmPasswordReset } from "fusabase/auth";

// Send Password Reset Email
sendPasswordResetEmail(auth, 'email@example.com')
  .then(() => {
    // Email reset password sent!
    // ...
  });

// Use the URL in the email or copy the code from the Email
// verify if the action code is valid.
verifyPasswordResetCode(auth, actionCode)
  .then((email) => {
     console.log("valid code for: " + email);
	 // reset password for the user email returned by verifyPasswordResetCode
     await confirmPasswordReset(auth, actionCode, newPassword);
  });
// Send Password Reset Email
auth.sendPasswordResetEmail('email@example.com')
  .then(() => {
    // Email reset password sent!
    // ...
  });

// Use the URL in the email or copy the code from the Email
// verify if the action code is valid.
auth.verifyPasswordResetCode(actionCode)
  .then((email) => {
     console.log("valid code for: " + email);
	 // reset password for the user email returned by verifyPasswordResetCode
     await auth.confirmPasswordReset(actionCode, newPassword);
  });
import android.util.Log;

import androidx.annotation.NonNull;

import com.oracle.mobile.fusabase.auth.FusabaseAuth;
import com.oracle.mobile.fusabase.task.OnCompleteListener;
import com.oracle.mobile.fusabase.task.OnSuccessListener;
import com.oracle.mobile.fusabase.task.Task;

FusabaseAuth mAuth = FusabaseAuth.getInstance();

// Send password reset email
String email = "user@example.com";

mAuth.sendPasswordResetEmail(email)
    .addOnCompleteListener(new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> task) {
            if (task.isSuccessful()) {
                Log.d("FusabaseAuth", "Password reset email sent to: " + email);
            } else {
                Log.w(
                    "FusabaseAuth",
                    "Failed to send password reset email",
                    task.getException()
                );
            }
        }
    });

// Example of verifying and confirming password reset.
// This would typically be done in a separate flow after the user receives the email.
String actionCode = "reset-code-from-email"; // Retrieved from email link
String newPassword = "newSecurePassword123";

mAuth.verifyPasswordResetCode(actionCode)
    .addOnSuccessListener(new OnSuccessListener<String>() {
        @Override
        public void onSuccess(String email) {
            Log.d(TAG, "Password reset code verified for: " + email);

            // Confirm the password reset
            mAuth.confirmPasswordReset(actionCode, newPassword)
                .addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        if (task.isSuccessful()) {
                            Log.d(
                                "FusabaseAuth",
                                "Password reset successful for: " + email
                            );
                        } else {
                            Log.w(
                                "FusabaseAuth",
                                "Password reset failed",
                                task.getException()
                            );
                        }
                    }
                });
        }
    })
    .addOnFailureListener(e -> {
        Log.w("FusabaseAuth", "Password reset code verification failed", e);
    });
import FusabaseAuth

let mAuth = FusabaseAuth.auth()

// Step 1: Verify the code
let email = try await mAuth.verifyPasswordReset(actionCode)
print("Code verified for: \(email)")

// Step 2: Reset the password
let result = try await mAuth.confirmPasswordReset(
    withCode: actionCode,
    newPassword: newPassword
)
print("Password successfully reset for: \(email)")
// Send Password Reset Email
await auth.sendPasswordResetEmail(email: 'email@example.com');

// Use the URL in the email or copy the code from the Email
// verify if the action code is valid.
String email = await auth.verifyPasswordResetCode(actionCode);
await auth.confirmPasswordReset(code: actionCode, newPassword: 'newPass');

11.6 Third-Party Identity Providers

Oracle Backend for Firebase supports integration with popular third-party identity providers to enable secure and seamless authentication for application users. This section explains how to configure and use providers such as Google, Facebook, and GitHub within your Oracle Backend for Firebase project.

Prerequisite (Console UI)

Before configuring third-party identity providers, ensure the following:

  • You have created and initialized an Oracle Backend for Firebase project using the Console or CLI.

  • Authentication service is enabled.

Supported Providers

  • Google

  • Facebook

  • GitHub

Set Up Providers Using Console

See Also:

Setting Up Third-Party Identity Providers for more information on the Console steps required to register and configure third-party identity providers

11.6.1 Web Sign-In Flow

On the web platforms, Oracle Backend for Firebase SDK provides three different sign-in flows for the users to authenticate with Social Providers.

To initiate the sign-in flow with the Oracle Backend for Firebase SDK, follow these steps:

1. Create an instance of the AuthProvider for the sign-in method.

import { OAuthProvider, GoogleAuthProvider, FacebookAuthProvider, GithubAuthProvider, SAMLAuthProvider } from "fusabase/auth";
import { IDCSAuthProvider } from "fusabase/auth";

// choose the provider you want to use for Social Sign-in

// If your Auth Server is Oracle IDCS, the Social Sign-in flow is completed
// through the Oracle IDCS SSO page itself, and only IDCSAuthProvider is available.
// The Oracle IDCS SSO page allows choosing the Social Provider to login through.
const provider = new IDCSAuthProvider();

// If you Auth Server is BASIC / LDAP, continue with:  
// Google
const provider = new GoogleAuthProvider();

// Facebook
const provider = new FacebookAuthProvider();

// Github
const provider = new GithubAuthProvider();

// OIDC Provider
const provider = new OAuthProvider("oidc_example");

// SAML Provider
const provider = new SAMLAuthProvider("saml_example");
// choose the provider you want to use for Social Sign-in

// If your Auth Server is Oracle IDCS, the Social Sign-in flow is completed
// through the Oracle IDCS SSO page itself, and only IDCSAuthProvider is available.
// The Oracle IDCS SSO page allows choosing the Social Provider to login through.
let provider = new auth.IDCSAuthProvider();

// If you Auth Server is BASIC / LDAP, continue with: 
// Google
let provider = new auth.GoogleAuthProvider();

// Facebook
let provider = new auth.FacebookAuthProvider();

// Github
let provider = new auth.GithubAuthProvider();

// OIDC Provider
let provider = new auth.OAuthProvider("oidc_example");

// SAML Provider
let provider = new auth.SAMLAuthProvider("saml_example");
// If your Auth Server is Oracle IDCS, the Social Sign-in flow is completed
// through the Oracle IDCS SSO page itself, and only IDCSAuthProvider is available.
// The Oracle IDCS SSO page allows choosing the Social Provider to login through.
final provider = IDCSAuthProvider();

// If you Auth Server is BASIC / LDAP, continue with:  
// Google
final provider = GoogleAuthProvider();

// Facebook
final provider = FacebookAuthProvider();

// Github
final provider = GithubAuthProvider();

// OIDC Provider
final provider = OAuthProvider("oidc_example");

// SAML Provider
final provider = SAMLAuthProvider("saml_example");

2. Start the Sign-in Flow:

a. Redirect Flow

import { signInWithRedirect, getRedirectResult } from "fusabase/auth";

// Start sign in with redirect flow
signInWithRedirect(auth, provider);

// After the user completes sign-in and returns to the app, obtain sign-in result by calling getRedirectResult()
getRedirectResult(auth)
  .then((result) => {
    var credential = result.credential;

    // OAuth access and id tokens can also be retrieved:
    var accessToken = credential.accessToken;
    var idToken = credential.idToken;
  })
  .catch((error) => {
    // Handle error.
  });
// Start sign in with redirect flow
auth.signInWithRedirect(provider);

// After the user completes sign-in and returns to the app, obtain sign-in result by calling getRedirectResult()
auth.getRedirectResult()
  .then((result) => {
    var credential = result.credential;

    // OAuth access and id tokens can also be retrieved:
    var accessToken = credential.accessToken;
    var idToken = credential.idToken;
  })
  .catch((error) => {
    // Handle error.
  });

Note:

This is valid only for web platform.

await auth.signInWithRedirect(provider);

// After the user completes sign-in and returns to the app, obtain sign-in result by calling getRedirectResult()
UserCredential credential = await auth.getRedirectResult();

b. Popup Flow

import { signInWithPopup } from "fusabase/auth";

// After the user completes sign-in and returns to the app, obtain sign-in result by calling getRedirectResult()
signInWithPopup(auth, provider)
  .then((result) => {
    var credential = result.credential;

    // OAuth access and id tokens can also be retrieved:
    var accessToken = credential.accessToken;
    var idToken = credential.idToken;
  })
  .catch((error) => {
    // Handle error.
  });
auth.signInWithPopup(provider)
  .then((result) => {
    var credential = result.credential;

    // OAuth access and id tokens can also be retrieved:
    var accessToken = credential.accessToken;
    var idToken = credential.idToken;
  })
  .catch((error) => {
    // Handle error.
  });
// supports mobile devices as well
UserCredential credential = await auth.signInWithPopup(provider);

c. Manual Sign-In Flow

Note:

Manual flow is not supported when the Auth Server is Oracle IDCS.

Note:

Providers like Facebook and Github mint Opaque Access Tokens. For the manual flow to work properly, it is necessary that these access tokens have the scope permissions to read the email of the user.

Facebook requires scope: public_profile, email

Github requires scope: read:user, user:email

import { OAuthProvider, GoogleAuthProvider, FacebookAuthProvider, GithubAuthProvider, SAMLAuthProvider, signInWithCredential } from "fusabase/auth";

// Get the id token or access token from the provider
// How you get the token, it can be using Native SDKs for the Auth Providers
// like Google, Facebook web SDKs

// Create a credential object 
// using Google ID token
const authCredential = GoogleAuthProvider.credential(idToken, null);

// using Facebook Access token
const authCredential = FacebookAuthProvider.credential(null, accessToken);

// using Github tokens
const authCredential = GithubAuthProvider.credential(null, accessToken);

// using OIDC Token
const authCredential = OAuthProvider.credential(idToken, null);

// using SAML Token
const authCredential = SAMLAuthProvider.credential(idToken);

signInWithCredential(auth, authCredential)
  .then((result) => {
    var credential = result.credential;

    // OAuth access and id tokens can also be retrieved:
    var accessToken = credential.accessToken;
    var idToken = credential.idToken;
  })
  .catch((error) => {
    // Handle error.
  });
// Get the id token or access token from the provider
// How you get the token, it can be using Native SDKs for the Auth Providers
// like Google, Facebook web SDKs

// Create a credential object 
// using Google ID token
const authCredential = auth.GoogleAuthProvider.credential(idToken, null);

// using Facebook Access token
const authCredential = auth.FacebookAuthProvider.credential(null, accessToken);

// using Github tokens
const authCredential = auth.GithubAuthProvider.credential(null, accessToken);

// using OIDC Token
const authCredential = auth.OAuthProvider.credential(idToken, null);

// using SAML Token
const authCredential = auth.SAMLAuthProvider.credential(idToken);
 

auth.signInWithCredential(authCredential)
  .then((result) => {
    var credential = result.credential;

    // OAuth access and id tokens can also be retrieved:
    var accessToken = credential.accessToken;
    var idToken = credential.idToken;
  })
  .catch((error) => {
    // Handle error.
  });
// Get the id token or access token from the provider
AuthCredential credential = provider.credential({
    idToken: idToken,
	accessToken: accessToken
});

// use the AuthCredential to create the UserCredential
UserCredential credential = await auth.signInWithCredential(credential);

11.6.2 Android Sign-In Flows

Oracle Backend for Firebase's Java Android SDK enables developers to use the manual flow or the Chrome Custom Tabs flow to allow user login through Social Accounts.

a. Manual Flow

1. Get the valid ID Token or Access Token from the Social ID Provider Android SDKs.

The following are the examples for Google and Facebook.

a. Integrate Sign in with Google into your app by following the steps in the Credential Manager documentation. Here are the high-level instructions:

  1. Instantiate a Google sign in request using GetGoogleIdOption. Then, create the Credential Manager request using GetCredentialRequest:

    import androidx.credentials.GetCredentialRequest;
    import com.google.android.libraries.identity.googleid.GetGoogleIdOption;
    
    GetGoogleIdOption googleIdOption = new GetGoogleIdOption.Builder()
            .setFilterByAuthorizedAccounts(true)
            .setServerClientId(getString(R.string.default_web_client_id))
            .build();
    
    // Create the Credential Manager request
    GetCredentialRequest request = new GetCredentialRequest.Builder()
            .addCredentialOption(googleIdOption)
            .build();

    In the request above, you must pass your "server" client ID to the setServerClientId method. To find the OAuth 2.0 client ID:

    1. Open the Credentials page in the Google Cloud console.
    2. The Web application type client ID is your backend server's OAuth 2.0 client ID.
  2. In order to trigger the Google Sign-In popup, use the following snippet after you have initialized your GetCredentialRequest and configured your Web Client ID.
    import android.annotation.SuppressLint;
    import android.os.Bundle;
    import android.util.Log;
    import android.widget.Toast;
    
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.core.content.ContextCompat;
    import androidx.credentials.Credential;
    import androidx.credentials.CredentialManager;
    import androidx.credentials.CredentialManagerCallback;
    import androidx.credentials.GetCredentialResponse;
    import androidx.credentials.exceptions.GetCredentialException;
    
    import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential;
    
    import java.util.concurrent.Executor;
    
    // Inside your Activity method
    CredentialManager credentialManager = CredentialManager.create(this);
    Executor executor = ContextCompat.getMainExecutor(this);
    
    credentialManager.getCredentialAsync(
        this,
        request, // Your pre-configured GetCredentialRequest
        null,    // cancellationSignal
        executor,
        new CredentialManagerCallback<GetCredentialResponse, GetCredentialException>() {
            @Override
            public void onResult(GetCredentialResponse result) {
                // Successfully retrieved credential
                handleSignIn(result.getCredential());
            }
    
            @SuppressLint("RestrictedApi")
            @Override
            public void onError(GetCredentialException e) {
                Log.e("AuthError", "Credential Manager Error: " + e.getMessage());
                Toast.makeText(MainActivity.this, "Sign-in failed: " + e.getMessage(), Toast.LENGTH_SHORT).show();
            }
        }
    );
  3. Check that after you integrate Sign in with Google, your sign-in activity has code similar to the following:
    import android.os.Bundle;
    import android.util.Log;
    import androidx.credentials.Credential;
    import androidx.credentials.CustomCredential;
    import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential;
    import static com.google.android.libraries.identity.googleid.GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL;
    
    private void handleSignIn(Credential credential) {
        // Check if credential is of type Google ID
        if (credential instanceof CustomCredential customCredential
                && credential.getType().equals(TYPE_GOOGLE_ID_TOKEN_CREDENTIAL)) {
            // Create Google ID Token
            Bundle credentialData = customCredential.getData();
            GoogleIdTokenCredential googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credentialData);
    
            // Sign in using the token
            authenticateWithToken(googleIdTokenCredential.getIdToken(), null);
        } else {
            Log.w(TAG, "Credential is not of type Google ID!");
        }
    }

Integrate Facebook Login into your app by following the developer's documentation. When you configure the LoginButton or LoginManager object, you must request the public_profile and email permissions. If you integrated Facebook Login using a LoginButton, your sign-in activity has code similar to the following:

// Initialize Facebook Login button
mCallbackManager = CallbackManager.Factory.create();
LoginButton loginButton = findViewById(R.id.button_sign_in);
loginButton.setReadPermissions("email", "public_profile");
loginButton.registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() {
    @Override
    public void onSuccess(LoginResult loginResult) {
        Log.d(TAG, "facebook:onSuccess:" + loginResult);
        authenticateWithToken(null, loginResult.getAccessToken());
    }

    @Override
    public void onCancel() {
        Log.d(TAG, "facebook:onCancel");
    }

    @Override
    public void onError(FacebookException error) {
        Log.d(TAG, "facebook:onError", error);
    }
});
// ...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Pass the activity result back to the Facebook SDK
    mCallbackManager.onActivityResult(requestCode, resultCode, data);
}

Providers like Facebook and Github mint Opaque Access Tokens. For the manual flow to work properly, it is necessary that these access tokens have the scope permissions to read the email of the user.

Facebook requires scope: public_profile, email

Github requires scope: read:user, user:email

2. Use the ID token or Access Token to create the AuthCredential Object and Exchange for Access Token.

import com.oracle.mobile.fusabase.auth.FusabaseAuth;
import com.oracle.mobile.fusabase.auth.FusabaseUser;
import com.oracle.mobile.fusabase.auth.AuthCredential;
import com.oracle.mobile.fusabase.auth.GoogleAuthProvider;
import com.oracle.mobile.fusabase.auth.FacebookAuthProvider;
import com.oracle.mobile.fusabase.auth.GithubAuthProvider;
import com.oracle.mobile.fusabase.auth.OAuthProvider;
import com.oracle.mobile.fusabase.auth.SAMLAuthProvider;
import android.util.Log;
import androidx.annotation.NonNull;
import com.oracle.mobile.fusabase.task.OnCompleteListener;
import com.oracle.mobile.fusabase.task.Task;

/**
 * Exchanges the Social Provider token for a credential recognized by our authentication
 * service and signs the user in using that credential.
 */
private void authenticateWithToken(String idToken, String accessToken) {
	
	FusabaseAuth mAuth = FusabaseAuth.getInstance();

    // Create a credential object 
	// using Google ID token
    AuthCredential authCredential = GoogleAuthProvider().getCredential(idToken, null);

	// using Facebook Access token
	AuthCredential authCredential = FacebookAuthProvider.getCredential(accessToken);

	// using Github tokens
	AuthCredential authCredential = GithubAuthProvider.getCredential(accessToken);

	// using OIDC Token
	AuthCredential authCredential = OAuthProvider.newCredentialBuilder("oidc_example")
												 .setIdTokenWithRawNonce(idToken, null)
												 .build();

    // using SAML Token
	AuthCredential authCredential = SAMLAuthProvider.newCredentialBuilder("saml_example")
												 .setIdTokenWithRawNonce(idToken, null)
												 .build();

    // Attempt to sign in with the generated credential
    mAuth.signInWithCredential(authCredential)
            .addOnCompleteListener(this, task -> {
                if (task.isSuccessful()) {

                    // Authentication successful — retrieve the signed-in user
                    Log.d(TAG, "Authentication successful");
                    FusabaseUser signedInUser = mAuth.getCurrentUser();

                    // Update the UI for the authenticated state
                    refreshUIForUser(signedInUser);

                } else {

                    // Authentication failed — log the error and show the sign-in UI
                    Log.w(TAG, "Authentication failed", task.getException());
                    refreshUIForUser(null);
                }
            });
}

Note:

Manual Flow is not supported when Auth Server is Oracle IDCS.

b. Custom Tabs Flow

  1. Create an instance of the AuthProvider you want to login through.
    import com.oracle.mobile.fusabase.auth.IDCSAuthProvider;
    import com.oracle.mobile.fusabase.auth.GoogleAuthProvider;
    import com.oracle.mobile.fusabase.auth.FacebookAuthProvider;
    import com.oracle.mobile.fusabase.auth.GithubAuthProvider;
    import com.oracle.mobile.fusabase.auth.OAuthProvider;
    import com.oracle.mobile.fusabase.auth.SAMLAuthProvider;
    
    // If your Auth Server is Oracle IDCS, the Social Sign-in flow is completed
    // through the Oracle IDCS SSO page itself, and only IDCSAuthProvider is available.
    // The Oracle IDCS SSO page allows choosing the Social Provider to login through.
    IDCSAuthProvider provider = new IDCSAuthProvider(mAuth);
    
    // Google
    GoogleAuthProvider provider = new GoogleAuthProvider(mAuth);
    
    // Facebook
    FacebookAuthProvider provider = new FacebookAuthProvider(mAuth);
    
    // Github
    GithubAuthProvider provider = new GithubAuthProvider(mAuth);
    
    // OIDC Provider
    OAuthProvider.Builder provider = OAuthProvider.newBuilder("oidc_example").build();
    
    // SAML Provider
    SAMLAuthProvider.Builder provider = SAMLAuthProvider.newBuilder("saml_example").build();
  2. Authenticate with Fusabase using the provider object. This will take control of your UI by popping up a Custom Chrome Tab. As a result, do not reference your Activity in the OnSuccessListener and OnFailureListener that you attach as they will immediately detach when the operation starts the UI.
  3. You should first check if you've already received a response. Signing in with this method puts your Activity in the background, which means that it can be reclaimed by the system during the sign in flow. In order to make sure that you don't make the user try again if this happens, you should check if a result is already present.

    To check if there is a pending result, call getPendingAuthResult:

    import com.oracle.mobile.fusabase.auth.FusabaseAuth;
    import com.oracle.mobile.fusabase.auth.AuthResult;
    import android.util.Log;
    import androidx.annotation.NonNull;
    import com.oracle.mobile.fusabase.task.OnSuccessListener;
    import com.oracle.mobile.fusabase.task.OnFailureListener;
    import com.oracle.mobile.fusabase.task.Task;
    
    FusabaseAuth mAuth = FusabaseAuth.getInstance();
    
    Task<AuthResult> pendingResultTask = mAuth.getPendingAuthResult();
    if (pendingResultTask != null) {
        // There's something already here! Finish the sign-in for your user.
        pendingResultTask
                .addOnSuccessListener(
                        new OnSuccessListener<AuthResult>() {
                            @Override
                            public void onSuccess(AuthResult authResult) {
                                // User is signed in.
                            }
                        })
                .addOnFailureListener(
                        new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                // Handle failure.
                            }
                        });
    } else {
        // There's no pending result so you need to start the sign-in flow.
        // See below.
    }
  4. To start the sign in flow:
    import com.oracle.mobile.fusabase.auth.FusabaseAuth;
    import com.oracle.mobile.fusabase.auth.AuthResult;
    import com.oracle.mobile.fusabase.auth.AuthProvider;
    import com.oracle.mobile.fusabase.auth.GoogleAuthProvider;
    import android.util.Log;
    import androidx.annotation.NonNull;
    import com.oracle.mobile.fusabase.task.OnSuccessListener;
    import com.oracle.mobile.fusabase.task.OnFailureListener;
    
    FusabaseAuth mAuth = FusabaseAuth.getInstance();
    
    mAuth.startActivityForSignInWithProvider(/* activity= */ this, provider)
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // User is signed in.
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure.
                        }
                    });

11.6.3 iOS Sign-In Flows

Oracle Backend for Firebase's Swift iOS SDK enables developers to use the manual flow or the Custom Tabs flow to allow user login through Social Accounts.

a. Manual Flow

1. Get the valid ID Token or Access Token from the Social ID Provider iOS SDKs.

Here are the examples for Google and Facebook

  1. Add the Google Sign-In SDK to your project
    1. In Xcode, with your app project open, navigate to File > Add Packages.
    2. When prompted, add the Google Sign-In SDK repository: https://github.com/google/GoogleSignIn-iOS
    3. When finished, Xcode will automatically begin resolving and downloading your dependencies in the background.

  2. Implement Google Sign-In
    1. Add custom URL schemes to your Xcode project:
    2. Open your project configuration: click the project name in the left tree view. Select your app from the TARGETS section, then select the Info tab, and expand the URL Types section.
    3. Click the + button, and add a URL scheme for your reversed client ID. To find this value, open the GoogleService-Info.plist configuration file, and look for the REVERSED_CLIENT_ID key. Copy the value of that key, and paste it into the URL Schemes box on the configuration page. Leave the other fields untouched.
    4. Add the GIDClientID key to your Info.plist with your iOS Client ID value from the GoogleService-Info.plist.
    5. Add the GIDServerClientID key to your Info.plist and paste your Web Client ID as the value.
    6. Add this code to your SceneDelegate.swift to ensure your app processes the login result after the browser returns control to your application:
      import GoogleSignIn
      func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        // ...
      }
        return GIDSignIn.sharedInstance.handle(url)
      }
    7. Pass the presenting view controller to the Google Sign-In signIn method and authenticate using the resulting ID and access tokens:
      import GoogleSignIn
      
      // Start the sign-in flow
      GIDSignIn.sharedInstance.signIn(withPresenting: viewController) { result, error in
          // Handle potential errors (e.g., user cancellation)
          if let error = error {
              print("Sign-in error: \(error.localizedDescription)")
              return
          }
      
          // Safely extract the user and tokens
          guard let user = result?.user,
                let idToken = user.idToken?.tokenString else {
              print("Missing user or ID token")
              return
          }
          
          let accessToken = user.accessToken.tokenString
      
          // Pass tokens to your backend authentication handler
          authenticateWithToken(idToken, accessToken)
      }

Providers like Facebook and Github mint Opaque Access Tokens. For the manual flow to work properly, it is necessary that these access tokens have the scope permissions to read the email of the user.

Facebook requires scope: public_profile, email

Github requires scope: read:user, user:email

  1. Integrate Facebook Login into your app by following the developer's documentation. When you initialize the FBSDKLoginButton object, set a delegate to receive login and logout events. For example:

    let loginButton = FBSDKLoginButton()
    loginButton.delegate = self
  2. In your delegate, implement didCompleteWithResult:error:

    func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
      if let error = error {
        print(error.localizedDescription)
        return
      }
      // ...
      authenticateWithToken(accessToken: AccessToken.current!.tokenString)
    }

Providers like Facebook and Github mint Opaque Access Tokens. For the manual flow to work properly, it is necessary that these access tokens have the scope permissions to read the email of the user.

Facebook requires scope: public_profile, email

Github requires scope: read:user, user:email

2. Use the ID token or Access Token to create the AuthCredential Object and Exchange for Oracle Backend for Firebase Access Token

import FusabaseAuth
/**
 * Exchanges the Social Provider token for a credential recognized by our authentication
 * service and signs the user in using that credential.
 */
func authenticateWithToken(idToken: String?, accessToken: String?) {
    // Create a credential object 
	// using Google ID token
    let authCredential = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: accessToken)

	// using Facebook Access token
	let authCredential = FacebookAuthProvider.credential(withAccessToken: accessToken)

	// using Github token
	let authCredential = GithubAuthProvider.credential(withAccessToken: accessToken)

	// using OIDC Token
	let authCredential = OAuthProvider.credential(providerID: 'oidc_example', idToken: idToken)

    // using SAML Token
	let authCredential = SAMLAuthProvider.credential(providerID: 'saml_example', idToken: idToken)

    // Attempt to sign in with the generated credential
    FusabaseAuth.auth().signIn(with: authCredential) { authResult, error in
		// ...
	}
}

Note:

Manual Flow is not supported when Auth Server is Oracle IDCS.

b. Customs Tabs Flow

  1. Create an instance of the AuthProvider you want to login through.
    import FusabaseAuth
    
    // If your Auth Server is Oracle IDCS, the Social Sign-in flow is completed
    // through the Oracle IDCS SSO page itself, and only IDCSAuthProvider is available.
    // The Oracle IDCS SSO page allows choosing the Social Provider to login through.
    
    // Using Google's Access Token
    let googleCredential = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: accessToken)
    // Using Facebook Access token
    let facebookCredential = FacebookAuthProvider.credential(withAccessToken: accessToken!)
    // Using GitHub token
    let githubCredential = GithubAuthProvider.credential(withToken: accessToken!)
    // Using OIDC Token
    let oidcCredential = OAuthProvider.credential(providerID: "oidc_example", idToken: idToken!)
    // Using SAML Token
    let samlCredential = SAMLAuthProvider.credential(providerID: "saml_example", idToken: idToken!)
  2. Authenticate with Fusabase using the system browser (Safari). This launches a Safari web authentication session and temporarily hands UI control over to the system. Because the system manages the presentation, avoid holding references to your view controller - the UI may be dismissed as soon as the authentication flow starts. The system manages the session lifecycle and resumes execution when the flow completes. If the app is suspended or resumed during authentication, the session state is preserved and the method either returns successfully or throws an error.

  3. To start the sign in flow:
    import FusabaseAuth
    
    do {
        // Create the OAuth provider
        let provider = OAuthProvider(providerID: providerID)
        
        // Get credential with default presentation context
        let userCredential = try await provider.getCredentialWith()
        
        // User is signed in automatically by getCredentialWith()
        print("User signed in successfully")
        print("User: \(userCredential.user.email ?? "No email")")
        
    } catch {
        print("Sign-in failed: \(error.localizedDescription)")
    }

11.7 Link Social Accounts

Users can be allowed to sign in to an Oracle Backend for Firebase application using multiple sign-in methods by linking the Auth provider credentials to an existing user account. The Auth provider being linked should share the same email address as the current user. For example, a user who signed in with a password can link a Google or a Facebook account and sign in with any of the methods in the future.

Link Auth Provider Credentials to a User Account

To link Auth Provider credentials to an existing user account:

  1. Sign in a user using any authentication provider or method.
  2. There are separate ways to link the new Auth provider:
a: Similar to the Manual Flow for Signing In, get the credentials from the new Auth Provider, but do not call the signInWithCredential. Instead, we will call the linkWithCredential().

Create an AuthCredential Object. For example:

import { GoogleAuthProvider } from "fusabase/auth";

const credential = GoogleAuthProvider.credential({
    idToken: idToken,
	accessToken: accessToken
});

Use the credential to link the user:

import { linkWithCredential } from "fusabase/auth";

linkWithCredential(auth.currentUser, credential)
.then(result => {
 // link successful
})

Create an AuthCredential Object. For example:

const credential = auth.GoogleAuthProvider.credential({
    idToken: idToken,
	accessToken: accessToken
});

Use the credential to link the user:

auth.currentUser.linkWithCredential(credential)
.then(result => {
 // link successful
})

Create an AuthCredential Object. For example:

import com.oracle.mobile.fusabase.auth.AuthCredential;
import com.oracle.mobile.fusabase.auth.GoogleAuthProvider;
import com.oracle.mobile.fusabase.auth.EmailAuthProvider;

AuthCredential credential = GoogleAuthProvider.getCredential(googleIdToken);
// or if you want to allow email-password login
// for an account registered via some social provider
AuthCredential credential = EmailAuthProvider.getCredential(email, password);

Use the AuthCredential Object to link the user:

import com.oracle.mobile.fusabase.auth.FusabaseAuth;
import com.oracle.mobile.fusabase.auth.FusabaseUser;
import com.oracle.mobile.fusabase.auth.AuthResult;
import com.oracle.mobile.fusabase.auth.AuthCredential;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.oracle.mobile.fusabase.task.OnCompleteListener;
import com.oracle.mobile.fusabase.task.Task;

FusabaseAuth mAuth = FusabaseAuth.getInstance();
        
// Assume you have a credential from previous step
AuthCredential credential = EmailAuthProvider.getCredential("user@example.com", "password");

// Link the credential to current user
if (mAuth.getCurrentUser() != null) {
    mAuth.getCurrentUser().linkWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "linkWithCredential:success");
                        FusabaseUser user = task.getResult().getUser();
                        updateUI(user);
                    } else {
                        Log.w(TAG, "linkWithCredential:failure", task.getException());
                        Toast.makeText(AuthActivity.this, "Authentication failed.",
                                Toast.LENGTH_SHORT).show();
                        updateUI(null);
                    }
                }
            });
}

Create AuthCredential Object:

import FusabaseAuth

let credential = GoogleAuthProvider.credential(withIDToken: idToken,
                                               accessToken: authentication.accessToken)
// or if you want to allow email-password login
// for an account registered via some social provider
let credential = EmailAuthProvider.credential(withEmail: email, password: password)

Use the AuthCredential Object to link the user:

import FusabaseAuth

let auth = FusabaseAuth.auth()

if let user = auth.currentUser {
    // Link credential using async/await
    do {
         let authResult = try await user.link(credential)
         print("Credential linked successfully")
         // authResult.user contains the updated user information
     } catch {
         print("Error linking credential: \(error.localizedDescription)")
     }
}
// Get the id token or access token from the provider
AuthCredential credential = GoogleAuthProvider.credential({
    idToken: idToken,
	accessToken: accessToken
});

// or if you want to allow email-password login
// for an account registered via some social provider
AuthCredential credential = EmailAuthProvider.credential({
	email: email,
	password: password
});

// Use the AuthCredential object to link the user
await auth.currentUser.linkWithCredential(credential);

If the call to linkWithCredential succeeds, the user can now sign in using any linked authentication provider.

b. Similar to the Redirect/Popup Flow for signing In, we start a new activity / window to link the new authentication provider to the current logged-in user.

Redirect Flow:

import { linkWithRedirect, getRedirectResult } from "fusabase/auth";

// Start linking with redirect flow
linkWithRedirect(auth.currentUser, provider);

// After the user completes sign-in and returns to the app, obtain sign-in result by calling getRedirectResult()
getRedirectResult(auth)
  .then((result) => {
    var credential = result.credential;

    // OAuth access and id tokens can also be retrieved:
    var accessToken = credential.accessToken;
    var idToken = credential.idToken;
  })
  .catch((error) => {
    // Handle error.
  });

Popup Flow:

import { linkWithPopup } from "fusabase/auth";

linkWithPopup(auth.currentUser, provider)
	.then(result => {
	    var credential = result.credential;
	})
	.catch((error) => {
    	// Handle error.
  	});

Redirect Flow:

// Start linking with redirect flow
auth.currentUser.linkWithRedirect(provider);

// After the user completes sign-in and returns to the app, obtain sign-in result by calling getRedirectResult()
auth.getRedirectResult()
  .then((result) => {
    var credential = result.credential;

    // OAuth access and id tokens can also be retrieved:
    var accessToken = credential.accessToken;
    var idToken = credential.idToken;
  })
  .catch((error) => {
    // Handle error.
  });

Popup Flow:

auth.currentUser.linkWithPopup(provider)
	.then(result => {
	    var credential = result.credential;
	})
	.catch((error) => {
    	// Handle error.
  	});
import com.oracle.mobile.fusabase.auth.FusabaseAuth;
import com.oracle.mobile.fusabase.auth.FusabaseUser;
import com.oracle.mobile.fusabase.auth.AuthResult;
import com.oracle.mobile.fusabase.auth.AuthProvider;
import com.oracle.mobile.fusabase.auth.GoogleAuthProvider;
import android.util.Log;
import androidx.annotation.NonNull;
import com.oracle.mobile.fusabase.task.OnSuccessListener;
import com.oracle.mobile.fusabase.task.OnFailureListener;
import com.oracle.mobile.fusabase.task.Task;

FusabaseAuth mAuth = FusabaseAuth.getInstance();
// Create the provider (e.g., Google)
AuthProvider provider = GoogleAuthProvider.getInstance();

// Start activity for linking with provider
if (mAuth.getCurrentUser() != null) {
    mAuth.getCurrentUser()
         .startActivityForLinkWithProvider(/* activity= */ this, provider)
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // User successfully linked with provider
                            Log.d(TAG, "User linked with provider successfully");
                            FusabaseUser user = authResult.getUser();
                            updateUI(user);
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure
                            Log.e(TAG, "Failed to link with provider", e);
                            updateUI(null);
                        }
                    });
}
import FusabaseAuth

let currentUser = FusabaseAuth.auth().currentUser

// Create OAuth provider synchronously
let provider = OAuthProvider(providerID: "google")

do {
    let result = try await currentUser.link(with: provider)
    print("Successfully linked with Google")
} catch {
    print("Failed to link: \(error.localizedDescription)")
}

Redirect Flow:

// Start linking with redirect flow
auth.currentUser.linkWithRedirect(provider);

// After the user completes sign-in and returns to the app, obtain sign-in result by calling getRedirectResult()
getRedirectResult(auth)
  .then((result) => {
    var credential = result.credential;

    // OAuth access and id tokens can also be retrieved:
    var accessToken = credential.accessToken;
    var idToken = credential.idToken;
  })
  .catch((error) => {
    // Handle error.
  });

Popup Flow (Supports Mobile Devices):

auth.currentUser.linkWithPopup(provider)
	.then(result => {
	    var credential = result.credential;
	})
	.catch((error) => {
    	// Handle error.
  	});

If the flow is successful, the user can now sign in using any linked authentication provider.

11.7.1 Unlink Social Accounts

You can unlink an Auth provider from an account, so that the user can no longer sign in with that provider.

import { unlink } from "fusabase/auth";

unlink(auth.currentUser, providerId).then(() => {
  // Auth provider unlinked from account
  // ...
}).catch((error) => {
  // An error happened
  // ...
});
auth.currentUser.unlink(providerId).then(() => {
  // Auth provider unlinked from account
  // ...
}).catch((error) => {
  // An error happened
  // ...
});
import com.oracle.mobile.fusabase.auth.FusabaseAuth;
import com.oracle.mobile.fusabase.auth.FusabaseUser;
import com.oracle.mobile.fusabase.auth.AuthResult;
import android.util.Log;
import androidx.annotation.NonNull;
import com.oracle.mobile.fusabase.task.OnCompleteListener;
import com.oracle.mobile.fusabase.task.Task;

FusabaseAuth mAuth = FusabaseAuth.getInstance();

AuthProvider provider = GoogleAuthProvider.getInstance();

// Start activity for linking with provider
mAuth = FusabaseAuth.getInstance();
        
// Example provider ID to unlink (e.g., "google.com", "facebook.com", "github.com")
String providerId = "google.com";

// Unlink the provider from current user
mAuth.getCurrentUser().unlink(providerId)
        .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    // Auth provider unlinked from account
                    Log.d(TAG, "Provider " + providerId + " unlinked successfully");
                    FusabaseUser user = task.getResult().getUser();
                    updateUI(user);
                } else {
                    Log.w(TAG, "Failed to unlink provider " + providerId, task.getException());
                }
            }
        });
import FusabaseAuth

let currentUser = FusabaseAuth.auth().currentUser 

do {
    let result = try await currentUser.unlink(fromProvider: providerId)
    // Auth provider unlinked from account
    print("Provider \(providerId) unlinked successfully")
} catch {
    print("Failed to unlink provider: \(error.localizedDescription)")
}
var updatedUser = await auth.currentUser.unlink(providerId);

11.8 Persistence Settings

Use persistence settings to control how long a user stays signed in and where the SDK stores tokens. This choice affects user experience, cross-tab behavior, and how you handle shared devices.

Session maintenance across client platforms uses JSON Web Tokens (JWTs) and refresh tokens. The SDK stores token state in platform-native storage and SDK settings.

Web

The Web SDK (JS Modular and JS Namespace) lets you choose how to persist the signed-in user. JS Namespace defaults to local persistence when available. JS Modular defaults to in-memory persistence unless you configure it. If you want a "stay signed in" behavior in JS Modular, call setPersistence before sign-in or immediately after app initialization.

  • When LOCAL Persistence is set, the Auth State is persisted even when the browser tab is closed and reopened, and the same Auth State is shared by all the tabs of the browser.
  • When SESSION Persistence is set, the Auth State is persisted for the current session or the current tab of the browser.
  • When NONE Persistence is set, the Auth State is stored in memory and will be cleared on a tab or window refresh.

Choose LOCAL when you want a "stay signed in" experience across browser restarts. Use SESSION or NONE for shared devices, kiosks, or sensitive apps where you want the session to clear when the tab closes or reloads.

import { getAuth, setPersistence, signInWithEmailAndPassword } from "fusabase/auth";
import { browserSessionPersistence, inMemoryPersistence, browserLocalPersistence } from "fusabase/auth";

const auth = getAuth();
setPersistence(auth, browserSessionPersistence)
  .then(() => {
    // Existing and future Auth states are now persisted in the current
    // session only. Closing the window would clear any existing state even
    // if a user forgets to sign out.
    // ...
    // New sign-in will be persisted with session persistence.
    return signInWithEmailAndPassword(auth, email, password);
  })
  .catch((error) => {
    // Handle Errors here.
    const errorCode = error.code;
    const errorMessage = error.message;
  });
fusabase.auth().setPersistence(fusabase.auth().Persistence.SESSION)
  .then(() => {
    // Existing and future Auth states are now persisted in the current
    // session only. Closing the window would clear any existing state even
    // if a user forgets to sign out.
    // ...
    // New sign-in will be persisted with session persistence.
    return fusabase.auth().signInWithEmailAndPassword(email, password);
  })
  .catch((error) => {
    // Handle Errors here.
    var errorCode = error.code;
    var errorMessage = error.message;
  });
await auth.setPersistence(Persistence.SESSION);

final userCredential = await auth.signInWithEmailAndPassword(
  email: 'email@example.com',
  password: 'password123',
);

The following behavior can be seen across various browser tabs:

  • Users can sign in using SESSION or NONE persistence with different users on multiple tabs. Each tab cannot see the state of the other tab.
  • Any attempt to sign in using LOCAL persistence will be detected and synchronized on all tabs. If the user was previously signed in on a specific tab using SESSION or NONE persistence, that state will be cleared.
  • If the user was previously signed in using LOCAL persistence with multiple tabs opened and then switches to NONE or SESSION persistence in one tab, the state of that tab will be modified with the user persisted in SESSION or NONE, and on all other tabs, the user will be signed out.

Use LOCAL if you want a single sign-in state across tabs and consistent sign-out everywhere.

Android

Android SDK ensures that the App user does not need to log in on every visit of the application by storing the Auth State in SharedPreferences in a secure manner, using Android KeyStore APIs.

iOS

iOS SDK ensures that the App user does not need to log in on every visit of the application by storing the Auth State in a secure manner using Apple's KeyChain APIs.