Your First Attestation
Quick Start
Advanced Features
First Attestation
Step-by-step guide to completing your first device attestation with Grantiva.
Prerequisites
- Grantiva account created
- iOS app with Grantiva SDK integrated
- Backend server configured to validate JWT tokens
- Physical iOS device (iOS 14.0+)
Step 1: Verify Setup
iOS App Checklist
// AppDelegate.swift or App.swift
import Grantiva
import DeviceCheck
// Verify App Attest is available
if DCAppAttestService.shared.isSupported {
print("✅ App Attest is supported")
} else {
print("❌ App Attest not supported on this device")
}
Server Checklist
// Verify JWT secret is configured
console.log('JWT Secret configured:', !!process.env.GRANTIVA_JWT_SECRET);
// Test endpoint
app.get('/api/test-auth', authenticateToken, (req, res) => {
res.json({
status: 'authenticated',
deviceId: req.user.sub,
riskScore: req.user.deviceIntelligence.riskScore
});
});
Step 2: Implement Attestation Flow
iOS Implementation
import SwiftUI
import Grantiva
struct ContentView: View {
@State private var attestationStatus = "Not Started"
@State private var jwtToken: String?
@State private var riskScore: Int?
@State private var isLoading = false
private let grantiva = Grantiva()
var body: some View {
VStack(spacing: 20) {
Text("Grantiva Attestation Demo")
.font(.title)
VStack(alignment: .leading, spacing: 10) {
Label("Status: \(attestationStatus)", systemImage: statusIcon)
if let score = riskScore {
Label("Risk Score: \(score)/100", systemImage: "shield")
}
if jwtToken != nil {
Label("Token: Received ✅", systemImage: "key")
}
}
.padding()
.background(Color.gray.opacity(0.1))
.cornerRadius(10)
Button(action: performAttestation) {
if isLoading {
ProgressView()
.progressViewStyle(CircularProgressViewStyle())
} else {
Text("Start Attestation")
}
}
.buttonStyle(.borderedProminent)
.disabled(isLoading)
if jwtToken != nil {
Button("Test Authenticated API Call") {
testAuthenticatedCall()
}
.buttonStyle(.bordered)
}
}
.padding()
}
private var statusIcon: String {
switch attestationStatus {
case "Success": return "checkmark.circle.fill"
case "Failed": return "xmark.circle.fill"
default: return "circle"
}
}
private func performAttestation() {
isLoading = true
attestationStatus = "Attesting..."
Task {
do {
// Perform attestation
let result = try await grantiva.validateAttestation()
await MainActor.run {
if result.isValid {
attestationStatus = "Success"
jwtToken = result.token
riskScore = result.deviceIntelligence.riskScore
// Store token for API calls
UserDefaults.standard.set(result.token, forKey: "attestation_token")
print("Attestation successful!")
print("Device ID: \(result.deviceIntelligence.deviceId)")
print("Risk Score: \(result.deviceIntelligence.riskScore)")
print("Jailbreak Detected: \(result.deviceIntelligence.jailbreakDetected)")
} else {
attestationStatus = "Failed"
}
isLoading = false
}
} catch {
await MainActor.run {
attestationStatus = "Failed: \(error.localizedDescription)"
isLoading = false
}
}
}
}
private func testAuthenticatedCall() {
guard let token = jwtToken else { return }
Task {
var request = URLRequest(url: URL(string: "https://api.yourapp.com/api/test-auth")!)
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
do {
let (data, _) = try await URLSession.shared.data(for: request)
let response = try JSONDecoder().decode(TestResponse.self, from: data)
print("API Response: \(response)")
} catch {
print("API call failed: \(error)")
}
}
}
}
struct TestResponse: Codable {
let status: String
let deviceId: String
let riskScore: Int
}
Step 3: Run Your First Attestation
-
Build and run on a real device
Connect your iPhone and select it as the run destination in Xcode
-
Tap "Start Attestation"
The attestation process will begin
-
Monitor the console output
You'll see detailed logs about the attestation process
-
Check the results
View your risk score and attestation status
Step 4: Verify in Dashboard
After successful attestation, you can verify the device in your Grantiva dashboard:
- Log in to your Grantiva dashboard
- Navigate to Analytics → Devices
- Find your device by its ID or attestation time
- View detailed device intelligence and risk analysis
Common Issues and Solutions
App Attest Not Supported
Error: DCAppAttestService.shared.isSupported returns false
Solution: Ensure you're testing on a real device with iOS 14.0+ and in a supported region
Network Error
Error: Failed to connect to Grantiva servers
Solution: Check internet connection and ensure your bundle ID is registered in Grantiva
Invalid Bundle ID
Error: Bundle ID mismatch
Solution: Verify your app's bundle ID matches what's configured in your Grantiva account
JWT Validation Failed
Error: 403 Forbidden on API calls
Solution: Ensure your server has the correct JWT secret configured
Understanding Your Results
Risk Scores
- 0-20: Low risk - Normal device with no suspicious indicators
- 21-50: Medium risk - Some anomalies detected, monitor closely
- 51-75: High risk - Multiple risk factors present
- 76-100: Critical risk - Strong indicators of compromise
Device Intelligence Factors
- Jailbreak detection status
- App integrity verification
- Device consistency checks
- Historical attestation patterns
- Geographic anomalies
Next Steps
Congratulations! You've completed your first attestation. Here's what to do next: