Files
skybridge/TOKEN_LOOKUP_ANALYSIS.md
2025-08-26 13:51:15 -04:00

150 lines
5.2 KiB
Markdown

# Token Verification: App ID From Token vs Separate Parameter
## Current Implementation Analysis
### Current Flow (Requires app_id parameter):
```
1. Client: POST /api/verify {"token": "TESTT-abc123", "app_id": "test.example.com"}
2. System: Get app by app_id → Validate token against app's stored hashes
3. Result: Token validated within specific application scope
```
### Proposed Alternative (Extract app_id from token):
```
1. Client: POST /api/verify {"token": "TESTT-abc123"}
2. System: Extract prefix "TEST" → Find app by token_prefix → Validate token
3. Result: Token validated without requiring app_id parameter
```
## Security Analysis
### ✅ **Advantages of Token-Only Verification:**
#### 1. **Simpler API Usage**
```javascript
// Current (requires app knowledge)
await verify({token: "TESTT-abc123", app_id: "test.example.com"});
// Proposed (token-only)
await verify({token: "TESTT-abc123"});
```
#### 2. **Prevents App ID Mismatches**
- Current: Client could provide wrong app_id (though validation would fail)
- Proposed: App is determined directly from token - no mismatch possible
#### 3. **Better Token Portability**
- Tokens are self-describing and don't require external context
- Useful for tokens shared across different applications/services
### ❌ **Security Risks of Token-Only Verification:**
#### 1. **Information Disclosure Through Enumeration**
```bash
# Attacker can discover applications by trying token prefixes
curl -X POST /api/verify -d '{"token": "TESTX-fakehash"}'
# Response reveals if "TEST" application exists
curl -X POST /api/verify -d '{"token": "PRODX-fakehash"}'
# Response reveals if "PROD" application exists
```
#### 2. **Reduced Access Control Granularity**
```
Current: Client must know both token AND which app it belongs to
Proposed: Client only needs token - loses "need to know" app context
```
#### 3. **Prefix Collision Risk**
```sql
-- Multiple apps could theoretically have same prefix
INSERT INTO applications (app_id, token_prefix) VALUES
('app1.com', 'TEST'),
('app2.com', 'TEST'); -- Collision!
```
#### 4. **Weaker Defense Against Token Leakage**
- Current: Leaked token + need app_id knowledge = double barrier
- Proposed: Leaked token alone is sufficient = single barrier
## Implementation Feasibility
### Required Changes for Token-Only Verification:
```go
// 1. Add repository method
func (r *ApplicationRepository) GetByTokenPrefix(ctx context.Context, prefix string) (*domain.Application, error)
// 2. Extract prefix from token
func extractTokenPrefix(token string) string {
dashIndex := strings.Index(token, "-")
if dashIndex >= 3 && dashIndex <= 6 {
return token[:dashIndex-1] // Remove "T" or "UT" part
}
return ""
}
// 3. Modified verification flow
func (s *tokenService) VerifyTokenOnly(ctx context.Context, token string) (*domain.VerifyResponse, error) {
prefix := extractTokenPrefix(token)
app, err := s.appRepo.GetByTokenPrefix(ctx, prefix)
if err != nil {
return &domain.VerifyResponse{Valid: false, Error: "Invalid token"}, nil
}
// Continue with existing verification logic...
}
```
### Database Schema Considerations:
```sql
-- Ensure unique prefixes (recommended)
ALTER TABLE applications ADD CONSTRAINT unique_token_prefix
UNIQUE (token_prefix) WHERE token_prefix != '';
-- Index already exists from migration 003
-- CREATE INDEX idx_applications_token_prefix ON applications(token_prefix);
```
## Recommendation: **Keep Current Implementation (Require app_id)**
### Reasoning:
#### **Security-First Approach** 🛡️
1. **Prevents enumeration attacks** - attackers can't discover apps by probing prefixes
2. **Maintains access control granularity** - clients must know token + app context
3. **Defense in depth** - two required pieces of information instead of one
4. **Clear audit trails** - logs show which app context was used for verification
#### **Architectural Benefits** 🏗️
1. **Explicit application scoping** - makes it clear which app owns the token
2. **Better error handling** - can distinguish between "invalid app" vs "invalid token"
3. **Supports multi-tenancy** - different apps can have isolated token validation
4. **Future extensibility** - can add per-app validation rules without breaking changes
#### **Operational Benefits** 🔧
1. **Clear API contracts** - consumers explicitly specify their context
2. **Better monitoring** - can track usage per application
3. **Simpler debugging** - logs clearly show app context for each verification
### **Optional: Provide Both Endpoints**
```go
// Existing secure endpoint (recommended for production)
POST /api/verify
{
"token": "TESTT-abc123",
"app_id": "test.example.com"
}
// Optional convenience endpoint (for development/testing)
POST /api/verify/token-only
{
"token": "TESTT-abc123"
}
```
## Final Answer
**Keep the current implementation requiring app_id** for security and architectural reasons. The slight inconvenience of requiring the app_id parameter provides significant security benefits and maintains better system architecture.
The token prefix provides tampering protection (which is working correctly), but requiring separate app_id provides additional security layers that outweigh the convenience of token-only verification.