Skip to content

Commit c79587e

Browse files
[150] Concepts Docs Update (#74)
* refactor(docs): update concepts content pages * fix(docs): update architecture diagram * fix(docs): broken links
1 parent ec60413 commit c79587e

16 files changed

+1841
-356
lines changed
Lines changed: 126 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,133 @@
11
# Architecture
22

3-
Some contracts can be classified into the following categories:
3+
The FastAuth contract system is organized into several categories based on their responsibilities:
44

5-
- `Guard` - A middleware contract that checks if the request is authenticated.
6-
- `GuardRouter` - A contract that routes the request to the appropriate guard contract.
5+
- **Entry Point** - The `FastAuth` contract serves as the main gateway for users to interact with the system.
6+
- **Router** - The `JwtGuardRouter` contract routes verification requests to the appropriate guard based on the authentication provider.
7+
- **Guards** - Middleware contracts that verify JWT tokens from specific identity providers (Auth0, Firebase, Custom Issuers).
8+
- **Attestation** - The `Attestation` contract manages decentralized public key updates through a quorum-based system.
79

8-
The following diagram shows the architecture of the contracts and how they interact with the MPC:
10+
## Contract Interaction Flow
911

10-
![Contracts](./fa-contracts.png)
12+
1. **User Request**: The user calls the `sign` function on the `FastAuth` contract with their JWT token and the payload to sign.
13+
2. **Guard Resolution**: `FastAuth` resolves the guard contract based on the `guard_id` prefix. If the prefix is `jwt`, the request is routed to `JwtGuardRouter`.
14+
3. **JWT Verification**: The appropriate guard contract verifies the JWT signature and claims.
15+
4. **MPC Signing**: Upon successful verification, `FastAuth` forwards the signing request to the MPC network.
16+
5. **Signature Return**: The MPC signature is returned to the user.
1117

12-
The architecture is composed of the following contracts:
18+
### Contract Architecture Diagram
1319

14-
- [FastAuth](./architecture_contracts_fa.md) - The main contract. It acts as the gateway to perform signatures via [MPC](./architecture_mpc.md). Accessible to the end-user.
15-
- [JwtGuardRouter](./architecture_contracts_jwt-guard-router.md) - A contract that routes JWT verification requests to the appropriate guard contract.
16-
- [Auth0Guard](./architecture_contracts_auth0-guard.md) - A guard contract that verifies a JWT token forged through Auth0.
20+
```
21+
┌─────────┐
22+
│ User │
23+
└────┬────┘
24+
│ 1. sign(JWT + payload)
25+
26+
27+
┌─────────────────────────────────┐
28+
│ FastAuth │
29+
│ (Entry Point) │
30+
└────┬────────────────────────────┘
31+
│ 2. guard_id prefix = 'jwt'
32+
33+
34+
┌─────────────────────────────────┐
35+
│ JwtGuardRouter │
36+
│ (Router) │
37+
└───┬──────┬──────┬───────────────┘
38+
│ │ │
39+
│ 3a │ 3b │ 3c
40+
│ │ │
41+
▼ ▼ ▼
42+
┌──────┐ ┌──────────┐ ┌──────────────────┐
43+
│Auth0 │ │Firebase │ │ CustomIssuer │
44+
│Guard │ │Guard │ │ Guard │
45+
└───┬──┘ └────┬─────┘ └────────┬─────────┘
46+
│ │ │
47+
│ │ Verify │ Verify
48+
│ │ public keys │ public keys
49+
│ │ │
50+
│ ▼ ▼
51+
│ ┌──────────────────────────┐
52+
│ │ Attestation │
53+
│ │ (Key Management) │
54+
│ └──────────────────────────┘
55+
56+
│ 4. Verification success
57+
58+
59+
┌─────────────────────────────────┐
60+
│ FastAuth │
61+
│ (Entry Point) │
62+
└────┬────────────────────────────┘
63+
│ 5. Forward signing request
64+
65+
66+
┌─────────────────────────────────┐
67+
│ MPC Network │
68+
│ (Signing Service) │
69+
└────┬────────────────────────────┘
70+
│ 6. Return signature
71+
72+
73+
┌─────────────────────────────────┐
74+
│ FastAuth │
75+
│ (Entry Point) │
76+
└────┬────────────────────────────┘
77+
│ 7. Return signature
78+
79+
80+
┌─────────┐
81+
│ User │
82+
└─────────┘
83+
```
84+
85+
**Flow Description:**
86+
87+
1. **User** calls `sign()` on **FastAuth** with JWT token and payload
88+
2. **FastAuth** routes to **JwtGuardRouter** when `guard_id` prefix is `jwt`
89+
3. **JwtGuardRouter** delegates to the appropriate guard:
90+
- **Auth0Guard** (3a)
91+
- **FirebaseGuard** (3b) - verifies keys via **Attestation**
92+
- **CustomIssuerGuard** (3c) - verifies keys via **Attestation**
93+
4. Guards return verification success to **FastAuth**
94+
5. **FastAuth** forwards signing request to **MPC Network**
95+
6. **MPC Network** returns signature to **FastAuth**
96+
7. **FastAuth** returns signature to **User**
97+
98+
## Contract Categories
99+
100+
### Entry Point
101+
102+
- [FastAuth](./architecture_contracts_fa.md) - The main contract that manages guards, verifies payloads via delegation, and coordinates MPC signing. Supports multiple signature algorithms: `secp256k1`, `ecdsa`, and `eddsa`.
103+
104+
### Router
105+
106+
- [JwtGuardRouter](./architecture_contracts_jwt-guard-router.md) - A registry and router for JWT guard contracts. Delegates verification to the appropriate guard based on the guard name.
107+
108+
### Guards
109+
110+
All guard contracts implement the `JwtGuard` trait, which provides:
111+
- RS256 JWT signature verification
112+
- Issuer and expiration validation
113+
- Custom claims verification (specific to each guard type)
114+
115+
| Guard | Provider | Key Management | Custom Claims |
116+
|-------|----------|----------------|---------------|
117+
| [Auth0Guard](./architecture_contracts_auth0-guard.md) | Auth0 | Owner-managed | `fatxn` claim matching |
118+
| [FirebaseGuard](./architecture_contracts_firebase-guard.md) | Firebase | Attestation-based | OIDC hash claim matching |
119+
| [CustomIssuerGuard](./architecture_contracts_custom-issuer-guard.md) | Custom OIDC | DAO-managed | OIDC hash claim matching |
120+
121+
### Supporting Infrastructure
122+
123+
- [Attestation](./architecture_contracts_attestation.md) - Decentralized public key management through attester quorum consensus.
124+
125+
## Security Model
126+
127+
The architecture implements multiple layers of security:
128+
129+
1. **JWT Verification**: Guards verify the cryptographic signature of JWT tokens using RS256.
130+
2. **Claim Validation**: Each guard validates specific claims (issuer, expiration, custom claims).
131+
3. **Quorum-Based Key Updates**: The attestation contract ensures public keys can only be updated when multiple trusted attesters agree.
132+
4. **Role-Based Access Control**: Administrative functions are protected by role-based permissions (DAO, CodeStager, CodeDeployer, etc.).
133+
5. **Pause Functionality**: Critical contracts support pausing to mitigate security incidents.
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
# Attestation
2+
3+
The `Attestation` contract manages decentralized public key updates through a quorum-based consensus mechanism. Multiple trusted attesters must agree on the same public keys before they are accepted. This contract is used by the `FirebaseGuard` to source its public keys in a trust-minimized manner.
4+
5+
## Features
6+
7+
- Quorum-based public key attestation requiring multiple attesters to agree.
8+
- Role-based access control (DAO, Attester, CodeStager, CodeDeployer, DurationManager, PauseManager, UnpauseManager).
9+
- Pausable contract for emergency situations.
10+
- Upgradable contract with staged deployments.
11+
- Safe attester management that prevents quorum violations.
12+
13+
## Contract State
14+
15+
| Field | Type | Description |
16+
|-------|------|-------------|
17+
| `attestations` | `IterableMap<AccountId, Attestation>` | Current attestations from each attester |
18+
| `quorum` | `u32` | Number of matching attestations required to update keys |
19+
| `public_keys` | `Vector<PublicKey>` | Currently active public keys |
20+
21+
### PublicKey Structure
22+
23+
```rust
24+
pub struct PublicKey {
25+
n: Vec<u8>, // RSA modulus
26+
e: Vec<u8>, // RSA exponent
27+
}
28+
```
29+
30+
### Attestation Structure
31+
32+
```rust
33+
pub struct Attestation {
34+
hash: Vec<u8>, // SHA256 hash of the public keys
35+
public_keys: Vec<PublicKey>, // The attested public keys
36+
}
37+
```
38+
39+
## Roles
40+
41+
| Role | Permissions |
42+
|------|-------------|
43+
| `DAO` | Full administrative access, can attest, manage quorum, manage attesters |
44+
| `Attester` | Can submit public key attestations |
45+
| `CodeStager` | Can stage contract code updates |
46+
| `CodeDeployer` | Can deploy staged contract updates |
47+
| `DurationManager` | Can manage upgrade duration settings |
48+
| `PauseManager` | Can pause the contract |
49+
| `UnpauseManager` | Can unpause the contract |
50+
51+
## Initialization
52+
53+
```rust
54+
#[init]
55+
pub fn new(quorum: u32, super_admins: Vec<AccountId>, attesters: Vec<AccountId>) -> Self
56+
```
57+
58+
- `quorum`: Number of attesters that must agree before keys are updated.
59+
- `super_admins`: Accounts with full administrative privileges (also granted DAO role).
60+
- `attesters`: Initial accounts authorized to submit attestations.
61+
62+
**Validation**:
63+
- Quorum must be greater than 0.
64+
- At least one super admin is required.
65+
- Quorum cannot exceed the number of attesters.
66+
67+
## Attestation Process
68+
69+
### Submitting an Attestation
70+
71+
Accounts with the `Attester` or `DAO` role can submit attestations:
72+
73+
```rust
74+
#[pause]
75+
#[access_control_any(roles(Role::Attester, Role::DAO))]
76+
pub fn attest_public_keys(&mut self, public_keys: Vec<PublicKey>)
77+
```
78+
79+
**Process**:
80+
1. Validates that public keys are not empty and all components are valid.
81+
2. Computes the SHA256 hash of the concatenated public key data.
82+
3. Stores the attestation for the calling attester.
83+
4. Counts how many existing attestations have the same hash.
84+
5. If the count reaches quorum:
85+
- Updates the active public keys.
86+
- Clears all attestations to prepare for future updates.
87+
88+
### Example Flow
89+
90+
With a quorum of 2 and 3 attesters:
91+
92+
1. **Attester A** submits public keys `[PK1, PK2]` → Attestation stored, count = 1.
93+
2. **Attester B** submits public keys `[PK1, PK2]` → Same hash, count = 2, quorum reached!
94+
3. Public keys updated to `[PK1, PK2]`, all attestations cleared.
95+
96+
If **Attester C** had submitted different keys, the hashes wouldn't match and quorum wouldn't be reached.
97+
98+
## Querying State
99+
100+
### Get Public Keys
101+
102+
```rust
103+
pub fn get_public_keys(&self) -> Vec<PublicKey>
104+
```
105+
106+
Returns the currently active public keys (empty until quorum is first reached).
107+
108+
### Get Attestation
109+
110+
```rust
111+
pub fn get_attestation(&self, account_id: AccountId) -> Option<Attestation>
112+
```
113+
114+
Returns the current attestation from a specific attester.
115+
116+
### Get Quorum
117+
118+
```rust
119+
pub fn get_quorum(&self) -> u32
120+
```
121+
122+
### Get Attesters
123+
124+
```rust
125+
pub fn get_attesters(&self, from_index: u64, limit: u64) -> Vec<AccountId>
126+
```
127+
128+
Paginated list of accounts with the `Attester` role.
129+
130+
## Quorum Management
131+
132+
Only accounts with the `DAO` role can update the quorum:
133+
134+
```rust
135+
#[pause]
136+
#[access_control_any(roles(Role::DAO))]
137+
pub fn set_quorum(&mut self, quorum: u32)
138+
```
139+
140+
**Validation**: Quorum cannot exceed the current number of attesters.
141+
142+
## Attester Management
143+
144+
### Granting Attester Role
145+
146+
```rust
147+
#[pause]
148+
#[access_control_any(roles(Role::DAO))]
149+
pub fn grant_attester(&mut self, account_id: AccountId)
150+
```
151+
152+
### Revoking Attester Role
153+
154+
```rust
155+
#[pause]
156+
#[access_control_any(roles(Role::DAO))]
157+
pub fn revoke_attester(&mut self, account_id: AccountId)
158+
```
159+
160+
**Safety Check**: Cannot revoke an attester if doing so would make the quorum impossible to reach (i.e., if `quorum >= remaining_attesters`).
161+
162+
## Pause Functionality
163+
164+
The contract can be paused to prevent attestations during security incidents:
165+
166+
- **Pause**: Accounts with `PauseManager` or `DAO` role.
167+
- **Unpause**: Accounts with `UnpauseManager` or `DAO` role.
168+
169+
When paused, `attest_public_keys`, `set_quorum`, `grant_attester`, and `revoke_attester` are disabled.
170+
171+
## Security Considerations
172+
173+
### Hash Computation
174+
175+
The hash of public keys is computed by concatenating all modulus (`n`) and exponent (`e`) bytes:
176+
177+
```rust
178+
fn compute_public_keys_hash(&self, public_keys: &[PublicKey]) -> Vec<u8> {
179+
let mut data = Vec::new();
180+
for pk in public_keys {
181+
data.extend_from_slice(&pk.n);
182+
data.extend_from_slice(&pk.e);
183+
}
184+
env::sha256(&data).to_vec()
185+
}
186+
```
187+
188+
This ensures:
189+
- Attesters must agree on the exact same keys in the same order.
190+
- Any difference in key data results in a different hash.
191+
192+
### Quorum Safety
193+
194+
The contract enforces several invariants:
195+
- Quorum can never exceed the number of attesters.
196+
- Revoking an attester is blocked if it would violate the quorum requirement.
197+
- These checks prevent the contract from entering an unrecoverable state.
198+
199+
## Integration with FirebaseGuard
200+
201+
The `FirebaseGuard` contract fetches its public keys from this contract:
202+
203+
1. `FirebaseGuard` calls `attestation_contract.get_public_keys()`.
204+
2. The returned keys are validated and stored in `FirebaseGuard`.
205+
3. These keys are then used to verify Firebase JWT signatures.
206+
207+
This design allows:
208+
- Decentralized key management without trusting a single party.
209+
- Key rotation through attester consensus rather than a single admin.
210+
- Separation of concerns between authentication and key management.

0 commit comments

Comments
 (0)