Integrator Quickstart
Get from zero to first successful authentication in 5 minutes
Integrator Quickstart
You want to add hardware-backed authentication to your app. This guide gets you to your first successful auth in about 5 minutes.
We’ll use the Node SDK — the Go SDK works the same way, just swap the imports.
[!NOTE] Pre-release build: Sigil Auth is not yet published to GitHub or npm. This guide assumes you’re working from the local monorepo at
/Volumes/Expansion/src/sigilauth/. Replace paths as needed for your environment.
What You’ll Need
- Docker installed
- Node 18+ or Go 1.21+
- Access to the Sigil Auth source code
- 10 minutes
Step 1: Start the Sigil service
Run the full stack with docker-compose. This gives you the auth server, push relay, and PostgreSQL database.
If you’re working from the published repo (once available):
git clone https://github.com/sigilauth/server.git
cd server
make up
If you’re working from the local development tree:
cd /Volumes/Expansion/src/sigilauth/server
make up
The service boots in init mode. You’ll see:
INFO: Sigil Auth starting in init mode
INFO: Visit https://localhost:8443/init to complete setup
Open https://localhost:8443/init in your browser. Your browser will warn about the self-signed certificate — that’s expected in development. Click through.
The wizard shows you a 24-word mnemonic. Write it down. You’ll need it if you restart the container.
Click “Continue” and the service generates its keypair. You’ll see the server’s pictogram — five emoji that identify this server. That’s it. The server is operational.
Step 2: Get an API key
The init wizard gives you a test API key that looks like:
sgk_test_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
Copy it. Never commit this to git.
Set it in your environment:
export SIGIL_API_KEY='sgk_test_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2'
Step 3: Install the SDK
[!NOTE] The SDK is not yet published to npm or as a standalone Go module. Use the local path from your monorepo.
Node:
# Once published:
npm install @sigilauth/sdk
# For now, use local path:
npm install file:../server/sdk-node
Go:
# Once published:
go get github.com/sigilauth/server/sdk-go
# For now, use local replace directive in go.mod:
replace github.com/sigilauth/server/sdk-go => ../server/sdk-go
Step 4: Create your first challenge
Here’s the complete flow. A challenge is a request for the user to prove they control their device by signing with their private key.
Node:
import { SigilAuth } from '@sigilauth/sdk';
const sigil = new SigilAuth({
serviceUrl: 'https://localhost:8443'
});
// Create challenge for a device
const challenge = await sigil.auth.createChallenge({
fingerprint: 'a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2',
device_public_key: 'Ag8xYzI3ZWRkNDUzYmNlYzVmMTJjNmI5MzA4OGY0...',
action: {
type: 'step_up',
description: 'Add security key',
params: { key_name: "Sarah's YubiKey" }
}
});
console.log('Challenge created:', challenge.challenge_id);
console.log('Pictogram:', challenge.pictogram);
console.log('Speakable:', challenge.pictogram_speakable);
// Push notification sent to device automatically
// Poll for result
const result = await sigil.auth.awaitResult(challenge.challenge_id, {
timeout: 60000, // 60 seconds
pollInterval: 2000 // check every 2 seconds
});
if (result.status === 'verified') {
console.log('User approved! Signature verified.');
} else if (result.status === 'rejected') {
console.log('User denied the request.');
} else {
console.log('Challenge expired.');
}
Go:
package main
import (
"context"
"fmt"
"log"
"os"
"time"
"github.com/sigilauth/server/sdk-go"
)
func main() {
client, err := sigilauth.New(sigilauth.Config{
ServiceURL: "https://localhost:8443",
APIKey: os.Getenv("SIGIL_API_KEY"),
HTTPTimeout: 30 * time.Second,
})
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
challenge, err := client.Auth.CreateChallenge(ctx, &sigilauth.ChallengeRequest{
Fingerprint: "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
DevicePublicKey: "Ag8xYzI3ZWRkNDUzYmNlYzVmMTJjNmI5MzA4OGY0...",
Action: sigilauth.Action{
Type: "step_up",
Description: "Add security key",
Params: map[string]string{"key_name": "Sarah's YubiKey"},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Challenge created: %s\n", challenge.ChallengeID)
fmt.Printf("Pictogram: %v\n", challenge.Pictogram)
// Poll for result
result, err := client.Auth.AwaitResult(ctx, challenge.ChallengeID, &sigilauth.AwaitOptions{
PollInterval: 1000, // ms
MaxAttempts: 30,
})
if err != nil {
log.Fatal(err)
}
switch result.Status {
case "verified":
fmt.Println("User approved! Signature verified.")
case "rejected":
fmt.Println("User denied the request.")
case "expired":
fmt.Println("Challenge expired.")
}
}
Where’s the device fingerprint coming from?
In the example above, fingerprint and device_public_key are placeholders. In your real app, these come from device registration.
When a user pairs their phone with your app:
- The mobile app generates a keypair in the device’s secure hardware (Secure Enclave on iOS, StrongBox on Android)
- The app sends the public key to your backend
- Your backend stores
user_id → device_public_keyin your database - The device fingerprint is
SHA256(device_public_key)— Sigil’s SDK calculates this for you, or you can compute it yourself
Check the App Onboarding Guide for the full pairing flow, or see the self-hosting guide for how to wire up your app’s backend.
What happens on the device?
When you call createChallenge, Sigil:
- Generates a cryptographic challenge (random bytes)
- Signs it with the server’s private key
- Sends a push notification to the device via APNs (iOS) or FCM (Android)
The device:
- Receives the push
- Verifies the server’s signature
- Shows the action to the user (“Approve: Add security key”)
- Prompts for biometric (Face ID, fingerprint, etc.)
- Signs the challenge with the device’s private key
- Sends the signed response back to Sigil
Sigil verifies the device’s signature against the public key you provided and marks the challenge as verified or rejected.
Next Steps
- CLI Device Tool — Test authentication flows without a mobile device (perfect for CI and local development)
- SDK documentation — Full API reference for the Node SDK
- Go SDK documentation — Full API reference for the Go SDK
- Self-hosting guide — Deploy Sigil Auth with Docker in production
- MPA setup — Configure multi-party approval for sensitive actions
- App onboarding — How users pair their phones and approve requests
That’s it. You’ve created your first challenge and seen how the SDK works. From here, you can wire this into your app’s authentication flow, configure webhooks for async notification, or set up multi-party approval for destructive actions.