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. The SDK uses this base URL to interact with the LoginID authentication service.
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,
});
First, ensure you have the Maven Central repository in your project's settings.gradle.kts file:
repositories {
google()
mavenCentral()
}
Next, add the SDK and required dependencies to your app module's build.gradle.kts:
dependencies {
// LoginID SDK
implementation("io.loginid:auth:1.0.1")
}
Import the class within your application:
import io.loginid.auth
class MainActivity : AppCompatActivity() {
val lid = LoginIDAuth(this, "<LOGINID_BASE_URL>")
override fun onCreate() {
super.onCreate()
// Additional setup...
}
}
Add the SDK dependency using Swift Package Manager in Xcode:
- In Xcode, open your project.
- Go to File → Add Package Dependencies….
- In the search bar, paste:
https://github.com/loginid1/loginid-ios
- Select the target(s) where you want to add the SDK and click Add Package.
Import the class within your view models:
import LoginIDAuth
@main
struct MyApp: App {
private let lid: LoginIDAuth
init() {
LoginIDAuth(baseUrl: "<LOGINID_BASE_URL>")
// Other setup code...
}
}
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
This method automatically uses the WebAuthn Signal API to keep a user’s passkeys synchronized between the authenticator and the LoginID server. This helps ensure that passkey information shown in the browser remains up-to-date, including helping remove revoked or stale passkeys from the user's authenticator.
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 androidx.lifecycle.lifecycleScope
import io.loginid.auth.LoginIDAuth
import io.loginid.core.errors.LoginIDError
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
private lateinit var usernameEditText: EditText
private lateinit var errorTextView: TextView
private lateinit var authenticateButton: Button
private val lid = LoginIDAuth(this, "<BASE_URL>")
private fun handleAuthenticate() {
val username = usernameEditText.text.toString()
errorTextView.text = ""
lifecycleScope.launch {
try {
// User authenticates with passkey
val result = lid.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"
}
}
}
}
}
}
import SwiftUI
import LoginIDAuth
@main
struct ExampleApp: App {
@State private var errorMessage: String? = nil
@State private var username: String = "user@example.com"
private let lid = LoginIDAuth(baseUrl: "<BASE_URL>")
private func handleAuthenticate() async {
do {
// User authenticates with passkey
let result = try await lid.authenticateWithPasskey(
username: username
)
// You can now send the authToken to be verified on your server
AuthContext.shared.setAuthUser(result.user)
} catch let error as LoginIDError {
errorMessage = error.message
} catch {
errorMessage = error.localizedDescription
}
}
}
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.