Attestation Validation API
Quick Start
Advanced Features
Attestation Validation
Deep dive into Grantiva's attestation validation process and how device authenticity is verified.
Overview
Attestation validation is the core of Grantiva's security. When your app submits an attestation, Grantiva performs multiple verification steps with Apple's servers and analyzes device intelligence to produce a comprehensive security assessment.
Validation Endpoint
/api/v1/attestation/validate
Validate an attestation object and receive a JWT token with device intelligence data.
Request Body
{
"keyId": "base64_encoded_key_id",
"attestation": "base64_encoded_attestation_object",
"challenge": "YmFzZTY0X2VuY29kZWRfY2hhbGxlbmdl"
}
Successful Response
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresAt": "2024-01-15T13:00:00Z",
"deviceIntelligence": {
"deviceId": "dev_abc123",
"riskScore": 15,
"deviceIntegrity": "high",
"jailbreakDetected": false,
"attestationCount": 42,
"firstSeen": "2024-01-01T00:00:00Z",
"lastSeen": "2024-01-15T12:00:00Z",
"riskFactors": []
},
"permissions": ["basic", "payments", "transfers"]
}
Validation Process
Step-by-Step Validation
- Challenge Verification: Ensure challenge is valid and unused
- Tenant Identification: Extract bundle ID and team ID from attestation
- Apple Verification: Validate attestation with Apple's servers
- Certificate Chain: Verify the complete certificate chain
- Receipt Validation: Validate embedded App Store receipt
- Device Analysis: Analyze device patterns and calculate risk score
- Token Generation: Issue JWT with device intelligence data
Device Intelligence
Risk Score Calculation
Risk scores range from 0-100, with lower scores indicating more trustworthy devices:
Score Range | Risk Level | Description |
---|---|---|
0-20 | Low | Trusted device with no risk indicators |
21-50 | Medium | Some anomalies detected, monitor closely |
51-75 | High | Multiple risk factors, restrict access |
76-100 | Critical | Severe compromise indicators |
Risk Factors
The following factors contribute to the risk score:
- Jailbreak Detection: +40-60 points if detected
- Invalid Receipt: +30-50 points for missing/invalid receipt
- Attestation Anomalies: +20-40 points for unusual patterns
- Geographic Anomalies: +10-30 points for impossible travel
- Device Age: +5-15 points for very new devices
- Attestation Frequency: +5-20 points for excessive requests
Validation Errors
Common Error Responses
// Invalid Challenge
{
"error": "invalid_challenge",
"message": "Challenge is expired or already used",
"code": "ATT_001"
}
// Invalid Attestation
{
"error": "invalid_attestation",
"message": "Attestation validation failed",
"code": "ATT_002",
"details": {
"reason": "certificate_chain_invalid"
}
}
// Bundle ID Mismatch
{
"error": "bundle_mismatch",
"message": "Bundle ID does not match registered tenant",
"code": "ATT_003"
}
// High Risk Device
{
"error": "high_risk_device",
"message": "Device risk score exceeds acceptable threshold",
"code": "ATT_004",
"riskScore": 85,
"riskFactors": ["jailbreak_detected", "invalid_receipt"]
}
Advanced Features
Custom Validation Rules (Enterprise)
Enterprise customers can configure custom validation rules:
{
"validationRules": {
"maxRiskScore": 50,
"requireValidReceipt": true,
"blockJailbrokenDevices": true,
"allowedCountries": ["US", "CA", "GB"],
"blockedCountries": [],
"minIOSVersion": "14.0",
"customChecks": [
{
"name": "business_hours",
"type": "time_based",
"config": {
"allowedHours": "09:00-17:00",
"timezone": "America/New_York"
}
}
]
}
}
Assertion Validation (Optional)
After initial attestation, subsequent requests can use assertions for better performance:
// Generate assertion (lighter than attestation)
let assertion = try await DCAppAttestService.shared.generateAssertion(
keyId,
clientDataHash: requestHash
)
// Validate assertion
let request = AssertionRequest(
keyId: keyId,
assertion: assertion.base64EncodedString(),
requestData: requestData
)
let response = try await validateAssertion(request)
Performance Considerations
Operation | Typical Latency | Notes |
---|---|---|
Challenge Generation | 10-50ms | Cached at edge locations |
Attestation Validation | 200-500ms | Includes Apple verification |
Assertion Validation | 50-100ms | Faster than attestation |
Integration Example
class SecurityService {
private let grantiva = Grantiva()
func authenticateDevice() async throws {
do {
// Perform attestation
let result = try await grantiva.validateAttestation()
// Check risk level
switch result.deviceIntelligence.riskScore {
case 0...20:
// Low risk - grant full access
await grantPermissions(["all"])
case 21...50:
// Medium risk - limited access
await grantPermissions(["read", "write"])
await logSecurityEvent("medium_risk_device", result)
case 51...75:
// High risk - read only
await grantPermissions(["read"])
await alertSecurityTeam("high_risk_device", result)
default:
// Critical risk - deny access
throw SecurityError.deviceCompromised
}
// Store token for API calls
await TokenManager.shared.store(result.token)
} catch {
// Handle attestation failure
await handleAttestationFailure(error)
throw error
}
}
}