Skip to content

v2.1.0

Choose a tag to compare

@github-actions github-actions released this 11 Aug 20:46
· 7 commits to master since this release
v2.1.0
b02f227

Added

  • Added the repl command: a persistent session bound to one account that reads the secret store once and answers token and auth commands over stdin/stdout.

    One-shot commands re-read the secret store on every run, so a keyring that confirms disclosure per process prompts again and again. The REPL resolves the token once, holds it in memory for the life of the process, and reuses it, collapsing those prompts into a single unlock (plus one per refresh, which must persist a rotated refresh token). It shows a prompt on a terminal and uses a plain line protocol when piped (one flushed result per command on stdout, errors on stderr), so an application can drive it without reimplementing the OAuth flow. auth get and auth resume run against the same in-memory account, so a token they issue is immediately served by a following token show.

  • Added the device authorization grant (RFC 8628).

    grant = "device" with endpoints.device-authorization. Interactive auth get polls; non-interactive / --json hands off to auth resume <DEVICE_CODE>.

  • Added the headless client credentials grants, so OAuth-ignorant tools (a sync daemon, a cron job) can exec ortie token show --auto-refresh and always read a valid bearer token.

    grant = "client-credentials" (RFC 6749 section 4.4) authenticates with the existing client-secret; grant = "client-credentials-jwt" (RFC 7523 section 2.2, the Microsoft certificate credentials flow) authenticates with a JWT assertion signed by the new client-key (PKCS#8 or PKCS#1 PEM path), carrying the x5t thumbprint of the new client-certificate (PEM or DER path). Both run auth get headlessly in one shot; auth resume has nothing to resume and says so.

    Neither grant issues a refresh token, so auto-refresh (token show --auto-refresh and token refresh) branches per grant: refresh-token exchange where one exists, silent re-acquisition (a re-run of the grant) for the client credentials kinds, including when the stored token is missing, so the very first run needs no prior auth get. Each JWT re-acquisition mints a fresh 10 minute assertion (unique jti, key and certificate re-read from disk); assertions are never stored.

    A provider invalid_client on the JWT kind now hints that the certificate credential may be expired and need renewal.

  • Added a welcome banner to the wizard, on stderr, framing what ortie is and where every field is documented.

  • Added a keyring entry prompt to the wizard's storage step, seeded with the account name and used verbatim, matching the Himalaya wizard, instead of being namespaced under ortie/ on your behalf.

  • Offered to save the wizard's account to a config file, defaulting to $XDG_CONFIG_HOME/ortie/config.toml.

    The account is printed first and the save comes after it, so the prompt decides one thing only and declining leaves you the printed fragment. An existing file is appended to, never rewritten: the fragment is one [accounts.<name>] table, so the accounts and comments already in it are untouched. Appending to a file that already holds something is confirmed first, naming the path. A redirected stdout (or --json) prints without prompting at all, so ortie >> <config> is unchanged.

  • Resolved issuers into concrete grants: a typed issuer URL, and a discovered OAuth issuer, are read through their RFC 8414 metadata instead of being emitted as a bare issuer comment.

    Every grant the metadata advertises is offered, so a server publishing both an authorization endpoint and a device authorization endpoint yields both flows, as RFC 8414 and RFC 8628 allow, and a machine with no browser can pick the device grant where a redirect is also possible.

  • Offered the authorization server's scopes_supported in the scope multi-select, for an application not bound to a registered set of scopes.

Changed

  • Bumped io-oauth to 0.2.1, for the RFC 7523 support behind its jwt-bearer feature, and io-pim-discovery to 0.5, for the time-bounded discovery the wizard now runs.

  • A refreshed or issued token now stamps its issuance time from the local clock (instead of relying on the server Date header), and a missing expires_in defaults to one hour, so auto-refresh stays reliable across a long-lived session.

  • Emitted keyring read commands as an exec-style array instead of a shell string, so no shell reinterprets an entry name.

    Write commands stay shell lines, since some rely on shell features ($(cat) on macOS), as do commands typed by hand.

  • Ordered the wizard's storage strategies by what is installed, the credential provider CLIs found on your PATH leading.

    The ones that are not found are still offered, and say so: each is one package install away, and the commands written for it are correct either way.

  • Bounded the wizard's discovery with a 6 second deadline, so one unreachable endpoint cannot stall the prompt.

  • Reduced discovered grants by authorization server rather than by endpoint URL, so one server described by two mechanisms is offered once instead of twice.

    Gmail no longer asks you to choose between Mozilla autoconfig's legacy accounts.google.com/o/oauth2/auth + www.googleapis.com/oauth2/v3/token pair and the current one: the most authoritative mechanism wins, and an entry is labelled by its flow and services instead of its token endpoint. A pick list left with a single grant is no longer prompted for.

  • Asked for the application before the scopes, since a registration is what decides which scopes can be requested.

    A public application now offers exactly the scopes it is registered for (Thunderbird on Google: Gmail, CardDAV and CalDAV), so a scope its client id was never verified for can no longer reach the authorization request and fail at consent. Dynamic registration picks its scopes before it registers, since they travel in the registration request.

  • Derived the wizard's account name from the input (the first label of the domain or issuer host) instead of prompting for it; rename the [accounts.<name>] key by hand.

  • Moved the wizard's guidance from the printed fragment into the stderr banner, so stdout now carries bare TOML.

  • Probed the authorization server metadata once per wizard run, shared by the scope options and the dynamic registration decision, instead of only before the application step.

  • Serialized the client id under --json even when left empty, matching the client-id = "" placeholder the TOML fragment already carried.

Fixed

  • Fired on-issue error hooks when the local device poll deadline expires (DeviceCodeExpired as expired_token).

  • Made the manual auth resume command printed by auth get runnable as printed.

    Its state and PKCE verifier are single quoted and attached to their flag with =, so a value starting with - is not read as a flag and one starting with ~ is not expanded by your shell.

  • Trimmed auth-code resume input; omitted redirect/state/PKCE bodies from resume errors.

Removed

  • Removed the auth discover subcommand: bare ortie already runs the same wizard. Run ortie (it prompts for the email, server or issuer input).

  • Removed hand-entry of OAuth 2.0 endpoints from the wizard, along with the "Enter OAuth 2.0 details manually" pick-list entry.

    The wizard configures only what it can discover; when nothing is found it stops and points at the sample configuration.

  • Removed the prompts behind the wizard's custom application entry (client id, secret, scopes, redirection).

    If you registered an application yourself you are already editing the config, so the wizard emits the account with everything it resolved, leaves client-id empty, and explains what to fill in by hand. The storage step still runs, being independent of the application.