mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
feat: implement OAuth2 dynamic client registration (RFC 7591/7592) (#18645)
# Implement OAuth2 Dynamic Client Registration (RFC 7591/7592)
This PR implements OAuth2 Dynamic Client Registration according to RFC 7591 and Client Configuration Management according to RFC 7592. These standards allow OAuth2 clients to register themselves programmatically with Coder as an authorization server.
Key changes include:
1. Added database schema extensions to support RFC 7591/7592 fields in the `oauth2_provider_apps` table
2. Implemented `/oauth2/register` endpoint for dynamic client registration (RFC 7591)
3. Added client configuration management endpoints (RFC 7592):
- GET/PUT/DELETE `/oauth2/clients/{client_id}`
- Registration access token validation middleware
4. Added comprehensive validation for OAuth2 client metadata:
- URI validation with support for custom schemes for native apps
- Grant type and response type validation
- Token endpoint authentication method validation
5. Enhanced developer documentation with:
- RFC compliance guidelines
- Testing best practices to avoid race conditions
- Systematic debugging approaches for OAuth2 implementations
The implementation follows security best practices from the RFCs, including proper token handling, secure defaults, and appropriate error responses. This enables third-party applications to integrate with Coder's OAuth2 provider capabilities programmatically.
This commit is contained in:
@@ -196,6 +196,32 @@ The frontend is contained in the site folder.
|
||||
|
||||
For building Frontend refer to [this document](docs/about/contributing/frontend.md)
|
||||
|
||||
## RFC Compliance Development
|
||||
|
||||
### Implementing Standard Protocols
|
||||
|
||||
When implementing standard protocols (OAuth2, OpenID Connect, etc.):
|
||||
|
||||
1. **Fetch and Analyze Official RFCs**:
|
||||
- Always read the actual RFC specifications before implementation
|
||||
- Use WebFetch tool to get current RFC content for compliance verification
|
||||
- Document RFC requirements in code comments
|
||||
|
||||
2. **Default Values Matter**:
|
||||
- Pay close attention to RFC-specified default values
|
||||
- Example: RFC 7591 specifies `client_secret_basic` as default, not `client_secret_post`
|
||||
- Ensure consistency between database migrations and application code
|
||||
|
||||
3. **Security Requirements**:
|
||||
- Follow RFC security considerations precisely
|
||||
- Example: RFC 7592 prohibits returning registration access tokens in GET responses
|
||||
- Implement proper error responses per protocol specifications
|
||||
|
||||
4. **Validation Compliance**:
|
||||
- Implement comprehensive validation per RFC requirements
|
||||
- Support protocol-specific features (e.g., custom schemes for native OAuth2 apps)
|
||||
- Test edge cases defined in specifications
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### OAuth2/Authentication Work
|
||||
@@ -270,6 +296,32 @@ if errors.Is(err, errInvalidPKCE) {
|
||||
- Test both positive and negative cases
|
||||
- Use `testutil.WaitLong` for timeouts in tests
|
||||
|
||||
## Testing Best Practices
|
||||
|
||||
### Avoiding Race Conditions
|
||||
|
||||
1. **Unique Test Identifiers**:
|
||||
- Never use hardcoded names in concurrent tests
|
||||
- Use `time.Now().UnixNano()` or similar for unique identifiers
|
||||
- Example: `fmt.Sprintf("test-client-%s-%d", t.Name(), time.Now().UnixNano())`
|
||||
|
||||
2. **Database Constraint Awareness**:
|
||||
- Understand unique constraints that can cause test conflicts
|
||||
- Generate unique values for all constrained fields
|
||||
- Test name isolation prevents cross-test interference
|
||||
|
||||
### RFC Protocol Testing
|
||||
|
||||
1. **Compliance Test Coverage**:
|
||||
- Test all RFC-defined error codes and responses
|
||||
- Validate proper HTTP status codes for different scenarios
|
||||
- Test protocol-specific edge cases (URI formats, token formats, etc.)
|
||||
|
||||
2. **Security Boundary Testing**:
|
||||
- Test client isolation and privilege separation
|
||||
- Verify information disclosure protections
|
||||
- Test token security and proper invalidation
|
||||
|
||||
## Code Navigation and Investigation
|
||||
|
||||
### Using Go LSP Tools (STRONGLY RECOMMENDED)
|
||||
@@ -409,3 +461,67 @@ Always run the full test suite after OAuth2 changes:
|
||||
7. **OAuth2 tests failing but scripts working** - Check in-memory database implementations in `dbmem.go`
|
||||
8. **Resource indicator validation failing** - Ensure database stores and retrieves resource parameters correctly
|
||||
9. **PKCE tests failing** - Verify both authorization code storage and token exchange handle PKCE fields
|
||||
10. **Race conditions in tests** - Use unique identifiers instead of hardcoded names
|
||||
11. **RFC compliance failures** - Verify against actual RFC specifications, not assumptions
|
||||
12. **Authorization context errors in public endpoints** - Use `dbauthz.AsSystemRestricted(ctx)` pattern
|
||||
13. **Default value mismatches** - Ensure database migrations match application code defaults
|
||||
14. **Bearer token authentication issues** - Check token extraction precedence and format validation
|
||||
15. **URI validation failures** - Support both standard schemes and custom schemes per protocol requirements
|
||||
16. **Log message formatting errors** - Use lowercase, descriptive messages without special characters
|
||||
|
||||
## Systematic Debugging Approach
|
||||
|
||||
### Multi-Issue Problem Solving
|
||||
|
||||
When facing multiple failing tests or complex integration issues:
|
||||
|
||||
1. **Identify Root Causes**:
|
||||
- Run failing tests individually to isolate issues
|
||||
- Use LSP tools to trace through call chains
|
||||
- Check both compilation and runtime errors
|
||||
|
||||
2. **Fix in Logical Order**:
|
||||
- Address compilation issues first (imports, syntax)
|
||||
- Fix authorization and RBAC issues next
|
||||
- Resolve business logic and validation issues
|
||||
- Handle edge cases and race conditions last
|
||||
|
||||
3. **Verification Strategy**:
|
||||
- Test each fix individually before moving to next issue
|
||||
- Use `make lint` and `make gen` after database changes
|
||||
- Verify RFC compliance with actual specifications
|
||||
- Run comprehensive test suites before considering complete
|
||||
|
||||
### Authorization Context Patterns
|
||||
|
||||
Common patterns for different endpoint types:
|
||||
|
||||
```go
|
||||
// Public endpoints needing system access (OAuth2 registration)
|
||||
app, err := api.Database.GetOAuth2ProviderAppByClientID(dbauthz.AsSystemRestricted(ctx), clientID)
|
||||
|
||||
// Authenticated endpoints with user context
|
||||
app, err := api.Database.GetOAuth2ProviderAppByClientID(ctx, clientID)
|
||||
|
||||
// System operations in middleware
|
||||
roles, err := db.GetAuthorizationUserRoles(dbauthz.AsSystemRestricted(ctx), userID)
|
||||
```
|
||||
|
||||
## Protocol Implementation Checklist
|
||||
|
||||
### OAuth2/Authentication Protocol Implementation
|
||||
|
||||
Before completing OAuth2 or authentication feature work:
|
||||
|
||||
- [ ] Verify RFC compliance by reading actual specifications
|
||||
- [ ] Implement proper error response formats per protocol
|
||||
- [ ] Add comprehensive validation for all protocol fields
|
||||
- [ ] Test security boundaries and token handling
|
||||
- [ ] Update RBAC permissions for new resources
|
||||
- [ ] Add audit logging support if applicable
|
||||
- [ ] Create database migrations with proper defaults
|
||||
- [ ] Update in-memory database implementations
|
||||
- [ ] Add comprehensive test coverage including edge cases
|
||||
- [ ] Verify linting and formatting compliance
|
||||
- [ ] Test both positive and negative scenarios
|
||||
- [ ] Document protocol-specific patterns and requirements
|
||||
|
||||
Reference in New Issue
Block a user