Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
f1c4123
docs: add docs
ncooke3 Jan 8, 2026
abfa6d3
review
ncooke3 Jan 8, 2026
779bd6a
wrap to 80
ncooke3 Jan 9, 2026
f948d2a
emphasize types we dont own
ncooke3 Jan 9, 2026
fc46b9b
reasier to read
ncooke3 Jan 9, 2026
c45c803
Feedback
ncooke3 Jan 9, 2026
9fca0bf
fdbk
ncooke3 Jan 9, 2026
d795779
fdbk
ncooke3 Jan 9, 2026
f151765
fdbk
ncooke3 Jan 9, 2026
038f296
fix ori
ncooke3 Jan 9, 2026
316401f
docs
ncooke3 Jan 9, 2026
d2e7f9c
b
ncooke3 Jan 9, 2026
8821cc3
b
ncooke3 Jan 9, 2026
bc09dd5
padding
ncooke3 Jan 9, 2026
21ebcd0
b
ncooke3 Jan 9, 2026
2113800
b
ncooke3 Jan 9, 2026
6e8b1af
b
ncooke3 Jan 9, 2026
82a5529
b
ncooke3 Jan 9, 2026
6083465
b
ncooke3 Jan 9, 2026
e7f525e
b
ncooke3 Jan 9, 2026
8ce6ad7
b
ncooke3 Jan 9, 2026
fd2c1e6
b
ncooke3 Jan 9, 2026
9807398
b
ncooke3 Jan 9, 2026
e021f09
b
ncooke3 Jan 9, 2026
a937cd7
b
ncooke3 Jan 9, 2026
67ea37f
b
ncooke3 Jan 9, 2026
2d7a055
b
ncooke3 Jan 9, 2026
397b9cc
b
ncooke3 Jan 9, 2026
51c3854
b
ncooke3 Jan 9, 2026
70fab43
b
ncooke3 Jan 9, 2026
14310bb
b
ncooke3 Jan 9, 2026
08396e3
b
ncooke3 Jan 9, 2026
8117e71
b
ncooke3 Jan 9, 2026
2e18fd0
b
ncooke3 Jan 9, 2026
620d979
b
ncooke3 Jan 9, 2026
a59b2ba
b
ncooke3 Jan 9, 2026
835e833
b
ncooke3 Jan 9, 2026
56138eb
b
ncooke3 Jan 9, 2026
9af2ddb
b
ncooke3 Jan 9, 2026
d2c05ec
b
ncooke3 Jan 9, 2026
80cb6d2
b
ncooke3 Jan 9, 2026
e13ec89
b
ncooke3 Jan 9, 2026
6da0bbe
b
ncooke3 Jan 9, 2026
e52dc69
b
ncooke3 Jan 9, 2026
55c4149
b
ncooke3 Jan 9, 2026
b330e00
b
ncooke3 Jan 9, 2026
3277e79
b
ncooke3 Jan 10, 2026
3d81ca2
b
ncooke3 Jan 10, 2026
e5c4d8e
b
ncooke3 Jan 10, 2026
76b5604
b
ncooke3 Jan 10, 2026
50f9dad
b
ncooke3 Jan 10, 2026
ae9b6c3
b
ncooke3 Jan 10, 2026
3315a31
b
ncooke3 Jan 12, 2026
bb77a50
b
ncooke3 Jan 12, 2026
18576a1
b
ncooke3 Jan 12, 2026
fbd2489
b
ncooke3 Jan 12, 2026
4b006f4
b
ncooke3 Jan 12, 2026
54897e2
b
ncooke3 Jan 12, 2026
1149547
b
ncooke3 Jan 12, 2026
362f40b
b
ncooke3 Jan 12, 2026
74c3f7d
b
ncooke3 Jan 12, 2026
8e5973c
Revert "b"
ncooke3 Jan 12, 2026
fa2da39
renew
ncooke3 Jan 12, 2026
382ba4f
b
ncooke3 Jan 12, 2026
ddaf306
b
ncooke3 Jan 14, 2026
fdaa82d
b
ncooke3 Jan 14, 2026
d53352d
b
ncooke3 Jan 14, 2026
7a1688d
Revert "b"
ncooke3 Jan 14, 2026
e9d9388
b
ncooke3 Jan 14, 2026
85f2bf5
b
ncooke3 Jan 14, 2026
3c47659
b
ncooke3 Jan 15, 2026
7c05850
b
ncooke3 Jan 15, 2026
5c73e75
b
ncooke3 Jan 15, 2026
a0f4ba3
b
ncooke3 Jan 15, 2026
cddc37f
b
ncooke3 Jan 15, 2026
00b64e5
b
ncooke3 Jan 15, 2026
cbfeca4
b
ncooke3 Jan 15, 2026
96b075c
b
ncooke3 Jan 15, 2026
3d0ec5d
b
ncooke3 Jan 15, 2026
486eeb6
B
ncooke3 Jan 15, 2026
a2df167
b
ncooke3 Jan 15, 2026
4087dbe
b
ncooke3 Jan 15, 2026
acfcc32
b
ncooke3 Jan 15, 2026
c01956b
b
ncooke3 Jan 15, 2026
c447f25
b
ncooke3 Jan 15, 2026
b0ec775
b
ncooke3 Jan 20, 2026
7fa305b
b
ncooke3 Jan 20, 2026
b630696
b
ncooke3 Jan 20, 2026
41a3258
b
ncooke3 Jan 20, 2026
7b221f9
callouts
ncooke3 Jan 20, 2026
dce848b
better summary
ncooke3 Jan 20, 2026
a6a2b1e
tables
ncooke3 Jan 20, 2026
ac47a33
b
ncooke3 Jan 21, 2026
b73c44f
fixes
ncooke3 Apr 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions docs/api-reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# API Reference

