Sign In With Passkey
This guide shows how to authenticate with a passkey, using LoginID.
We recommend always offering passkey autofill as an option for your users, as it provides the best user experience.
Prerequisites
- Create an application to obtain a base URL
Setup SDK
- Javascript
- Kotlin
- Swift
npm i @loginid/websdk3
Import and initialize an instance:
import { LoginIDWebSDK } from "@loginid/websdk3";
const lid = new LoginIDWebSDK({
baseUrl: process.env.LOGINID_BASE_URL,
});
Initialize a singleton configuration for the LoginID service in the application's onCreate
method.
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
// Initialize the singleton instance
val config = LoginIDServiceConfig("<BASE_URL>")
LoginID.configure(config).client()
}
}
Configure the singleton instance of LIDClient
with a base URL during the app's launch in the AppDelegate
.
import LoginID
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
{
// Initialize the singleton instance
LIDClient.shared.configure(baseURL: "<BASE_URL>")
return true
}
}
Authenticate With Passkey
Call the authenticateWithPasskey method, passing the email or username. The user will authenticate with a passkey, and the response will include a LoginID token.
The LoginID token is stored locally, allowing it to be used across different components or pages without needing to re-authenticate.
- Javascript
- Kotlin
- Swift
import React, { useState } from "react";
import { useAuth } from "../../contexts/AuthContext";
import { LoginIDWebSDK } from "@loginid/websdk3";
const lid = new LoginIDWebSDK({
baseUrl: process.env.REACT_APP_LOGINID_BASE_URL,
});
const Login: React.FC = () => {
const [username, setUsername] = useState<string>("");
const [error, setError] = useState<string>("");
const { setAuthUser } = useAuth();
const handlePasskeyLogin = async (e: React.FormEvent) => {
e.preventDefault();
try {
// User authenticates with passkey
const authResult = await lid.authenticateWithPasskey(username);
if (authResult.isAuthenticated) {
// You can return LoginID token to your backend for verification (authResult.token)
setAuthUser(user);
} else {
// Default to your fallback CIAM authentication method
}
} catch (e) {
if (e instanceof Error) {
setError(e.message);
}
}
};
};
If you wish to use webauthn autofill
, you can see Passkey Autofill guide
import loginid.LoginID
class MainActivity : AppCompatActivity() {
private lateinit var usernameEditText: EditText
private lateinit var errorTextView: TextView
private lateinit var authenticateButton: Button
private fun handleAuthenticate() {
val username = usernameEditText.text.toString()
errorTextView.text = ""
GlobalScope.launch(Dispatchers.Main) {
try {
// User authenticates with passkey
val result = LoginID.client().authenticateWithPasskey(this@MainActivity, username)
// You can now send the authToken to be verified on your server
AuthContext.setAuthUser(user)
} catch (e: Exception) {
when (e) {
is LoginIDError -> {
errorTextView.text = e.message ?: "A LoginID error occurred"
}
else -> {
errorTextView.text = e.message ?: "An error occurred"
}
}
}
}
}
}
// AppDelegate.swift
import UIKit
import PasskeySDK
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Configure the LoginID SDK with your base URL and app ID
LIDClient.shared.configure(baseURL: "<BASE_URL>", appID: "<APP_ID>")
return true
}
// Include any other necessary AppDelegate methods...
}
// ViewController.swift
import UIKit
import PasskeySDK
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Your UI setup code here...
}
@IBAction func loginButtonTapped(_ sender: Any) {
let username = "billy@loginid.io"
let options = LIDAuthenticationOptions() // or nil
LIDClient.shared.authenticateWithPasskey(
anchor: self.view.window!,
username: username,
options: options,
onComplete: { authResponse, error in
DispatchQueue.main.async {
if let error = error {
// Handle error scenario
print("Login failed with error: \(error.errorMessage)")
} else {
// Handle successful authentication
print("Login successful with response: \(response.jwtAccess)")
}
}
}
)
}
}
Once you have received the result LoginID token, you can send it to your backend, and verify it. For detailed technical instructions, refer to this section on verifying LoginID tokens.