Skip to main content

Auth

Struct Auth 

Source
pub struct Auth {
    pub token_store: TokenStore,
    /* private fields */
}
Expand description

Manages authentication for X API requests.

Holds the credential matrix (env-supplied vs store-derived client_id / client_secret), the active app name, and the TokenStore that persists tokens to disk. Constructed via Auth::new (legacy ~/.xurl path) or Auth::new_with_store_path (test-friendly explicit path).

Fields§

§token_store: TokenStore

Token store backing this Auth instance.

Implementations§

Source§

impl Auth

Source

pub fn new(cfg: &Config) -> Self

Creates a new Auth object using the legacy ~/.xurl token-store path.

Shim over Auth::new_with_store_path resolving to Config::default_store_path. Credentials are resolved: env vars -> active app.

Source

pub fn new_with_store_path(cfg: &Config, store_path: &Path) -> Self

Creates a new Auth object backed by an explicit token-store path.

The canonical constructor. Tests pass a TempDir-rooted path to avoid touching the real ~/.xurl; the binary calls Auth::new which resolves to Config::default_store_path. Credentials are resolved: env vars -> active app at store_path.

Runs the three-level redirect URI resolver (env > app-stored > built-in default) against the constructed token store and writes the result back into the owned Config, satisfying KTD2’s single source of truth invariant.

Source

pub fn with_app_name(&mut self, app_name: &str)

Sets the explicit app name override and re-resolves the redirect URI.

Credentials honor env precedence per the internal client_id_from_env / client_secret_from_env flags: env-supplied values survive the switch; store-derived values get re-resolved from the new app’s entry, even when the previous app’s stored value was non-empty. The redirect URI is always re-resolved (env-precedence is enforced inside the resolver itself, so re-running unconditionally produces the right value per KTD3).

Source

pub fn get_oauth1_header( &self, method: &str, url_str: &str, additional_params: Option<&BTreeMap<String, String>>, ) -> Result<String>

Gets the OAuth1 Authorization header for a request.

§Errors

Returns an error if no OAuth1 token is found or signature generation fails.

Source

pub fn get_oauth2_header(&mut self, username: &str) -> Result<String>

Gets or refreshes an OAuth2 token and returns the Authorization header.

Lookup precedence is intent-split per KTD5:

  • non-empty username (named caller): try the username’s own token first; on miss, fall through to TokenStore::get_first_oauth2_token_for_app (which itself prefers default_user, then arbitrary-first); on total miss, trigger the full OAuth2 flow. The unnamed (/me-failed salvage) slot is never consulted on this branch — a caller who supplies a username has explicit identity intent and must not silently receive a salvage-state token under their name.
  • empty username: try get_first_oauth2_token_for_app (which prefers default_user, then arbitrary-first); on miss, fall through to the unnamed slot via TokenStore::get_oauth2_token_unnamed_for_app; on total miss, trigger the OAuth2 flow.

In both branches the cached-token path delegates to Auth::refresh_oauth2_token, which is a no-op if the token is still valid.

§Errors

Returns an error if the OAuth2 flow fails or token refresh fails.

Source

pub fn oauth2_flow( &mut self, username: &str, out: &OutputConfig, stdout: &mut dyn Write, ) -> Result<String>

Starts the OAuth2 PKCE flow with the default open::that browser opener.

Browser-failure prompts are written to stdout via out’s print_message, so callers can capture them in tests. Library consumers needing a custom opener (recording / headless / tests for the listener-before-browser ordering) call oauth2::run_oauth2_flow directly with their own fn(&str) -> io::Result<()> opener.

§Errors

Returns an error if the authorization flow, token exchange, or username resolution fails.

Source

pub fn refresh_oauth2_token(&mut self, username: &str) -> Result<String>

Validates and refreshes an OAuth2 token if needed.

§Errors

Returns an error if no token is found or the refresh request fails.

Source

pub fn remote_oauth2_step1(&self, pending_path: &Path) -> Result<String>

Runs step 1 of the remote OAuth2 PKCE flow.

Returns the authorization URL that the user should open in a browser on another machine.

§Errors

Returns an error if the authorization URL is invalid or the pending state file cannot be written.

Source

pub fn remote_oauth2_step2( &mut self, redirect_url: &str, username: &str, pending_path: &Path, ) -> Result<String>

Runs step 2 of the remote OAuth2 PKCE flow.

Takes the redirect URL from the browser, extracts the authorization code, exchanges it for an access token, and saves the token.

§Errors

Returns an error if the pending state is missing/expired/invalid, the token exchange fails, or the username cannot be resolved.

Source

pub fn get_bearer_token_header(&self) -> Result<String>

Gets the bearer token Authorization header.

Resolution order: XURL_BEARER_TOKEN env var first (one-shot agent flows that pipe a secret without persisting it to disk), then the token store entry on the resolved app. Empty env values fall through to the store. The env var matches the precedence shape used by every other agentic flag (XURL_VERBOSE, XURL_OUTPUT, XURL_NO_BROWSER, etc.) and pairs with XURL_OUTPUT=json xr ... --auth app for stateless container invocations.

Production code reads XURL_BEARER_TOKEN from the process environment. The resolution logic is factored into resolve_bearer_token so unit tests can exercise every precedence path without mutating the global environment (the project policy in MEMORY: no env mutation in tests, no #[serial]).

§Errors

Returns an error if XURL_BEARER_TOKEN is unset (or empty) AND no bearer token is stored for the resolved app.

Source

pub fn with_token_store(self, token_store: TokenStore) -> Self

Replaces the token store (used in integration tests).

Honors the internal env-precedence flags (client_id_from_env / client_secret_from_env): env-supplied values survive the swap; store-derived values get re-resolved from the new store’s active app. Replaces the older equality-based heuristic (self.client_id == old_app.client_id) which produced false negatives when the old and new stores happened to share a value.

Source

pub fn token_store(&self) -> &TokenStore

Returns a reference to the token store.

Source

pub fn app_name(&self) -> &str

Returns the active app name resolved against --app / XURL_APP.

Source

pub fn client_id(&self) -> &str

Returns the active OAuth2 client ID (env-supplied or store-derived).

Source

pub fn client_secret(&self) -> &str

Returns the active OAuth2 client secret (env-supplied or store-derived).

Source

pub fn auth_url(&self) -> &str

Returns the OAuth2 authorization URL.

Source

pub fn token_url(&self) -> &str

Returns the OAuth2 token-exchange URL.

Source

pub fn redirect_uri(&self) -> &str

Returns the resolved OAuth2 redirect URI.

The value already reflects the three-level precedence (env > app-stored > built-in default) applied at construction by Auth::new_with_store_path.

Source

pub fn http_timeout_secs(&self) -> u64

Per-request HTTP timeout in seconds for OAuth2 token exchange, refresh, and /2/users/me lookups. Mirrors the --timeout flag.

Auto Trait Implementations§

§

impl Freeze for Auth

§

impl RefUnwindSafe for Auth

§

impl Send for Auth

§

impl Sync for Auth

§

impl Unpin for Auth

§

impl UnsafeUnpin for Auth

§

impl UnwindSafe for Auth

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more