This section provides a high-level overview of the main classes and protocols within `AppCheckCore`. For detailed API documentation, please refer to the header files directly.

## Core Classes

### `GACAppCheck`
The central class for managing App Check tokens. It serves as the primary entry point for your application to interact with the App Check system.

* **Purpose:** Manages the lifecycle of App Check tokens, including fetching, caching, and refreshing. It delegates attestation logic to an `GACAppCheckProvider` instance.
* **Key Methods:**
* `tokenForcingRefresh:completion:`: Requests an App Check token, with an option to force a refresh, bypassing the cache.
* `limitedUseTokenWithCompletion:`: Requests a limited-use App Check token, which does not affect the primary token's refresh cycle.

### `GACAppCheckSettings`
Provides configurable settings for the `AppCheckCore` library.

* **Purpose:** Allows customization of various behaviors, such as token refresh intervals or logging levels.

### `GACAppCheckToken`
Represents an App Check token received from the App Check backend.

* **Properties:**
* `token` (`NSString *`): The actual App Check token string.
* `expirationDate` (`NSDate *`): The date and time when the token expires.

### `GACAppCheckTokenResult`
A wrapper object containing either an `GACAppCheckToken` upon success or an `NSError` upon failure.

* **Properties:**
* `token` (`GACAppCheckToken * _Nullable`): The App Check token if the request was successful.
* `error` (`NSError * _Nullable`): An error object if the token request failed.

## Protocols

### `GACAppCheckProvider`
A protocol that defines the interface for App Check providers. Custom providers must conform to this protocol.

* **Purpose:** Abstracts the specifics of how App Check tokens are obtained. Implementations interact with platform-specific attestation services or provide mock tokens.
* **Key Methods:**
* `getTokenWithCompletion:`: Asynchronously fetches a new App Check token.
* `getLimitedUseTokenWithCompletion:`: Asynchronously fetches a new limited-use App Check token.

### `GACAppCheckTokenDelegate`
A protocol for delegates that wish to receive notifications about App Check token updates.

