weblogin

package module
v0.0.0-...-b5b2547 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 19, 2023 License: Apache-2.0 Imports: 21 Imported by: 1

README

go-web-login

go-web-login is an example of golang web app (https server) that implement Form based authentication with session cookies.

Many of the principles from https://stackoverflow.com/questions/549/the-definitive-guide-to-form-based-website-authentication and https://security.stackexchange.com/questions/117854/how-to-implement-forgot-password-functionality have or will be implemented.

Documentation

Overview

Copyright 2023 Bill Nixon

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Index

Constants

View Source
const (
	EventLogin     = "login"
	EventLogout    = "logout"
	EventRegister  = "register"
	EventSaveToken = "save_token"
	EventReset     = "reset_pass"
	EventMax       = "1234567890"
)
View Source
const (
	MsgMissingEmail  = "Please provide an Email."
	MsgNoSuchUser    = "There is no user for the Email provided."
	MsgMissingAction = "Action is missing."
	MsgInvalidAction = "Action is invalid."
)
View Source
const (
	MsgMissingUserNameAndPassword = "Missing username and password"
	MsgMissingUserName            = "Missing username"
	MsgMissingPassword            = "Missing password"
	MsgLoginFailed                = "Login Failed"
)
View Source
const (
	MsgMissingRequired    = "Please provide all the required values"
	MsgUserNameExists     = "User Name already exists."
	MsgEmailExists        = "Email Address already registered."
	MsgPasswordsDifferent = "Password values do not match."
)
View Source
const MsgTemplateError = "Sorry, the server was unable to display this page. Please contact the administrator."
View Source
const ReqIDKey ctxReqIDKey = 0

ReqIDKey is the key for the unique request ID in a request context.

View Source
const SessionTokenCookieName = "session"

Variables

View Source
var (
	ErrAppGetConfig     = errors.New("failed")
	ErrAppInvalidConfig = errors.New("invalid config")
	ErrAppInitDB        = errors.New("failed")
	ErrAppInitTemplates = errors.New("failed")
)
View Source
var (
	ErrConfigOpen   = errors.New("failed")
	ErrConfigDecode = errors.New("failed to decode")
)
View Source
var (
	ErrDBOpen = errors.New("failed to open db")
	ErrDBPing = errors.New("failed to ping db")
)
View Source
var (
	ErrUserSessionNotFound    = errors.New("user session not found")
	ErrUserNotFound           = errors.New("user not found")
	ErrUserSessionExpired     = errors.New("user session expired")
	ErrUserGetLastLoginFailed = errors.New("user failed to get last login")
)

Define command error values.

View Source
var ErrInvalidLength = errors.New("invalid length")
View Source
var ErrRequestNil = errors.New("request is nil")

Functions

func CompareUserPassword

func CompareUserPassword(db *sql.DB, userName, password string) error

CompareUserPassword compares the password and hashed password for the user. Returns nil on success or an error on failure.

func EmailExists

func EmailExists(db *sql.DB, email string) (bool, error)

EmailExists returns true if the given email already exists.

func GenerateRandomString

func GenerateRandomString(n int) (string, error)

GenerateRandomString returns a URL safe base64 encoded string of n random bytes.

func GetCookieValue

func GetCookieValue(r *http.Request, name string) (string, error)

GetCookieValue returns the Value for the named cookie or an empty string if not found or an error occurs.

func GetRealRemoteAddr

func GetRealRemoteAddr(r *http.Request) string

GetRealRemoteAddr returns X-Real-IP header or r.RemoteAddr.

func GetReqID

func GetReqID(ctx context.Context) string

GetReqID returns the request ID from ctx if present, otherwise "".

func GetUserNameForEmail

func GetUserNameForEmail(db *sql.DB, email string) (string, error)

GetUserNameForEmail returns the userName for a given email.

func GetUserNameForResetToken

func GetUserNameForResetToken(db *sql.DB, tokenValue string) (string, error)

GetUserNameForResetToken returns the userName for a given reset token.

func InitDB

func InitDB(driverName, dataSourceName string) (*sql.DB, error)

