Skip to main content

OauthRuntime

Struct OauthRuntime 

Source
pub struct OauthRuntime {
    pub codec: Codec,
    pub client: ClientConfig,
    pub client_id: String,
    pub client_key: Option<SigningKey>,
    pub auth_method: AuthMethod,
    pub locks: RefreshLocks,
    pub plc_directory: String,
    pub resolver: TokioResolver,
}
Expand description

Everything the Rust OAuth client needs that outlives a request.

Fields§

§codec: Codec

At-rest encryption for sessions and the signing key.

§client: ClientConfig

The validated client identity.

§client_id: String

client_id, precomputed — it is derived, and recomputing it per request invites a divergence between what we send and what we publish.

§client_key: Option<SigningKey>

The ES256 client key. None for the dev client, which is a public client and publishes no JWKS — and for a confidential client whose backend is not selected and which has no key file yet, since creating one it will never use is key material at rest for nothing.

§auth_method: AuthMethod

How this client authenticates to the authorization server.

§locks: RefreshLocks

Per-subject refresh serialization. One map process-wide, or the locking does nothing.

§plc_directory: String

The PLC directory for did:plc resolution.

§resolver: TokioResolver

The system DNS resolver, for handle → DID.

Implementations§

Source§

impl OauthRuntime

Source

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

Build the runtime from configuration.

Dev is inferred from the public URL, exactly as the sidecar infers it, so the two agree on which client identity they present. A localhost public URL means atproto’s localhost development client: a public client with no JWKS.

The signing key is loaded (or created) only for a confidential client that is actually going to use it — i.e. when the Rust backend is the selected one. Two reasons, and the second is the one that bit:

  • a dev client is public, so a key there is never used and never published, and later reads as “the key exists, so it must be in play”;
  • the runtime is built on EVERY start so configuration errors surface early, including when the sidecar is serving. Creating the key as part of that validation meant a sidecar deployment wrote an ES256 private key it would never use — key material at rest, for nothing. In tests it also meant any AppState built with a production-like public_url dropped a private key into the working directory.
Source§

impl OauthRuntime

Source

pub fn without_creating_key(cfg: &Config) -> Result<Self>

OauthRuntime::new, refusing instead of CREATING a missing signing key. For the operator’s --revoke-all-sessions.

new creates the key when a confidential client has none — right for the app’s first boot, wrong here. Run from the wrong directory (the default FEATHERREADER_OAUTH_KEY_PATH is relative) or with the wrong environment, it minted a fresh key under the same kid while the live app kept publishing the old JWKS. Every client assertion was then rejected, every row deleted anyway, and the teardown proceeded over live tokens. Revocation can only work with the key the PDSes know, so a missing one is an error.

App startup is unchanged: it still calls new.

Auto Trait Implementations§

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<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
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 = !

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

fn try_from(value: U) -> Result<T, !>

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<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