* **Purpose:** Allows your application to react to changes in the App Check token, such as when a new token is fetched or an existing one is refreshed.
* **Key Methods:**
* `appCheck:didChangeToken:`: Notifies the delegate when the App Check token changes.
97 changes: 97 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Architecture & Design

This document details the internal architecture of `AppCheckCore`,
focusing on token storage, lifecycle management, and security
mechanisms.

> [!WARNING]
> This document describes internal implementation details that are subject
> to change. Rely only on the public API surface for integration
> (see [App Check Core Documentation](index.md#important-disclaimer)).

## Token Storage
App Check tokens are sensitive credentials that grant access to your
backend resources. `AppCheckCore` treats them with high security.

### Keychain Storage
The `GACAppCheckStorage` class is responsible for persisting App Check
tokens.
* **Mechanism:** It uses the iOS Keychain via `GULKeychainStorage`.
* **Service Name:** `com.google.app_check_core.token_storage`.
* **Data Protection:** Tokens are stored as `GACAppCheckStoredToken`
objects (conforming to `NSSecureCoding`).
* **Access Groups:** Supports sharing tokens across apps/extensions
via Keychain Access Groups (configurable during initialization).

### Artifact Storage (App Attest)
For the App Attest provider, intermediate artifacts are also stored to
maintain a stable device identity.
* **Class:** `GACAppAttestArtifactStorage`
* **Storage:** Keychain.
* **Key Suffix:** Keys are namespaced by the service name and resource
name (e.g., `my-sdk.projects/123/apps/abc`) to prevent collisions.

## Token Lifecycle Management
The `GACAppCheck` class acts as the central coordinator.

1. **Request:** The app requests a token via
`token(forcingRefresh:completion:)`.
2. **Cache Check:**
* If `forcingRefresh` is `NO`: Checks `GACAppCheckStorage` for a
valid, non-expired token.
* **Buffer Time:** Tokens are considered "expired" slightly before
their actual expiration time to account for clock skew and
network latency.
3. **Fetch (if needed):**
* If the cache is empty or expired, or `forcingRefresh` is `YES`,
a request is made to the configured `GACAppCheckProvider`.
4. **Storage:**
* Upon successful retrieval, the new token is written to
`GACAppCheckStorage`.
* Any old token is overwritten.
5. **Completion:** The token (cached or new) is returned to the caller.

## Exponential Backoff Strategy
To prevent overwhelming the backend or Apple's servers during failures,
`AppCheckCore` implements a robust exponential backoff strategy via
`GACAppCheckBackoffWrapper`.

### Algorithm
The backoff interval is calculated as follows:
```math
Interval = \min(Base \times Jitter, MaxInterval)
```
* **Base:** $`2^{retryCount}`$ seconds.
* **Jitter:** A random multiplier between $1.0$ and $1.5$ (to prevent
thundering herd problems).
* **MaxInterval:** 4 hours.

### Error Policies
The backoff behavior depends on the error type, specifically HTTP status
codes returned by the backend:

| HTTP Status Code | Backoff Type | Reason |
| :--- | :--- | :--- |
| **< 400** | **None** | Network errors or successful requests do not trigger backoff. |
| **400 (Bad Request)**<br>**404 (Not Found)** | **1 Day** | Indicates a project misconfiguration or outdated app version. Unlikely to resolve quickly. |
| **403 (Forbidden)**<br>**429 (Too Many Requests)**<br>**503 (Service Unavailable)** | **Exponential** | Indicates soft deletion, rate limiting, or server overload. Retrying later is appropriate. |
| **Other 5xx** | **Exponential** | Standard server errors. |

### Implementation
* **Class:** `GACAppCheckBackoffWrapper`
* **Usage:** Providers (`GACAppAttestProvider`, `GACDeviceCheckProvider`)
wrap their network and attestation calls in this backoff mechanism.
* **State:** The wrapper tracks the failure count and the last failure
time. It resets to 0 upon a successful token fetch.

## Threading Model
* **Concurrency:** `AppCheckCore` is designed to be thread-safe.
* **Queues:**
* **Main Queue:** Completion handlers are typically dispatched to
the main queue.
* **Internal Queues:** Providers use private serial queues (e.g.,
`com.google.GACAppAttestProvider`) to manage state and
sequentialize complex attestation flows (like generating a key,
then attesting, then exchanging).
* **Background:** Network requests are performed on background
queues (`QOS_CLASS_DEFAULT` or `QOS_CLASS_UTILITY`).
85 changes: 85 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# App Check Core - Documentation

## Introduction
`AppCheckCore` is the underlying engine for app attestation and token
management, primarily used by the Firebase iOS SDK but designed for
broader internal Google use. It provides a robust and secure way to
verify the authenticity of app instances accessing your backend
resources. This library supports applications running on iOS, macOS,
tvOS, and watchOS.

## Key Features
* **Token Management:** Handles the lifecycle of App Check tokens,
including caching and automatic refreshing to ensure continuous
protection.
* **Provider Abstraction:** Abstracts different attestation providers,
allowing for flexible integration with various platform-specific
integrity mechanisms.
* **Limited-Use Tokens:** Supports the generation and management of
limited-use tokens for scenarios requiring single-use or short-lived
authentication.

> [!IMPORTANT]
> **The detailed architectural and implementation documentation within this
> `docs/` directory, especially the deep dives into provider internals and
> decision logic, are provided for comprehensive understanding only.**
>
> **Consumers of the App Check Core library should exclusively rely on the
> public API surface (as defined by the public header files, e.g., in
> `AppCheckCore/Sources/Public`) for integration. Internal implementation
> details, including specific error handling flows, storage mechanisms, and
> concurrency management described herein, are subject to change without
> notice across library versions.**

## Documentation Sections

* [Usage Guide](usage.md): How to initialize and fetch tokens.
* [Providers Deep Dive](providers.md): Detailed architectural
breakdown of App Attest, DeviceCheck, and Debug providers,
including sequence diagrams.
* [Architecture](architecture.md): Internal design details regarding
token storage, caching strategies, and threading.
* [API Reference](api-reference.md): High-level class overview.

## High-Level Architecture
This diagram illustrates the core relationships. For detailed sequence
flows, see [Providers Deep Dive](providers.md).

```mermaid
classDiagram
class GACAppCheck {
+tokenForcingRefresh:completion:
+limitedUseTokenWithCompletion:
}

class GACAppCheckProvider {
<<protocol>>
+getTokenWithCompletion:
+getLimitedUseTokenWithCompletion:
}

class GACAppAttestProvider {
-AppAttestService
-KeyStorage
-ArtifactStorage
}

class GACDeviceCheckProvider {
-DCDevice
}

class GACAppCheckDebugProvider {
-LocalDebugToken
}

class GACAppCheckToken {
+token: String
+expirationDate: Date
}

GACAppCheck "1" *-- "1" GACAppCheckProvider : uses
GACAppCheckProvider <|-- GACAppAttestProvider : implements
GACAppCheckProvider <|-- GACDeviceCheckProvider : implements
GACAppCheckProvider <|-- GACAppCheckDebugProvider : implements
GACAppCheck --> GACAppCheckToken : returns
```
15 changes: 15 additions & 0 deletions docs/providers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# App Check Providers: Deep Dive

This section details the internal design and detailed flows of each
App Check provider, including error handling, retries, and state
resets.

Select a provider below for detailed documentation:

* [AppAttest Provider](providers/app-attest.md)
* The primary provider for modern iOS devices, wrapping `DCAppAttestService`.
* Features complex state management, automatic retries, and request coalescing.
* [DeviceCheck Provider](providers/device-check.md)
* A fallback provider for older devices using `DCDevice`.
* [Debug Provider](providers/debug.md)
* For local development and CI/CD environments.
Loading
Loading