Attestation Validation API

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

POST /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

  1. Challenge Verification: Ensure challenge is valid and unused
  2. Tenant Identification: Extract bundle ID and team ID from attestation
  3. Apple Verification: Validate attestation with Apple's servers
  4. Certificate Chain: Verify the complete certificate chain
  5. Receipt Validation: Validate embedded App Store receipt
  6. Device Analysis: Analyze device patterns and calculate risk score
  7. 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
        }
    }
}

Next Steps