-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
module:coreCore infrastructureCore infrastructurestoryFeature story linked to epicFeature story linked to epic
Milestone
Description
User Story
As a developer, I want to authenticate with qctl using my browser so I can securely access Voyage APIs without managing passwords in the CLI.
Design
Command Interface
# Start login flow
qctl auth login
# Login to specific provider
qctl auth login --provider voyage
# Check authentication status
qctl auth status
# Logout (clear tokens)
qctl auth logout
# Refresh token manually
qctl auth refreshDevice Flow Output
Logging in to Voyage...
Please visit: https://voyage.qrun.io/device
Enter code: ABCD-1234
Waiting for authorization... (press Ctrl+C to cancel)
[Browser opens automatically]
Authenticated as: james.maes@example.com
Organization: acme-corp
Token stored in: macOS Keychain
Login successful!
OIDC Configuration
# ~/.qctl/qctl.yaml
auth:
provider: voyage
providers:
voyage:
issuer: https://auth.qrun.io
client_id: qctl-cli
scopes:
- openid
- profile
- qctl:read
- qctl:write
device_auth_endpoint: /oauth/device/code
token_endpoint: /oauth/tokenToken Storage
# Tokens stored in OS keychain with entries:
qctl:voyage:access_token
qctl:voyage:refresh_token
qctl:voyage:id_token
qctl:voyage:expires_at
Files to Create/Modify
| File | Action | Purpose |
|---|---|---|
qctl-core/src/main/java/io/qrun/qctl/core/auth/AuthCommand.java |
Create | Auth command group |
qctl-core/src/main/java/io/qrun/qctl/core/auth/LoginCommand.java |
Create | Login subcommand |
qctl-core/src/main/java/io/qrun/qctl/core/auth/LogoutCommand.java |
Create | Logout subcommand |
qctl-core/src/main/java/io/qrun/qctl/core/auth/StatusCommand.java |
Create | Status subcommand |
qctl-core/src/main/java/io/qrun/qctl/core/auth/DeviceFlow.java |
Create | Device flow implementation |
qctl-core/src/main/java/io/qrun/qctl/core/auth/TokenManager.java |
Create | Token lifecycle |
qctl-core/src/main/java/io/qrun/qctl/core/auth/OIDCClient.java |
Create | OIDC HTTP client |
qctl-core/src/main/java/io/qrun/qctl/core/auth/model/DeviceCode.java |
Create | Device code response |
qctl-core/src/main/java/io/qrun/qctl/core/auth/model/TokenResponse.java |
Create | Token response |
Implementation Tasks
- Create AuthCommand with login, logout, status, refresh subcommands
- Implement DeviceFlow with RFC 8628 compliance
- Request device code from authorization server
- Display user code and verification URI
- Open browser automatically (with fallback)
- Poll token endpoint with appropriate interval
- Handle authorization_pending, slow_down, expired_token errors
- Implement TokenManager for token storage/retrieval
- Integrate with OS keychain (Add OS keychain integration #57)
- Implement automatic token refresh before expiry
- Add --provider flag for multi-provider support
- Write unit tests for DeviceFlow
- Write integration tests with mock OIDC server
Acceptance Criteria
-
qctl auth loginstarts device authorization flow - Displays verification URI and user code
- Opens browser automatically
- Polls for token with backoff
- Stores tokens securely in keychain
-
qctl auth statusshows current auth state -
qctl auth logoutclears stored tokens - Automatic token refresh works silently
- Works with Voyage OIDC provider
Metadata
Metadata
Assignees
Labels
module:coreCore infrastructureCore infrastructurestoryFeature story linked to epicFeature story linked to epic
Type
Projects
Status
No status