add developer portal planning documentation (M01-M12)
This commit is contained in:
429
DEV_PORTAL_M04_AUTH.md
Normal file
429
DEV_PORTAL_M04_AUTH.md
Normal file
@@ -0,0 +1,429 @@
|
||||
# Milestone 4: Authentication System
|
||||
|
||||
**Status**: Planning
|
||||
**Goal**: Secure developer authentication and app signing infrastructure.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Authentication covers two areas:
|
||||
1. **Developer authentication** - Login to portal, API access
|
||||
2. **App signing** - Package integrity and developer verification
|
||||
|
||||
---
|
||||
|
||||
## Developer Authentication
|
||||
|
||||
### Methods Required
|
||||
|
||||
| Method | Use Case | Priority |
|
||||
|--------|----------|----------|
|
||||
| OAuth2 (GitHub) | Primary login | P0 |
|
||||
| OAuth2 (Google) | Alternative login | P1 |
|
||||
| Email + Password | Fallback | P2 |
|
||||
| API Keys | CLI tools, CI/CD | P0 |
|
||||
|
||||
### OAuth2 Flow
|
||||
|
||||
```
|
||||
┌─────────┐ ┌─────────┐ ┌──────────┐ ┌─────────┐
|
||||
│ Browser │────►│ Portal │────►│ Provider │────►│ Callback│
|
||||
└─────────┘ └─────────┘ │(GitHub) │ └────┬────┘
|
||||
└──────────┘ │
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ Create/Link │
|
||||
│ Account │
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
### OAuth2 Implementation
|
||||
|
||||
#### GitHub OAuth
|
||||
|
||||
```
|
||||
Authorization URL: https://github.com/login/oauth/authorize
|
||||
Token URL: https://github.com/login/oauth/access_token
|
||||
User Info: https://api.github.com/user
|
||||
Scopes: read:user, user:email
|
||||
```
|
||||
|
||||
#### Google OAuth
|
||||
|
||||
```
|
||||
Authorization URL: https://accounts.google.com/o/oauth2/v2/auth
|
||||
Token URL: https://oauth2.googleapis.com/token
|
||||
User Info: https://www.googleapis.com/oauth2/v2/userinfo
|
||||
Scopes: openid, email, profile
|
||||
```
|
||||
|
||||
### Session Management
|
||||
|
||||
#### JWT Tokens
|
||||
|
||||
```json
|
||||
{
|
||||
"sub": "dev_uuid",
|
||||
"email": "dev@example.com",
|
||||
"iat": 1704067200,
|
||||
"exp": 1704153600,
|
||||
"type": "access"
|
||||
}
|
||||
```
|
||||
|
||||
| Token Type | Lifetime | Storage |
|
||||
|------------|----------|---------|
|
||||
| Access Token | 1 hour | Memory/Cookie |
|
||||
| Refresh Token | 30 days | HttpOnly Cookie |
|
||||
|
||||
#### Token Refresh Flow
|
||||
|
||||
```
|
||||
1. Access token expires
|
||||
2. Client sends refresh token
|
||||
3. Server validates refresh token
|
||||
4. Issue new access + refresh tokens
|
||||
5. Invalidate old refresh token
|
||||
```
|
||||
|
||||
### API Key Authentication
|
||||
|
||||
#### Key Format
|
||||
|
||||
```
|
||||
mk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
│ │ └── 32 random bytes (base62)
|
||||
│ └── Environment (live/test)
|
||||
└── Prefix (mosis key)
|
||||
```
|
||||
|
||||
#### Key Storage
|
||||
|
||||
```sql
|
||||
-- Only store hash, never the key itself
|
||||
INSERT INTO api_keys (
|
||||
developer_id,
|
||||
name,
|
||||
key_hash, -- bcrypt or argon2
|
||||
key_prefix, -- "mk_live_abc" for display
|
||||
permissions
|
||||
) VALUES (...);
|
||||
```
|
||||
|
||||
#### Key Permissions
|
||||
|
||||
```json
|
||||
{
|
||||
"permissions": [
|
||||
"apps:read",
|
||||
"apps:write",
|
||||
"versions:upload",
|
||||
"telemetry:read"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
| Endpoint Category | Limit | Window |
|
||||
|-------------------|-------|--------|
|
||||
| Auth endpoints | 10 | 1 minute |
|
||||
| API (authenticated) | 1000 | 1 hour |
|
||||
| API (per key) | 100 | 1 minute |
|
||||
| Upload | 10 | 1 hour |
|
||||
|
||||
---
|
||||
|
||||
## App Signing
|
||||
|
||||
### Key Generation
|
||||
|
||||
#### Algorithm: Ed25519
|
||||
|
||||
```
|
||||
Private key: 32 bytes (256 bits)
|
||||
Public key: 32 bytes (256 bits)
|
||||
Signature: 64 bytes (512 bits)
|
||||
```
|
||||
|
||||
#### Why Ed25519?
|
||||
- Fast signing and verification
|
||||
- Small key and signature sizes
|
||||
- No configuration choices (secure by default)
|
||||
- Widely supported
|
||||
|
||||
### Key Generation Flow
|
||||
|
||||
```bash
|
||||
# Developer generates keypair locally
|
||||
mosis keys generate
|
||||
|
||||
# Output:
|
||||
# Private key saved to: ~/.mosis/signing_key.pem
|
||||
# Public key saved to: ~/.mosis/signing_key.pub
|
||||
#
|
||||
# Fingerprint: SHA256:xxxxx
|
||||
#
|
||||
# IMPORTANT: Keep your private key secure!
|
||||
# Upload your public key to the developer portal.
|
||||
```
|
||||
|
||||
### Key Format
|
||||
|
||||
#### Private Key (PEM)
|
||||
|
||||
```
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MC4CAQAwBQYDK2VwBCIEIGxxxxx...
|
||||
-----END PRIVATE KEY-----
|
||||
```
|
||||
|
||||
#### Public Key (PEM)
|
||||
|
||||
```
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MCowBQYDK2VwAyEAxxxxx...
|
||||
-----END PUBLIC KEY-----
|
||||
```
|
||||
|
||||
### Signing Flow
|
||||
|
||||
```
|
||||
1. Build package (ZIP all files)
|
||||
2. Generate MANIFEST.MF with SHA-256 hashes
|
||||
3. Sign MANIFEST.MF with private key
|
||||
4. Store signature in META-INF/CERT.SIG
|
||||
5. Include public key in META-INF/CERT.PEM
|
||||
```
|
||||
|
||||
#### MANIFEST.MF Example
|
||||
|
||||
```
|
||||
Manifest-Version: 1.0
|
||||
Created-By: mosis-cli 1.0.0
|
||||
Package-Id: com.developer.myapp
|
||||
Version-Code: 1
|
||||
|
||||
Name: manifest.json
|
||||
SHA-256-Digest: K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=
|
||||
|
||||
Name: assets/main.rml
|
||||
SHA-256-Digest: uU0nuZNNPgilLlLX2n2r+sSE7+N6U4DukIj3rOLvzek=
|
||||
```
|
||||
|
||||
### Verification Flow
|
||||
|
||||
```
|
||||
1. Extract MANIFEST.MF from package
|
||||
2. Extract CERT.SIG (signature)
|
||||
3. Extract CERT.PEM (public key)
|
||||
4. Verify signature of MANIFEST.MF using public key
|
||||
5. Verify CERT.PEM matches registered developer key
|
||||
6. Verify each file hash matches MANIFEST.MF entry
|
||||
```
|
||||
|
||||
### Key Registration
|
||||
|
||||
```
|
||||
Developer Portal:
|
||||
├── Go to Settings > Signing Keys
|
||||
├── Click "Add Key"
|
||||
├── Paste public key (PEM format)
|
||||
├── Verify fingerprint matches local
|
||||
└── Key is now registered
|
||||
|
||||
Server stores:
|
||||
├── public_key (PEM text)
|
||||
├── fingerprint (SHA256 of public key)
|
||||
├── created_at
|
||||
└── is_active
|
||||
```
|
||||
|
||||
### Key Rotation
|
||||
|
||||
```
|
||||
1. Generate new keypair
|
||||
2. Register new public key in portal
|
||||
3. Sign new versions with new key
|
||||
4. (Optional) Revoke old key after transition period
|
||||
```
|
||||
|
||||
### Trust Model
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ Trust Chain │
|
||||
├─────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Developer │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ Private Key ──signs──► Package │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ Public Key ──registered──► Portal │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ Portal ──verifies──► Signature │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ Device ──trusts──► Portal-verified packages │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Password Storage (if used)
|
||||
|
||||
```
|
||||
Algorithm: Argon2id
|
||||
Memory: 64 MB
|
||||
Iterations: 3
|
||||
Parallelism: 4
|
||||
Salt: 16 bytes random
|
||||
```
|
||||
|
||||
### Token Security
|
||||
|
||||
- Access tokens: Short-lived, in-memory only
|
||||
- Refresh tokens: HttpOnly, Secure, SameSite=Strict
|
||||
- API keys: Hashed with bcrypt, shown once on creation
|
||||
|
||||
### Key Security
|
||||
|
||||
- Private keys never leave developer's machine
|
||||
- Public keys verified via fingerprint
|
||||
- Key compromise: Revoke immediately, re-sign apps
|
||||
|
||||
### Audit Logging
|
||||
|
||||
```sql
|
||||
INSERT INTO auth_audit_log (
|
||||
developer_id,
|
||||
action, -- login, logout, key_create, key_revoke
|
||||
ip_address,
|
||||
user_agent,
|
||||
success,
|
||||
failure_reason,
|
||||
timestamp
|
||||
) VALUES (...);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Authentication
|
||||
|
||||
```
|
||||
POST /auth/oauth/github # Start GitHub OAuth
|
||||
GET /auth/oauth/github/callback # GitHub callback
|
||||
POST /auth/oauth/google # Start Google OAuth
|
||||
GET /auth/oauth/google/callback # Google callback
|
||||
POST /auth/refresh # Refresh tokens
|
||||
POST /auth/logout # Invalidate tokens
|
||||
GET /auth/me # Get current user
|
||||
```
|
||||
|
||||
### API Keys
|
||||
|
||||
```
|
||||
GET /api-keys # List keys
|
||||
POST /api-keys # Create key
|
||||
DELETE /api-keys/:id # Revoke key
|
||||
```
|
||||
|
||||
### Signing Keys
|
||||
|
||||
```
|
||||
GET /signing-keys # List keys
|
||||
POST /signing-keys # Register key
|
||||
DELETE /signing-keys/:id # Revoke key
|
||||
GET /signing-keys/:id/verify # Verify a signature
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Libraries
|
||||
|
||||
### Node.js
|
||||
|
||||
```json
|
||||
{
|
||||
"passport": "OAuth strategies",
|
||||
"jose": "JWT handling",
|
||||
"@noble/ed25519": "Ed25519 signing",
|
||||
"argon2": "Password hashing"
|
||||
}
|
||||
```
|
||||
|
||||
### Go
|
||||
|
||||
```go
|
||||
import (
|
||||
"golang.org/x/oauth2"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"crypto/ed25519"
|
||||
"golang.org/x/crypto/argon2"
|
||||
)
|
||||
```
|
||||
|
||||
### Rust
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
oauth2 = "4.4"
|
||||
jsonwebtoken = "9"
|
||||
ed25519-dalek = "2"
|
||||
argon2 = "0.5"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deliverables
|
||||
|
||||
- [ ] OAuth2 integration (GitHub)
|
||||
- [ ] OAuth2 integration (Google)
|
||||
- [ ] JWT token management
|
||||
- [ ] API key generation and validation
|
||||
- [ ] Ed25519 key generation tool
|
||||
- [ ] Signature creation and verification
|
||||
- [ ] Key registration API
|
||||
- [ ] Audit logging
|
||||
|
||||
---
|
||||
|
||||
## Test Cases
|
||||
|
||||
| Test | Description |
|
||||
|------|-------------|
|
||||
| OAuthLogin | Complete OAuth flow |
|
||||
| TokenRefresh | Refresh expired access token |
|
||||
| InvalidToken | Reject tampered JWT |
|
||||
| APIKeyAuth | Authenticate with API key |
|
||||
| KeyGeneration | Generate valid Ed25519 keypair |
|
||||
| SignPackage | Sign and verify package |
|
||||
| InvalidSignature | Reject tampered package |
|
||||
| KeyRevocation | Revoked key fails verification |
|
||||
|
||||
---
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. Support for hardware security keys (YubiKey)?
|
||||
2. Multi-factor authentication for portal?
|
||||
3. Team accounts with role-based access?
|
||||
4. Key escrow for enterprise customers?
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [OAuth 2.0 RFC 6749](https://tools.ietf.org/html/rfc6749)
|
||||
- [JWT RFC 7519](https://tools.ietf.org/html/rfc7519)
|
||||
- [Ed25519 paper](https://ed25519.cr.yp.to/ed25519-20110926.pdf)
|
||||
- [OWASP Authentication Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html)
|
||||
Reference in New Issue
Block a user