The primary method for recording user activities and initiating authentication challenges. This is the core operation you’ll use throughout your application.
Custom UI
Pre-built UI
// Track an action on your backendconst result = await authsignal.track({ userId: "0272c312-e181-4cad-a494-43647b503a0a", action: "withdraw-funds", attributes: { deviceId: "555c17e1-3837-4f13-81bb-131e5597e168", ipAddress: "203.0.113.42", },});// Handle different action outcomesif (result.state === "CHALLENGE_REQUIRED") { // User needs to complete a challenge return { token: result.token, };} else if (result.state === "ALLOW") { // Proceed with the action return { success: true };} else if (result.state === "REVIEW") { // Action requires manual review return { status: "under_review", message: "Your request is being reviewed" };} else if (result.state === "BLOCK") { // Action is blocked return { error: "This action cannot be completed for security reasons" };}
// Track an action on your backendconst result = await authsignal.track({ userId: "0272c312-e181-4cad-a494-43647b503a0a", action: "withdraw-funds", attributes: { redirectUrl: "https://yourapp.com/callback", deviceId: "deviceId", ipAddress: "ipAddress", },});// Handle different action outcomesif (result.state === "CHALLENGE_REQUIRED") { // User needs to complete a challenge return { url: result.url, };} else if (result.state === "ALLOW") { // Proceed with the action return { success: true };} else if (result.state === "REVIEW") { // Action requires manual review return { status: "under_review", message: "Your request is being reviewed" };} else if (result.state === "BLOCK") { // Action is blocked return { error: "This action cannot be completed for security reasons" };}
When you track an action, you provide:
User ID - Unique identifier for the user
Action code - What the user is doing (e.g., “signIn”, “withdrawFunds”)
Attributes - Contextual information for risk assessment
Track actions at the point where authentication is needed:
async function handleSensitiveOperation(userId: string) { // Track the action first const result = await authsignal.track({ userId, action: "accessSensitiveData", attributes: { ipAddress: request.ip, userAgent: request.headers.userAgent } }); // Handle based on result switch (result.state) { case "ALLOW": return performSensitiveOperation(); case "CHALLENGE_REQUIRED": return { challengeUrl: result.url }; case "BLOCK": throw new Error("Access denied"); case "REVIEW": return { status: "pending_review" }; }}
Actions are automatically deduplicated using idempotency keys. Multiple calls with the same user ID, action, and idempotency key will return the same result.