InitDB initializes a connection to the database.

func InitLog

func InitLog(logFileName string, logLevel slog.Level, addSource bool) error

InitLog initializes logging for the application.

func InitTemplates

func InitTemplates(pattern string) (*template.Template, error)

InitTemplates parses the templates.

func IsEmpty

func IsEmpty(strs ...string) bool

IsEmpty returns true if any of the strings are empty, otherwise false.

func LastLoginForUser

func LastLoginForUser(db *sql.DB, userName string) (time.Time, string, error)

LastLoginForUser retrieves the last login time and result for a given userName. It returns zero values in case of no previous login.

func LogRequestHandler

func LogRequestHandler(next http.Handler) http.Handler

LogRequestHandler is middleware that logs all HTTP requests.

func RegisterUser

func RegisterUser(db *sql.DB, userName, fullName, email, password string) error

RegisterUser registers a user with the given values. Returns nil on success or an error on failure.

func RemoveToken

func RemoveToken(db *sql.DB, tType, tValue string) error

RemoveToken removes the given sessionToken.

func RenderTemplate

func RenderTemplate(t *template.Template, w http.ResponseWriter, name string, data interface{}) error

RenderTemplate executes the named template with given data to the writer. If an error occurs, writer is updated to indicate a Internal Server Error. The caller must ensure no further writes are done for a non-nil error.

func RequestIDHandler

func RequestIDHandler(next http.Handler) http.Handler

RequestIDHandler is middleware that adds a unique request ID to the request context.

func RowExists

func RowExists(db *sql.DB, qry string, args ...interface{}) (bool, error)

RowExists return true if the given query returns at least one row. qry should be of the form "SELECT 1 ..."

func SendEmail

func SendEmail(smtpUser, smtpPassword, smtpHost, smtpPort, to, subject, body string) error

SendEmail will send an email using the values provided.

func ServeFileHandler

func ServeFileHandler(file string) http.HandlerFunc

ServeFileHandler returns a HandlerFunc to serve the specified file.

func StringContains

func StringContains(slice []string, value string) bool

StringContains reports if slice contain value.

func UserExists

func UserExists(db *sql.DB, userName string) (bool, error)

UserExists returns true if the given userName already exists in db.

func ValidMethod

func ValidMethod(w http.ResponseWriter, r *http.Request, allowed []string) bool

ValidMethod checks if the given HTTP request method is allowed based on the provided list of allowed methods. It returns true if the method is allowed, and false otherwise. If the method is not allowed or is OPTIONS, the function updates the response writer appropriately and returns false. The calling handler should return without further processing.

func WriteEvent

func WriteEvent(db *sql.DB, name string, result bool, user, message string)

WriteEvent will write an event to the database. There is no return value and if an error is encountered, it will be logged.

Types

type App

type App struct {
	DB    *sql.DB
	Tmpls *template.Template
	Cfg   Config
}

App contains common variables to avoid using global variables.

func NewApp

func NewApp(configFilename string) (*App, error)

NewApp returns a new App based on the config filename provided.

func (*App) ForgotHandler

func (app *App) ForgotHandler(w http.ResponseWriter, r *http.Request)

ForgotHandler handles /forgot requests.

func (*App) HelloHandler

func (app *App) HelloHandler(w http.ResponseWriter, r *http.Request)

HelloHandler prints a simple hello and any user information.

func (*App) LoginHandler

func (app *App) LoginHandler(w http.ResponseWriter, r *http.Request)

LoginHandler handles /login requests.

func (*App) LoginUser

func (app *App) LoginUser(userName, password string) (Token, error)

LoginUser returns a session Token if userName and password is correct.

func (*App) LogoutHandler

func (app *App) LogoutHandler(w http.ResponseWriter, r *http.Request)

LogoutHandler handles /logout requests.

func (*App) RegisterHandler

func (app *App) RegisterHandler(w http.ResponseWriter, r *http.Request)

RegisterHandler handles /register requests.

func (*App) ResetHandler

func (app *App) ResetHandler(w http.ResponseWriter, r *http.Request)

ResetHandler handles /reset requests.

func (*App) UsersHandler

func (app *App) UsersHandler(w http.ResponseWriter, r *http.Request)

UsersHandler prints a simple hello message.

type Config

type Config struct {
	Title               string // title of the application
	BaseURL             string // base URL, e.g., https://host:port
	ParseGlobPattern    string // pattern to use with template.ParseGlob
	SessionExpiresHours int    // number of hours user session is valid
	Server              ConfigServer
	SQL                 ConfigSQL
	SMTP                ConfigSMTP
}

Config represents the configuration values.

func GetConfigFromFile

func GetConfigFromFile(filename string) (Config, error)

GetConfigFromFile returns the Config from filename.

func (*Config) IsValid

func (c *Config) IsValid() (bool, []string)

IsValid returns true if the config has all the required values.

func (Config) MarshalJSON

func (c Config) MarshalJSON() ([]byte, error)

MarshalJSON is a custom Marshaler to redact some fields.

func (Config) String

func (c Config) String() string

String is a custom Stringer to redact some fields.

type ConfigSMTP

type ConfigSMTP struct {
	Host     string
	Port     string
	User     string
	Password string
}

ConfigSMTP contains SMTP related configuration values.

type ConfigSQL

type ConfigSQL struct {
	DriverName     string
	DataSourceName string
}

ConfigSQL contains SQL related configuration values.

type ConfigServer

type ConfigServer struct {
	Host string
	Port string
}

ConfigServer contains Server related configuration values.

type Event

type Event struct {
	Name     string // name of the event
	Result   bool   // result of the event
	UserName string // username for the event
	Message  string // message associated with event
	Created  time.Time
}

type ForgotPageData

type ForgotPageData struct {
	Title     string
	Message   string
	EmailFrom string
}

ForgotPageData contains data passed to the HTML template.

type HelloPageData

type HelloPageData struct {
	Title   string
	Message string
	User    User
}

HelloPageData contains data passed to the HTML template.

type LoginPageData

type LoginPageData struct {
	Title   string
	Message string
}

LoginPageData contains data passed to the HTML template.

type LogoutPageData

type LogoutPageData struct {
	Title   string
	Message string
}

LogoutPageData contains data passed to the HTML template.

type MailMessage

type MailMessage struct {
	From    string
	To      string
	Subject string
	Body    string
}

MailMessage contains data to include in the email template.

type RedactedConfig

type RedactedConfig Config

RedactedConfig is a copy of Config used to redact values on output.

type RegisterPageData

type RegisterPageData struct {
	Title   string
	Message string
}

RegisterPageData contains data passed to the HTML template.

type ResetPageData

type ResetPageData struct {
	Title      string
	Message    string
	ResetToken string
}

ResetPageData contains data passed to the HTML template.

type Token

type Token struct {
	Value   string
	Expires time.Time
	Type    string
}

Token represent a token for the user.

func SaveNewToken

func SaveNewToken(db *sql.DB, tType, userName string, size, hrs int) (Token, error)

SaveNewToken creates and saves a token for user of size that expires in hrs.

type User

type User struct {
	UserName        string
	FullName        string
	Email           string
	IsAdmin         bool
	Created         time.Time
	LastLoginTime   time.Time
	LastLoginResult string
}

User represents a user stored in the database.

func GetUserForName

func GetUserForName(db *sql.DB, userName string) (User, error)

GetUserForName returns a user for the given userName.

func GetUserForSessionToken

func GetUserForSessionToken(db *sql.DB, sessionToken string) (User, error)

GetUserForSessionToken returns a user for the given sessionToken.

func GetUserFromRequest

func GetUserFromRequest(w http.ResponseWriter, r *http.Request, db *sql.DB) (User, error)

GetUserFromRequest returns the current User or empty User if the session is not found.

func GetUsers

func GetUsers(db *sql.DB) ([]User, error)

GetUsers returns a list of all users.

type UsersPageData

type UsersPageData struct {
	Title   string
	Message string
	User    User
	Users   []User
}

UsersPageData contains data passed to the HTML template.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL