Skip to content

oauth: add HTMLSuccess + HTMLError fields for branded login pages#330

Closed
davidlwg wants to merge 1 commit into
rest-sh:mainfrom
davidlwg:davidlwg/customizable-oauth-html
Closed

oauth: add HTMLSuccess + HTMLError fields for branded login pages#330
davidlwg wants to merge 1 commit into
rest-sh:mainfrom
davidlwg:davidlwg/customizable-oauth-html

Conversation

@davidlwg
Copy link
Copy Markdown

@davidlwg davidlwg commented May 15, 2026

Summary

Adds two optional fields, HTMLSuccess and HTMLError, to AuthorizationCodeTokenSource. When set, they override the built-in success / error HTML pages served to the browser at the end of the OAuth callback flow. When empty (the default), behaviour is unchanged.

The change is purely additive — no existing callers see different behaviour.

Why

The default htmlSuccess / htmlError templates are good general defaults, but they're shipped as unexported package-level vars, so downstream tools have no way to brand the post-login landing page short of forking the package. Branded CLIs (a fairly common use of AuthorizationCodeTokenSource) currently have to choose between using restish's PKCE flow and showing their own success / error UI, even though everything else about the flow is already factored out as configurable.

A motivating example: I'm building a corporate-internal CLI on top of restish where the post-login page should show the user "logged in as to " and the team's brand. Today the user just sees the generic restish "Login Successful!" page, which works fine but feels unbranded. With this change, callers configure the HTML alongside the URL / scope / client config:

source := &oauth.AuthorizationCodeTokenSource{
    ClientID:     clientID,
    AuthorizeURL: authorizeURL,
    TokenURL:     tokenURL,
    RedirectURL:  redirectURL,
    Scopes:       []string{"openid", "profile"},
    HTMLSuccess:  customSuccessHTML,
    HTMLError:    customErrorHTML,  // $ERROR / $DETAILS substitution still works
}

token, err := source.Token()

Implementation

Three small touches in oauth/authcode.go:

  1. Two fields on AuthorizationCodeTokenSource (HTMLSuccess, HTMLError) with doc comments documenting the $ERROR / $DETAILS substitution behaviour for the error path.
  2. Two unexported fields on authHandler (successHTML, errorHTML) and a default-when-empty fallback in ServeHTTP that selects the override when set, otherwise the existing package-level constants.
  3. Plumbing in Token() to pass the user-provided HTML into the handler at construction time.

Tests

Five new tests in oauth/authcode_test.go cover:

  • Default htmlSuccess served when successHTML is unset
  • Custom HTML served verbatim when successHTML is set
  • Default htmlError served with $ERROR / $DETAILS substitution when errorHTML is unset
  • Custom error HTML served with substitution when errorHTML is set
  • The two fields are independent (overriding only success leaves error unaffected)

go test ./oauth/... passes locally (6 tests including the existing TestEncodeUrlWindowsSuccess).

Compatibility

Pure addition. Existing callers see no behaviour change — the new fields default to empty strings, which routes through the existing constants. No public API removed or renamed. Safe to merge under semver.

The htmlSuccess / htmlError templates are good defaults but shipped as
unexported package vars, so callers can't brand the post-login landing
page short of forking. Adds two optional fields on
AuthorizationCodeTokenSource that override the defaults when set, and
plumbs them through to authHandler via two matching unexported fields.

When empty, the new fields are no-ops and the existing constants are
served, so existing callers see no behaviour change.

The custom error HTML supports the same $ERROR / $DETAILS substitution
the built-in errorHTML does, so callers can reuse the documented format
without having to learn two templating systems.

Tests: five new cases in oauth/authcode_test.go covering default + custom
success, default + custom error, and field independence (overriding
success alone leaves the error path unaffected).
@davidlwg davidlwg force-pushed the davidlwg/customizable-oauth-html branch from a181ae1 to 2474109 Compare May 15, 2026 16:08
@davidlwg davidlwg marked this pull request as ready for review May 15, 2026 16:17
@danielgtaylor
Copy link
Copy Markdown
Collaborator

Superceded by #335, so closing this one. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants