package oauth import ( "html/template" "net/http" "net/url" "strings" "github.com/krow/krow-backend/go-api/internal/authctx" ) // The consent step: the one place a person decides. // // Phase 3 approved a signed-in user's authorization immediately. That was // honest scaffolding and is not a flow anybody should ship: OAuth's entire // premise is that a RESOURCE OWNER grants access, and an authorization nobody // was asked about is a token minted on their behalf without their knowledge. // Any page on the internet could have linked a person to a crafted authorize // URL and had Claude connected to their workspace before they read anything. // // HOW THIS RESISTS THAT // // The consent form carries a CSRF token bound to the session, and approval is // a POST. A cross-site GET to /oauth/authorize can therefore render the form — // which is harmless, it is a question — but cannot answer it. Without the POST // and the token, an attacker who can make a browser navigate cannot make it // consent. // // WHAT IT SHOWS // // The client's self-declared name, the organisation being granted, the scope in // plain words, and the resource. The client name is UNTRUSTED — it is whatever // the registering client sent — so it is escaped by html/template and is never // the basis of a decision, only of a label. The organisation is read from the // signed-in identity, so a person can see which tenant they are about to hand // over even when they belong to more than one. // consentTemplate is the approval page. // // Deliberately one self-contained page with inline styles: it renders before a // person is willing to trust anything, it must work with no stylesheet, no // script and no font available, and a consent screen that depends on assets is // a consent screen that can fail open into a blank page with two buttons. // // Every interpolation is escaped by html/template. The `.ClientName` in // particular is attacker-controlled — anyone may register a client called // `