Documentation
¶
Overview ¶
Package authui serves ready-made, server-rendered pages for the common flows — sign in, sign up, forgot and reset password, verify email, the two-factor step, and account settings — for apps that do not build their own. It is optional: the library is headless, and every page here is a thin form over the same typed Go API an app would call, so every rule of the pipeline applies.
The pages live at the paths the plugins' default links point to (/verify-email, /reset-password, /magic-link), so mail links work with no configuration. They are plain HTML forms that work without JavaScript; a small script adds show-password toggles. Every POST — sign-in included — is refused unless its Origin is trusted, which the pipeline cannot check for a sign-in because no session cookie exists yet: without it, a hostile page could sign a visitor into the attacker's account.
Index ¶
- Constants
- Variables
- func DefaultTemplates() fs.FS
- func DefaultTexts() map[string]string
- func Handler(a *auth.Auth, opts ...Option) http.Handler
- type Option
- func APIPrefix(p string) Option
- func AfterSignIn(path string) Option
- func AppName(name string) Option
- func HTTPOptions(opts ...authhttp.Option) Option
- func Methods(m ...authhttp.SignInMethod) Option
- func Prefix(p string) Option
- func Templates(fsys fs.FS) Option
- func TermsURL(u string) Option
- func Texts(c auth.MessageCatalog) Option
- type TextKey
Constants ¶
const ( //ds:def id=pathlogin-eafqgnka owner=@khanakia stability=stable PathLogin = "/login" //ds:def id=pathsignup-dyp2pd6b owner=@khanakia stability=stable PathSignup = "/signup" //ds:def id=pathforgot-rtazq8zj owner=@khanakia stability=stable PathForgot = "/forgot-password" //ds:def id=pathreset-ex6z22hc owner=@khanakia stability=stable PathReset = "/reset-password" //ds:def id=pathverify-3hsmy6r7 owner=@khanakia stability=stable PathVerify = "/verify-email" //ds:def id=pathmagic-xs2qcwh5 owner=@khanakia stability=stable PathMagic = "/magic-link" //ds:def id=pathmagicsend-wfrkehrn owner=@khanakia stability=stable PathMagicSend = "/magic-link-send" //ds:def id=pathtwofactor-2atudgb3 owner=@khanakia stability=stable PathTwoFactor = "/two-factor" //ds:def id=pathsettings-53hm2zqk owner=@khanakia stability=stable PathSettings = "/settings" //ds:def id=pathlogout-gf6hx9n8 owner=@khanakia stability=stable PathLogout = "/logout" //ds:def id=pathlogoutall-sc34tgn6 owner=@khanakia stability=stable PathLogoutAll = "/logout-everywhere" )
Page paths, relative to the prefix. The verify, reset and magic-link paths match the plugins' default link pages.
Variables ¶
var ErrOriginRefused = auth.NewError("authui.origin_refused", http.StatusForbidden, "This form was sent from another site. Open the page again and retry.")
ErrOriginRefused answers a form posted from a site that is not trusted, or with no Origin or Referer at all: without it, a hostile page could sign a visitor into the attacker's account (login CSRF).
Functions ¶
func DefaultTemplates ¶
DefaultTemplates is the file system of the built-in templates and static files, laid out as Templates expects. An app that overrides a few pages copies the rest from here, or serves them through its own fs.FS that falls back to this one.
func DefaultTexts ¶
DefaultTexts returns the English text of every key, as a translator's template: {"authui.sign_in": "Sign in", …}. Translate the values, put them under a locale in an auth.Messages map, and pass it to Texts (and, with the error codes, to auth.WithMessages). The identifier labels are not in it, because their English depends on the configured kinds; add TextSignInIdentifier and its siblings to translate them. It is a copy, so changing it changes nothing.
Types ¶
type Option ¶
type Option func(*config)
Option configures the pages.
func APIPrefix ¶
APIPrefix is where the app mounted authhttp.Handler, such as "/auth"; the sign-in methods plugins offer (authhttp.UIMethod) link to their routes under it. The default is "", authhttp's own default.
func AfterSignIn ¶
AfterSignIn is where a successful sign-in or sign-up lands, a path on this site. The default is "/". It is fixed at startup rather than read from the request, so no link can turn the sign-in page into an open redirect.
func AppName ¶
AppName is shown after the page name in every title ("Sign in · Acme"). The default is "Account".
func HTTPOptions ¶
HTTPOptions passes authhttp options, such as authhttp.CookieDomain, which must match the rest of the app.
func Methods ¶
func Methods(m ...authhttp.SignInMethod) Option
Methods adds sign-in buttons to the sign-in and sign-up pages, after the ones plugins offer through authhttp.UIMethod: the escape hatch for a method whose plugin offers none, or an app that wants its own label. A method with the ID of a plugin's (such as "oauth.github") replaces that one in place, so an app that listed its OAuth buttons before the OAuth plugin offered them keeps exactly its own.
func Prefix ¶
Prefix mounts the pages under p, such as "/account"; a trailing slash is dropped. The plugins' default links assume no prefix; with one, set their Links options to match, or mailed links land on a 404.
func Templates ¶
Templates replaces the built-in pages with the templates in fsys, which is laid out like DefaultTemplates:
- layout.html defines "layout", the outer page; it calls {{template "body" .}} and may call {{template "methods" .}} if it defines one.
- login.html, signup.html, forgot.html, reset.html, token.html and settings.html each define "body".
- ui.css and ui.js, when present, replace the built-in static files at <prefix>/_authui/; when absent the built-in ones are served.
Every page is parsed with layout.html when Handler runs, so a missing or broken file panics at start-up instead of failing one request later. Templates read the page's fields ({{.Error}}, {{.Identifier}}, {{.Methods}}, ...) and text through {{.T "authui.sign_in"}}; the form field names the handlers read are the name attributes of the built-in templates, which a replacement must keep. Pages are served with a CSP of default-src 'self', so styles and scripts must be files on this site.
func TermsURL ¶
TermsURL is the page the sign-up form links the terms to. It is shown only when the terms plugin is registered.
func Texts ¶
func Texts(c auth.MessageCatalog) Option
Texts translates the pages: every heading, label, button and notice is looked up in c by its TextKey in the request's locale (auth.Auth.Locale: the client's language, then auth.WithDefaultLocale), and a key c lacks shows its English text, so a half-done translation never shows a blank. An auth.Messages map works, the same one that translates the errors, and so does any auth.MessageCatalog. The page's lang attribute is the request's locale. Without Texts every page is in English.
type TextKey ¶
type TextKey string
TextKey names one piece of page text: a heading, a label, a button, a notice. The keys share the "authui." prefix so a single auth.Messages map can hold an app's error translations and its page translations without a collision; the value of each key is the English text in DefaultTexts.
const ( TextSignIn TextKey = "authui.sign_in" TextCreateAccount TextKey = "authui.create_account" TextPassword TextKey = "authui.password" TextName TextKey = "authui.name" TextRemember TextKey = "authui.remember" TextForgotLink TextKey = "authui.forgot_link" TextMagicLabel TextKey = "authui.magic_label" TextMagicButton TextKey = "authui.magic_button" TextNoAccount TextKey = "authui.no_account" TextSignUpLink TextKey = "authui.sign_up_link" TextAcceptTerms TextKey = "authui.accept_terms" TextTerms TextKey = "authui.terms" TextHaveAccount TextKey = "authui.have_account" TextForgotTitle TextKey = "authui.forgot_title" TextSendReset TextKey = "authui.send_reset" TextBackToSignIn TextKey = "authui.back_to_sign_in" TextResetTitle TextKey = "authui.reset_title" TextNewPassword TextKey = "authui.new_password" TextSetPassword TextKey = "authui.set_password" TextCode TextKey = "authui.code" TextVerifyTitle TextKey = "authui.verify_title" TextVerifyPrompt TextKey = "authui.verify_prompt" TextVerifyButton TextKey = "authui.verify_button" TextMagicPrompt TextKey = "authui.magic_prompt" TextTwoFactorTitle TextKey = "authui.two_factor_title" TextTwoFactorPrompt TextKey = "authui.two_factor_prompt" TextContinue TextKey = "authui.continue" TextAccountTitle TextKey = "authui.account_title" TextSignedInAs TextKey = "authui.signed_in_as" TextProfile TextKey = "authui.profile" TextSave TextKey = "authui.save" TextCurrentPassword TextKey = "authui.current_password" TextChangePassword TextKey = "authui.change_password" TextSessions TextKey = "authui.sessions" TextUnknownDevice TextKey = "authui.unknown_device" TextThisSession TextKey = "authui.this_session" TextImpersonated TextKey = "authui.impersonated" TextSince TextKey = "authui.since" TextEndSession TextKey = "authui.end_session" TextSignOut TextKey = "authui.sign_out" TextSignOutAll TextKey = "authui.sign_out_all" TextRefusedTitle TextKey = "authui.refused_title" // The identifier field of each form. The English default is built from // the configured kinds ("Email or username"); a translation replaces the // whole label, because word order and capitals differ by language. TextSignInIdentifier TextKey = "authui.sign_in_identifier" TextSignUpIdentifier TextKey = "authui.sign_up_identifier" TextForgotIdentifier TextKey = "authui.forgot_identifier" // Notices, the fixed texts a ?notice= key selects. TextNoticeReset TextKey = "authui.notice_reset" TextNoticeCheck TextKey = "authui.notice_check" TextNoticeVerified TextKey = "authui.notice_verified" TextNoticeSaved TextKey = "authui.notice_saved" TextNoticeSignedOut TextKey = "authui.notice_signed_out" TextNoticePassword TextKey = "authui.notice_password" )
Page text keys. Every string a page shows that is not the user's own data or an error message (errors follow auth.WithMessages) is one of these; TestTexts_EveryKeyHasEnglish pins that each has an English default.