# CLI Browser OIDC PKCE Login v1

## Purpose

`gpuaas auth login` should use the same brokered identity path as the web product.
Password grant is useful for local/dev and breakglass testing, but it is not the
primary model for a cloud CLI because social and enterprise providers such as Hugging
Face, GitHub, and SSO do not fit a username/password prompt.

## Command Model

Primary human login:

```bash
gpuaas auth login
gpuaas auth login --provider huggingface
gpuaas auth login --provider github
gpuaas auth login --tenant-hint acme --identity-hint user@acme.example
gpuaas auth login --no-browser
```

Development-only password flows:

```bash
gpuaas auth dev-login --username dev-user --password dev123
gpuaas auth keycloak-login --username dev-user --password dev123
```

Automation flow:

```bash
gpuaas auth service-account-token --service-account-id ... --key-id ... --client-secret ...
```

Privileged human admin/ops login uses the same primary human login path. A
platform admin or ops user must authenticate through browser OIDC PKCE, or a
future OAuth device-code handoff when that flow is explicitly implemented and
reviewed. The CLI must not create a separate privileged password, static bearer
token, or service-account-token shortcut for a human admin/ops operator.

## Browser Login Flow

1. CLI generates a PKCE verifier and S256 challenge.
2. CLI starts a localhost callback listener on `127.0.0.1:<ephemeral>/callback`.
3. CLI calls `GET /api/v1/auth/oidc/authorize` with:
   - `redirect_uri`,
   - `code_challenge`,
   - `code_challenge_method=S256`,
   - optional `provider_hint`,
   - optional `tenant_hint`,
   - optional `identity_hint`.
4. API returns a server-authoritative authorization URL and opaque state.
5. CLI opens the browser unless `--no-browser` is set.
6. Browser completes the IdP flow and redirects to the localhost callback.
7. CLI validates callback state before token exchange.
8. CLI calls `POST /api/v1/auth/oidc/exchange` with code, verifier, redirect URI,
   and state in the JSON body.
9. CLI stores access and refresh tokens in the existing CLI config file.

The CLI never receives or passes access tokens in URL query parameters.

For human admin/ops users, the browser OIDC path is the MFA-compatible
credential boundary. Keycloak or the brokered IdP owns password and factor
verification. The CLI only receives tokens after the browser flow completes and
must not collect passwords, TOTP codes, recovery codes, WebAuthn assertions, or
other factor material.

## Provider Hints

Provider hints are advisory shortcuts. The server remains authoritative.

Supported first-pass values:

1. `huggingface`,
2. `github`,
3. `google`.

The API maps the validated hint to the brokered IdP hint understood by Keycloak. The
CLI does not construct direct provider URLs and does not bypass the GPUaaS API.

## Headless Behavior

`--no-browser` prints the authorization URL and still waits for the localhost callback.
This supports SSH sessions where the user can open the URL from another local browser
that can reach the callback endpoint through forwarding.

A true device-code flow is a later addition because the current API contract exposes
authorization-code exchange, not OAuth device authorization. If added, device
code must remain a human browser/IdP handoff that can satisfy MFA for admin/ops
users; it must not become a long-lived bearer-token bootstrap.

Until that endpoint exists, service-account auth remains the correct
non-interactive automation path. Service-account auth is not a privileged human
CLI login path.

## Security Rules

1. Use PKCE S256 for every human browser login.
2. Keep authorization codes, access tokens, refresh tokens, and client secrets out of
   logs.
3. Do not pass access or refresh tokens in URL query parameters.
4. Validate callback state before exchange.
5. Store tokens using the existing restricted-permission CLI config initially.
6. Move to OS keychain storage later as a separate hardening task.
7. Keep service-account auth for CI and automation.
8. Keep password grant commands clearly labeled as dev/breakglass paths.
9. Do not permit long-lived local bearer tokens for human privileged CLI use.
10. Do not permit service-account tokens, API keys, or client credentials to
    stand in for a human admin/ops CLI session.
11. Production platform admin/ops direct-grant or password-token CLI flows are
    blocked or disabled. Non-production dev-login commands must not be treated
    as MFA or production-access evidence.
12. Token persistence for human CLI sessions must support revocation by deleting
    local credentials and invalidating the IdP/API refresh session.

## Privileged Human CLI MFA Model

Human CLI access for `platform_superadmin`, `platform_admin`, and
`platform_ops` follows the same MFA enforcement model as browser access:

```text
gpuaas auth login
  -> browser OIDC PKCE or approved device-code handoff
  -> Keycloak/brokered IdP password and MFA enforcement
  -> CLI callback or polling completion
  -> short-lived access token plus refresh token storage
```

Required properties:

1. Human admin/ops operators authenticate as humans, not as service accounts.
2. The provider-enforced MFA selector from
   `IAM_MFA_Policy_and_Keycloak_Enforcement_v1.md` applies to the human account.
3. The CLI does not inspect or verify the factor. It relies on the IdP flow and
   later token/session assurance evidence when such claims are proven.
4. CLI token exchange must preserve the OIDC state, redirect URI, PKCE verifier,
   issuer, audience, expiry, and subject checks required by the API contract.
5. Sensitive-operation MFA gates remain deferred until reliable `amr`, `acr`, or
   equivalent assurance is proven in API-accepted tokens.

Forbidden privileged-human patterns:

1. copying a bearer token from a browser or Keycloak console into CLI config;
2. issuing a long-lived personal access token with platform admin/ops authority;
3. using a service-account token for an interactive human admin/ops action;
4. using direct grant/password login for production privileged CLI access;
5. storing refresh tokens in shell history, environment variables, scripts, or
   evidence artifacts.

## Credential Lifecycle

Initial storage remains `~/.gpuaas-cli/config.json` with restricted file
permissions until the OS keychain hardening task is implemented. That file may
store short-lived access tokens and refresh tokens for human sessions, but it is
not a durable bearer-token authority.

Credential lifecycle expectations:

1. Access tokens are short-lived and refreshed through the approved OIDC refresh
   path only while the refresh session remains valid.
2. Refresh tokens are stored only in the approved CLI credential store, never in
   command arguments, shell history, logs, CI variables, or Fairway evidence.
3. `gpuaas auth logout` deletes local access and refresh tokens and should call
   the provider/API revocation endpoint when available.
4. Incident revocation requires both local credential deletion on affected
   operator machines and server-side invalidation of refresh sessions or user
   sessions in Keycloak/API state.
5. Lost or exposed CLI credentials for a human admin/ops account are treated as
   a privileged credential incident, not as a normal logout.
6. CLI evidence must record token classes and timestamps only; never record raw
   access tokens, refresh tokens, ID tokens, authorization codes, device codes,
   TOTP seeds, recovery codes, or browser cookies.

## UX Implications

The normal help path should point users to:

```bash
gpuaas auth login
```

not to password grant. Brokered identities should work without asking users to know
whether the underlying provider is Keycloak, Hugging Face, GitHub, or enterprise SSO.

## Implementation Notes

The first implementation keeps token persistence compatible with the existing SDK
config file:

```text
~/.gpuaas-cli/config.json
```

That preserves current CLI behavior while changing the default login path. Future
hardening can move refresh-token storage to an OS keychain without changing the CLI
command contract.

Production admin/ops rollout must not be considered complete until the CLI help,
runbooks, and implementation make `gpuaas auth login` the privileged human path
and keep service-account/token bootstrap paths restricted to automation or
non-production development.
