-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
enterpriseEnterprise featureEnterprise featurestoryFeature story linked to epicFeature story linked to epic
Milestone
Description
User Story
As an enterprise developer, I want to authenticate using my organization's SSO provider so that I can use qctl without managing separate credentials.
Design
Command Interface
# Configure SSO provider
qctl auth sso configure --provider okta --issuer https://myorg.okta.com
# Login via SSO
qctl auth sso login
# Check SSO status
qctl auth sso status
# Remove SSO configuration
qctl auth sso removeSSO Configuration Flow
┌─────────────────────────────────────────────────────────────────┐
│ SSO Configuration │
├─────────────────────────────────────────────────────────────────┤
│ │
│ qctl auth sso configure │
│ │ │
│ ▼ │
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ Detect │────▶│ Fetch OIDC │────▶│ Store Provider │ │
│ │ Provider │ │ Metadata │ │ Config │ │
│ └─────────────┘ └──────────────┘ └──────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ Supported Providers: ││
│ │ - Okta (OIDC) ││
│ │ - Azure AD (OIDC/SAML) ││
│ │ - Google Workspace (OIDC) ││
│ │ - OneLogin (OIDC/SAML) ││
│ │ - Custom OIDC (any compliant provider) ││
│ │ - Custom SAML 2.0 ││
│ └─────────────────────────────────────────────────────────────┘│
│ │
└─────────────────────────────────────────────────────────────────┘
Output Format
$ qctl auth sso configure --provider okta --issuer https://myorg.okta.com
Fetching OIDC discovery metadata...
Provider: Okta
Issuer: https://myorg.okta.com
Authorization: https://myorg.okta.com/oauth2/v1/authorize
Token: https://myorg.okta.com/oauth2/v1/token
SSO configured successfully.
Run 'qctl auth sso login' to authenticate.
$ qctl auth sso login
Opening browser for SSO authentication...
Waiting for callback...
Authentication successful!
User: james.maes@acme.com
Organization: ACME Corp
Roles: developer, admin
Token expires: 2026-01-04 10:30:00 UTC
$ qctl auth sso status
Provider: Okta
Status: Authenticated
User: james.maes@acme.com
Organization: ACME Corp
Token expires in: 7h 23m
SAML Flow
┌──────┐ ┌─────────┐ ┌─────────┐ ┌────────┐
│ qctl │ │ Browser │ │ IdP │ │ Voyage │
└──┬───┘ └────┬────┘ └────┬────┘ └───┬────┘
│ │ │ │
│ Start SAML │ │ │
│──────────────▶ │ │
│ │ AuthnRequest │ │
│ │───────────────▶ │
│ │ │ │
│ │ Login Page │ │
│ │◀──────────────│ │
│ │ │ │
│ │ User Authenticates │
│ │───────────────▶ │
│ │ │ │
│ │ SAMLResponse │ │
│ │◀──────────────│ │
│ │ │ │
│ Callback with assertion │ │
│◀─────────────│ │ │
│ │ │ │
│ Exchange assertion for token │
│─────────────────────────────────────────────▶
│ │ │ │
│ Access Token │ │
│◀─────────────────────────────────────────────
Configuration File
# ~/.config/qctl/sso.yaml
provider: okta
type: oidc
issuer: https://myorg.okta.com
client_id: 0oa1234567890abcdef
scopes:
- openid
- profile
- email
- groups
redirect_uri: http://localhost:8400/callbackFiles to Create/Modify
| File | Action | Description |
|---|---|---|
qctl-core/src/main/java/io/qrun/qctl/core/auth/sso/SSOCommand.java |
Create | SSO subcommand group |
qctl-core/src/main/java/io/qrun/qctl/core/auth/sso/ConfigureCommand.java |
Create | SSO configure command |
qctl-core/src/main/java/io/qrun/qctl/core/auth/sso/SSOLoginCommand.java |
Create | SSO login command |
qctl-core/src/main/java/io/qrun/qctl/core/auth/sso/StatusCommand.java |
Create | SSO status command |
qctl-core/src/main/java/io/qrun/qctl/core/auth/sso/OIDCClient.java |
Create | OIDC protocol implementation |
qctl-core/src/main/java/io/qrun/qctl/core/auth/sso/SAMLClient.java |
Create | SAML 2.0 protocol implementation |
qctl-core/src/main/java/io/qrun/qctl/core/auth/sso/ProviderConfig.java |
Create | SSO provider configuration |
qctl-core/src/main/java/io/qrun/qctl/core/auth/sso/CallbackServer.java |
Create | Local HTTP server for callbacks |
qctl-core/src/main/java/io/qrun/qctl/core/auth/sso/ProviderDetector.java |
Create | Auto-detect provider from issuer |
Implementation Tasks
- Create SSOCommand subcommand group under auth
- Implement OIDC discovery metadata fetching
- Implement OIDC authorization code flow with PKCE
- Implement SAML 2.0 SP-initiated flow
- Create local callback server for browser redirect
- Add provider auto-detection from issuer URL
- Implement token exchange with Voyage API
- Store SSO configuration securely
- Add group/role claim mapping
- Handle token refresh for SSO sessions
- Add timeout and error handling for browser flows
- Write unit tests for protocol implementations
Acceptance Criteria
- Can configure Okta as OIDC provider
- Can configure Azure AD as OIDC/SAML provider
- Browser opens automatically for authentication
- Tokens are securely stored after SSO login
- Group claims are mapped to Voyage roles
- Token refresh works transparently
- Clear error messages for SSO failures
- Works in headless environments with device flow fallback
Metadata
Metadata
Assignees
Labels
enterpriseEnterprise featureEnterprise featurestoryFeature story linked to epicFeature story linked to epic
Type
Projects
Status
No status