morca · API · web

orca.web.auth

Who a request is from, and whether it may act: the session cookie of a browser, the API token of a script (orca --remote), and the checks that keep another site's page from posting to the UI. Also the endpoints that log in and out. The users, sessions and audit rows themselves are orca.auth; API tokens are orca.tokens; a worker's token is checked by orca.api.worker instead, and gets nothing here.

Path
/login GET: the form; POST name, password, next: a session, as the cookie orca_session
/logout ends the session and clears the cookie
/api/login JSON name, password, label, days: an API token for orca login
/api/logout revokes the API token it's sent with

A script's request is one with an Authorization header (or a JSON login for a token). A browser sends neither to another site without a CORS preflight, which the UI never answers, so a script's POST with no Origin needn't be the UI's own; the token, not a cookie, is what it acts with. A request with an Authorization header is answered 401 unless it's a live token, whatever cookie it has.

Functions

bearer

def bearer(authorization: String) -> String

The token of Authorization: Bearer <token>, or empty for any other header.

sign_in

def sign_in(mut db: State, req: Request, mut call: Call) -> Bool

Fills in who call is from: the user of its API token (source "cli"), or of its session cookie (source "ui"), or nobody. False for an Authorization that isn't a live API token, whose request is refused (cookies are never looked at instead).

client

def client(req: Request) -> String

The address a request came from: the connection's peer, or behind a proxy (ORCA_UI_TRUST_PROXY=1) the first address of X-Forwarded-For, which only a proxy in front can be trusted to set.

content_type

def content_type(req: Request) -> String

The request's media type, lower case, without its parameters, which a cross-site page may set however it likes.

scripted

def scripted(req: Request, path: String) -> Bool

Whether req is a script's (orca.remote): it has an Authorization header, or is a JSON login for a token. /login and /logout are a browser's whatever they're sent with.

same_origin

def same_origin(req: Request) -> Bool

Whether a POST came from the UI's own pages: its Origin, or without one its Referer, is this server as the browser addressed it, by Host and the scheme _scheme gives. Host and scheme compare in any case.

cross_origin

def cross_origin() -> Page

login_needed

def login_needed(req: Request, json: Bool) -> Response

An action without a session: 401 for a script, to the login page for a browser, which comes back to the page the form was on.

json_form

def json_form(body: String) -> String

A JSON object of strings, numbers and booleans (orca.remote's actions) as the form the UI's own pages post, so both are handled and audited alike: true is 1, false and null are left out.

json_error

def json_error(status: Int, why: String) -> Page

An error as JSON only, for a script.

token_refused

def token_refused() -> Page

A request with a token that's no use: unknown, expired or revoked, or an Authorization that isn't a bearer token.

login_form

def login_form(mut db: State, call: Call) -> Page

GET /login: the form, which goes on to ?next=.

login

def login(mut db: State, call: Call) -> Page

POST /login: a session for name and password, as a cookie, then on to next.

logout

def logout(mut db: State, call: Call) -> Page

/logout: ends the session, if there is one, and clears the cookie.

api_login

def api_login(mut db: State, call: Call) -> Page

POST /api/login: a new API token for a JSON name and password, labelled label, lasting days (at most ORCA_API_TOKEN_DAYS). Failures count against the same limit as /login's, and the token is in this answer only. A token it was sent with isn't looked at.

api_logout

def api_logout(mut db: State, call: Call) -> Page

POST /api/logout: revokes the API token it's sent with; a session has none to revoke.

Aliases

comptime LOGIN = "/login"
comptime LOGOUT = "/logout"
comptime API_LOGIN = "/api/login"
comptime API_LOGOUT = "/api/logout"