Documentation ¶
Overview ¶
Package webauth provides support for web apps that use form authentication.
Index ¶
- Constants
- Variables
- func CookieValue(r *http.Request, name string) (string, error)
- func GenerateRandomString(n int) (string, error)
- func Hash(s string) string
- func IsEmpty(strs ...string) bool
- func LoginCookie(value string, expires time.Time, session bool) *http.Cookie
- type AuthApp
- func (app *AuthApp) ConfirmHandlerGet(w http.ResponseWriter, r *http.Request)
- func (app *AuthApp) ConfirmHandlerPost(w http.ResponseWriter, r *http.Request)
- func (app *AuthApp) ConfirmRequestHandler(w http.ResponseWriter, r *http.Request)
- func (app *AuthApp) CreateLoginToken(username string) (Token, error)
- func (app *AuthApp) EventsCSVHandler(w http.ResponseWriter, r *http.Request)
- func (app *AuthApp) EventsHandler(w http.ResponseWriter, r *http.Request)
- func (app *AuthApp) ForgotHandler(w http.ResponseWriter, r *http.Request)
- func (app *AuthApp) LoginGetHandler(w http.ResponseWriter, r *http.Request)
- func (app *AuthApp) LoginPostHandler(w http.ResponseWriter, r *http.Request)
- func (app *AuthApp) LoginUser(username, password string) (Token, error)
- func (app *AuthApp) LogoutHandler(w http.ResponseWriter, r *http.Request)
- func (app *AuthApp) RegisterHandler(w http.ResponseWriter, r *http.Request)
- func (app *AuthApp) RenderPage(w http.ResponseWriter, logger *slog.Logger, templateName string, data PageData)
- func (app *AuthApp) ResetHandler(w http.ResponseWriter, r *http.Request)
- func (a *AuthApp) String() string
- func (app *AuthApp) UserGetHandler(w http.ResponseWriter, r *http.Request)
- func (app *AuthApp) UsersCSVHandler(w http.ResponseWriter, r *http.Request)
- func (app *AuthApp) UsersHandler(w http.ResponseWriter, r *http.Request)
- type AuthDB
- func (db *AuthDB) AuthenticateUser(username, password string) error
- func (db *AuthDB) ConfirmUser(username, ctoken string) error
- func (db *AuthDB) CreateConfirmEmailToken(username string) (Token, error)
- func (db *AuthDB) CreateToken(kind, username string, size int, duration string) (Token, error)
- func (db *AuthDB) EmailExists(email string) (bool, error)
- func (db *AuthDB) GetEvents() ([]Event, error)
- func (db *AuthDB) LastLoginForUser(username string) (time.Time, string, error)
- func (db *AuthDB) RegisterUser(username, fullName, email, password string) error
- func (db *AuthDB) RemoveToken(kind, value string) error
- func (db *AuthDB) RowExists(qry string, args ...interface{}) (bool, error)
- func (db *AuthDB) UserExists(username string) (bool, error)
- func (db *AuthDB) UserForLoginToken(loginToken string) (User, error)
- func (db *AuthDB) UserForName(username string) (User, error)
- func (db *AuthDB) UserFromRequest(w http.ResponseWriter, r *http.Request) (User, error)
- func (db *AuthDB) UsernameForConfirmToken(tokenValue string) (string, error)
- func (db *AuthDB) UsernameForEmail(email string) (string, error)
- func (db *AuthDB) UsernameForResetToken(tokenValue string) (string, error)
- func (db *AuthDB) WriteEvent(name EventName, succeeded bool, username, message string) error
- type CommonData
- type Config
- type ConfigAuth
- type ConfigSQL
- type ConfirmData
- type ConfirmRequestPageData
- type Event
- type EventName
- type EventsPageData
- type ForgotPageData
- type LoginForm
- type LoginPageData
- type LogoutPageData
- type Option
- type PageData
- type RedactedConfig
- type RegisterPageData
- type ResetPageData
- type Token
- type User
- type UserPageData
- type UsersPageData
Constants ¶
const ( MsgMissingConfirmToken = "Please provide a token." MsgInvalidConfirmToken = "Token is invalid. Request a new token below." MsgExpiredConfirmToken = "Token is expired. Request a new token below." )
const ( ConfirmTokenSize = 12 // Size of the confirm token ConfirmTokenExpires = "5m" // Token expiry time )
Constants for error and informational messages displayed to the user.
const ( EventLogin EventName = "login" EventLogout = "logout" EventRegister = "register" EventSaveToken = "save_token" EventResetPass = "reset_pass" EventConfirmed = "confirmed" EventMaxName = "1234567890" // Event defined as varchar(10). )
const ( MsgMissingEmail = "Please provide your email." MsgMissingAction = "Please provide an action." MsgInvalidAction = "Please provide a valid action." TemplateForgot = "forgot.html" TemplateForgotSent = "forgot_sent.html" ResetTokenSize = 12 // Size of the password reset token; TODO: move to config ResetTokenExpires = "5m" // Token expiry time; TODO: move to config )
Constants for error and informational messages displayed to the user.
const ( MsgMissingUsernameAndPassword = "Missing username and password." MsgMissingUsername = "Missing username." MsgMissingPassword = "Missing password." MsgLoginFailed = "Login failed." )
const ( MsgMissingRequired = "Please provide required values" MsgUsernameExists = "Username already exists." MsgEmailExists = "Email already registered." MsgPasswordsDifferent = "Passwords do not match." MsgRegisterFailed = "Unable to register user." )
const ConfirmTmpl = "confirm.html"
const LoginTokenCookieName = "login"
const LoginTokenKind = "login"
const LoginTokenSize = 32
Variables ¶
var ( ErrConfigRead = errors.New("failed to read config file") ErrConfigUnmarshal = errors.New("failed to unmarshal config file") )
var ( ErrInitDBOpen = errors.New("db open failed") ErrInitDBPing = errors.New("db ping failed") )
var ( ErrRowExistsDBNil = errors.New("RowExists: db is nil") ErrRowExistsQueryFailed = errors.New("RowExists: query failed") )
var ( ErrWriteEventDBNil = errors.New("WriteEvent: db is nil") ErrWriteEventFailed = errors.New("WriteEvent: db write failed") )
var ( ErrGetEventsDBNil = errors.New("GetEvents: db is nil") ErrGetEventsQuery = errors.New("GetEvents: query failed") ErrGetEventsScan = errors.New("GetEvents: scan failed") ErrGetEventsRows = errors.New("GetEvents: rows.Err()") )
var ( ErrInvalidDB = errors.New("invalid db") ErrUserLoginTokenNotFound = errors.New("user login token not found") ErrUserNotFound = errors.New("user not found") ErrUserLoginTokenExpired = errors.New("user login expired") ErrResetPasswordTokenExpired = errors.New("reset password token expired") ErrConfirmTokenExpired = errors.New("confirm token expired") ErrUserGetLastLoginFailed = errors.New("failed to get user last login") ErrMissingConfirmToken = errors.New("empty confirm token") )
Define command error values.
var ErrAppNil = errors.New("app is nil")
var ErrIncorrectPassword = errors.New("incorrect password")
var ErrInvalidConfig = errors.New("invalid config")
var ErrInvalidLength = errors.New("invalid length")
var ErrRequestNil = errors.New("request is nil")
var ErrTokenNotFound = errors.New("token not found")
Functions ¶
func CookieValue ¶
CookieValue returns the named cookie value provided in the request or an empty string if not found.
func GenerateRandomString ¶
GenerateRandomString returns a URL safe base64 encoded string of n random bytes.
func Hash ¶
Hash returns a hex encoded sha256 Hash of the given string. TODO: should this be a salted Hash to be more secure?
Types ¶
type AuthApp ¶
type AuthApp struct { *webapp.WebApp // Embedded WebApp DB *AuthDB // DB is the database connection. Cfg Config }
AuthApp extends the WebApp to support authentication.
func NewApp ¶
NewApp creates a new AuthApp with the given options and returns it. These options can be either AuthApp or WebApp Options.
func (*AuthApp) ConfirmHandlerGet ¶
func (app *AuthApp) ConfirmHandlerGet(w http.ResponseWriter, r *http.Request)
ConfirmHandlerGet handles confirm GET requests.
func (*AuthApp) ConfirmHandlerPost ¶
func (app *AuthApp) ConfirmHandlerPost(w http.ResponseWriter, r *http.Request)
ConfirmHandlerPost handles confirm POST requests.
func (*AuthApp) ConfirmRequestHandler ¶
func (app *AuthApp) ConfirmRequestHandler(w http.ResponseWriter, r *http.Request)
ConfirmRequestHandler handles a request to request a email confirmation.
func (*AuthApp) CreateLoginToken ¶
CreateLoginToken creates a login token for username.
func (*AuthApp) EventsCSVHandler ¶
func (app *AuthApp) EventsCSVHandler(w http.ResponseWriter, r *http.Request)
EventsCSVHandler provides list of events as a CSV file.
func (*AuthApp) EventsHandler ¶
func (app *AuthApp) EventsHandler(w http.ResponseWriter, r *http.Request)
EventsHandler displays a list of events.
func (*AuthApp) ForgotHandler ¶
func (app *AuthApp) ForgotHandler(w http.ResponseWriter, r *http.Request)
ForgotHandler handles HTTP requests for forgot user or password.
func (*AuthApp) LoginGetHandler ¶
func (app *AuthApp) LoginGetHandler(w http.ResponseWriter, r *http.Request)
LoginGetHandler handles login GET requests.
func (*AuthApp) LoginPostHandler ¶
func (app *AuthApp) LoginPostHandler(w http.ResponseWriter, r *http.Request)
LoginPostHandler handles login POST requests.
func (*AuthApp) LoginUser ¶
LoginUser returns a login token if the username and password are correct.
func (*AuthApp) LogoutHandler ¶
func (app *AuthApp) LogoutHandler(w http.ResponseWriter, r *http.Request)
LogoutHandler handles /logout requests.
func (*AuthApp) RegisterHandler ¶
func (app *AuthApp) RegisterHandler(w http.ResponseWriter, r *http.Request)
RegisterHandler handles requests to register a user.
func (*AuthApp) RenderPage ¶
func (app *AuthApp) RenderPage(w http.ResponseWriter, logger *slog.Logger, templateName string, data PageData)
RenderPage renders a web page using the specified template and data.
If the page cannot be rendered, http.StatusInternalServerError is set and the caller should ensure no further writes are done to w.
func (*AuthApp) ResetHandler ¶
func (app *AuthApp) ResetHandler(w http.ResponseWriter, r *http.Request)
ResetHandler handles /reset requests.
func (*AuthApp) UserGetHandler ¶
func (app *AuthApp) UserGetHandler(w http.ResponseWriter, r *http.Request)
UserGetHandler shows user information.
func (*AuthApp) UsersCSVHandler ¶
func (app *AuthApp) UsersCSVHandler(w http.ResponseWriter, r *http.Request)
UsersCSVHandler provides list of the current users as a CSV file.
func (*AuthApp) UsersHandler ¶
func (app *AuthApp) UsersHandler(w http.ResponseWriter, r *http.Request)
UsersHandler shows a list of the current users.
type AuthDB ¶
func (*AuthDB) AuthenticateUser ¶
AuthenticateUser compares the password and hashed password for the user. Returns nil on success or an error on failure.
func (*AuthDB) ConfirmUser ¶
ConfirmUser updates database to indicate user confirmed their email.
func (*AuthDB) CreateConfirmEmailToken ¶
CreateConfirmEmailToken generates a new token to confirm a user's email.
func (*AuthDB) CreateToken ¶
CreateToken creates and saves a token for user of size that expires in duration.
func (*AuthDB) EmailExists ¶
EmailExists returns true if the given email already exists.
func (*AuthDB) LastLoginForUser ¶
LastLoginForUser retrieves the last login time and result for a given username. It returns zero values in case of no previous login.
func (*AuthDB) RegisterUser ¶
RegisterUser registers a user with the given values. Returns nil on success or an error on failure.
func (*AuthDB) RemoveToken ¶
RemoveToken removes the token with kind and value.
func (*AuthDB) RowExists ¶
RowExists checks if the given SQL query returns at least one row. The query should be in the form "SELECT 1 FROM ... WHERE ... LIMIT 1".
func (*AuthDB) UserExists ¶
UserExists returns true if the given username already exists in db.
func (*AuthDB) UserForLoginToken ¶
UserForLoginToken returns a user for the given loginToken.
func (*AuthDB) UserForName ¶
UserForName returns a user for the given username.
func (*AuthDB) UserFromRequest ¶
UserFromRequest returns the user for the login token cookie in the request. If the login token is invalid or expired, the cookie is removed and an empty user returned.
func (*AuthDB) UsernameForConfirmToken ¶
UsernameForConfirmToken returns the username for a given confirm token.
If token is not found, ErrUserNotFound is returned.
If token is expired, ErrConfirmTokenExpired is returned and token is removed.
If a SQL error occurs, it will be returned, except ErrNoRows.
func (*AuthDB) UsernameForEmail ¶
UsernameForEmail looks up a username based on their email address.
If not found, ErrUserNotFound is returned.
If a SQL error occurs, other than ErrNoRows, it is returned.
func (*AuthDB) UsernameForResetToken ¶
UsernameForResetToken returns the username for a given reset token.
type CommonData ¶
type CommonData struct {
Title string
}
CommonData holds common fields for page data.
func (*CommonData) SetDefaultTitle ¶
func (c *CommonData) SetDefaultTitle(appName string)
SetDefaultTitle ensures that the Title of CommonPageData is not empty. If Title is empty, this method sets it to the value of appName.
type Config ¶
type Config struct { webapp.Config // Inherit webapp.Config Auth ConfigAuth // Auth app configuration. SQL ConfigSQL // SQL Database configuration. SMTP webutil.SMTPConfig // SMTP server configuration. }
Config represents the overall application configuration.
func ConfigFromJSONFile ¶
ConfigFromJSONFile loads configuration settings from a JSON file.
func (*Config) IsValid ¶
IsValid checks if all required Config fields are populated. Returns a boolean and a slice of messages indicating the issue(s).
func (*Config) MarshalJSON ¶
MarshalJSON customizes JSON marshalling to redact sensitive Config data.
type ConfigAuth ¶
type ConfigAuth struct { BaseURL string `required:"true"` // Base URL of the application. LoginExpires string `required:"true"` // Duration string for expiry. }
ConfigAuth holds settings specific to the auth app.
type ConfigSQL ¶
type ConfigSQL struct { DriverName string `required:"true"` // Database driver name. DataSourceName string `required:"true"` // Database connection string. }
ConfigSQL hold SQL database connection settings.
type ConfirmData ¶
type ConfirmData struct { CommonData Message string ConfirmToken string }
ConfirmData contains data to render the confirm template.
type ConfirmRequestPageData ¶
type ConfirmRequestPageData struct { CommonData Message string // An message to display to the user. EmailFrom string // The email address that sends the confirm message. }
ConfirmRequestPageData contains data to render the confirm request template.
type Event ¶
type Event struct { Name EventName // Name of the event. Succeeded bool // Indicates if the event was successful. Username string // Username associated with the event. Message string // Message or details about the event. Created time.Time // Timestamp of event, set by db when inserted. }
Event represents a system event, such as a user login or registration.
type EventsPageData ¶
type EventsPageData struct { CommonData User User Events []Event }
EventsPageData contains data passed to the HTML template.
type ForgotPageData ¶
type ForgotPageData struct { CommonData Message string // An informational or error message to display to the user. EmailFrom string // The email address from which the reset or reminder email will be sent. }
ForgotPageData contains data required to render the forgot templates.
type LoginForm ¶
func ParseLoginForm ¶
ParseLoginForm extracts and validates the login form fields. Message is updated with any errors related to the validation.
type LoginPageData ¶
type LoginPageData struct { CommonData Message string }
LoginPageData contains data passed to the HTML template.
type LogoutPageData ¶
type LogoutPageData struct { CommonData Message string }
LogoutPageData contains data passed to the HTML template.
type Option ¶
type Option func(*AuthApp)
Option is a function type used to apply configuration options to a AuthApp. This follows the Option pattern from https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html and elsewhere.
func WithConfig ¶
WithConfig returns an Option to set the Config for a AuthApp.
type PageData ¶
type PageData interface {
SetDefaultTitle(appName string)
}
PageData is an interface that all page data structs must implement.
type RedactedConfig ¶
type RedactedConfig Config
RedactedConfig provides a redacted copy of Config for secure logging.
type RegisterPageData ¶
type RegisterPageData struct { CommonData Message string }
RegisterPageData contains data passed to the HTML template.
type ResetPageData ¶
ResetPageData contains data passed to the HTML template.
type User ¶
type User struct { Username string FullName string Email string IsAdmin bool Confirmed bool Created time.Time LastLoginTime time.Time LastLoginResult string // TODO: implement as bool? }
User represents in the application.
var EmptyUser User // EmptyUser is a empty User used when returning a error.
type UserPageData ¶
UserPageData contains data passed to the HTML template.