OpenrouterSdk.OAuth (OpenRouter SDK v0.1.0)

Copy Markdown View Source

oauth pkce primitives.

this is intentionally just the math + the http exchange. the consumer owns the redirect route, session storage, and the code_verifier lifetime.

typical flow:

verifier = OpenrouterSdk.OAuth.generate_code_verifier()
challenge = OpenrouterSdk.OAuth.code_challenge(verifier)
url = OpenrouterSdk.OAuth.build_authorize_url(
  "https://myapp.example.com/openrouter/callback",
  code_challenge: challenge,
  code_challenge_method: :s256
)
# redirect the user to `url`. on callback, exchange the code:
{:ok, %{key: api_key}} =
  OpenrouterSdk.OAuth.exchange_code(
    conn.params["code"],
    code_verifier: verifier,
    code_challenge_method: :s256
  )

Summary

Functions

build the authorization url to redirect the user to.

derive the code_challenge from a verifier.

exchange an authorization code for an api key.

generate a cryptographically random code verifier (rfc 7636).

Types

method()

@type method() :: :s256 | :plain

Functions

build_authorize_url(callback_url, opts \\ [])

@spec build_authorize_url(
  String.t(),
  keyword()
) :: String.t()

build the authorization url to redirect the user to.

callback_url is required (where openrouter sends the user back with ?code=...). code_challenge is technically optional per the api but you should always include it.

code_challenge(verifier, method \\ :s256)

@spec code_challenge(String.t(), method()) :: String.t()

derive the code_challenge from a verifier.

defaults to s256 (recommended). pass :plain to skip hashing — only ever do that if the transport layer above can't hash, which is rare.

exchange_code(code, opts \\ [])

@spec exchange_code(
  String.t(),
  keyword()
) :: {:ok, map()} | {:error, OpenrouterSdk.Error.t()}

exchange an authorization code for an api key.

returns {:ok, %{key: "...", ...}} on success — the full decoded json body is returned so future fields (user info, etc.) are available transparently.

generate_code_verifier()

@spec generate_code_verifier() :: String.t()

generate a cryptographically random code verifier (rfc 7636).

uses 64 random bytes encoded as url-safe base64 (no padding) — well within the 43-128 char range the spec allows.