auth

package module
v0.26.0 Latest Latest
Warning

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

Go to latest
Published: Nov 26, 2025 License: GPL-3.0 Imports: 15 Imported by: 0

README

Auth Open in Gitpod

Tests Status Go Report Card PkgGoDev

Authentication library for Golang with two separate flows:

  1. Username/email and password - The user logs in via a username and password. Using email instead of username is also supported. These days most of the applications will use email instad of username, as it is more convenient for the user not having to remember a username.

  2. Passwordless - A verification code is emailed to the user on each login. The user does not have to remember a password. This flow is recommended because it is safer as it relieves the application from having to securely store passwords.

The aim of this library is to provide a quick preset for authentication, which includes:

  1. User interface

  2. HTTP handler

  3. Authentication middleware

It will then leave the actual implementation to you - where to save the tokens, session, users, etc.

Installation

go get github.com/dracory/auth

Usage of the Username/email and Password Flow

  • Implement your functions
// userFindByEmail find the user by the provided email, and returns the user ID
//
// retrieve the userID from your database
// note that the username can be an email (if you wish)
//
func userFindByUsername(username string, firstName string, lastName string) (userID string, err error) {
    // your code here
	return "yourUserId", nil
}

// userRegister registers the user
//
// save the user to your databases
// note that the username can be an email (if you wish)
//
func userRegister(username string, password string, first_name string, last_name string) error {
    // your code here
	return nil
}

// userLogin logs the user in
//
// find the user by the specified username and password, 
// note that the username can be an email (if you wish)
//
func userLogin(username string, password string, userIP string, userAgent string) (userID string, err error) {
    // your code here
	return "yourUserId", nil
}

// userLogout logs the user out
//
// remove the auth token from wherever you have stored it (i.e. session store or the cache store)
//
func userLogout(userID string) (err error) {
    // your code here (remove token from session or cache store)
	return nil
}

// userStoreAuthToken stores the auth token with the provided user ID
//
// save the auth token to your selected store it (i.e. session store or the cache store)
// make sure you set an expiration time (i.e. 2 hours)
//
func userStoreAuthToken(token string, userID string, userIP string, userAgent string) error {
    // your code here (store in session or cache store with desired timeout)
	return nil
}

// userFindByAuthToken find the user by the provided token, and returns the user ID
//
// retrieve the userID from your selected store  (i.e. session store or the cache store)
//
func userFindByAuthToken(token string, userIP string, userAgent string) (userID string, err error) {
    // your code here
	return "yourUserId", nil
}
  • Setup the auth settings
auth, err := auth.NewUsernameAndPasswordAuth(auth.ConfigUsernameAndPassword{
	EnableRegistration:              	true,
	EnableVerification:              	true, // optional, required only if you want the email to be verified before completing the registration
	Endpoint:                        	"/",
	UrlRedirectOnSuccess:            	"http://localhost/user/dashboard",
	FuncUserFindByAuthToken:         	userFindByAuthToken,
	FuncUserFindByUsername:          	userFindByUsername,
	FuncUserLogin:                   	userLogin,
	FuncUserLogout:                  	userLogout,
	FuncUserRegister:                	userRegister, // optional, required only if registration is enabled
	FuncUserStoreAuthToken:          	userStoreAuthToken,
	FuncEmailSend:				emailSend,
	FuncEmailTemplatePasswordRestore:	emailTemplatePasswordRestore, // optional, if you want to set custom email template
	FuncTemporaryKeyGet:             	tempKeyGet,
	FuncTemporaryKeySet:             	tempKeySet,
})
  • Attach to router
mux := http.NewServeMux()

// Example index page with login link
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("This is the index page visible to anyone on the internet. Login at: " + auth.LinkLogin()))
})

// Attach the authentication URLs
mux.HandleFunc("/auth/", auth.Router)
  • Used the AuthMiddleware to protect the authenticated routes
// Put your auth routes after the Auth middleware
mux.Handle("/user/dashboard", auth.AuthMiddleware(dashboardHandler("IN AUTHENTICATED DASHBOARD")))

Usage of the Passwordless Flow

  • Implement your functions
// emailSend sends an email to the provided email
func emailSend(email string, emailSubject string, emailBody string) error {
	// your code here
	return nil
}

// userFindByEmail find the user by the provided email, and returns the user ID
//
// retrieve the userID from your database
//
func userFindByEmail(email string) (userID string, err error) {
	// your code here
	return "yourUserId", nil
}

// userRegister registers the user
//
// save the user to your databases
// note that the username can be an email (if you wish)
//
func userRegister(email string, first_name string, last_name string) error {
    // your code here
	return nil
}

// userLogout logs the user out
//
// remove the auth token from wherever you have stored it (i.e. session store or the cache store)
//
func userLogout(userID string) (err error) {
    // your code here (remove token from session or cache store)
	return nil
}

// userStoreAuthToken stores the auth token with the provided user ID
//
// save the auth token to your selected store it (i.e. session store or the cache store)
// make sure you set an expiration time (i.e. 2 hours)
//
func userStoreAuthToken(token string, userID string) error {
    // your code here (store in session or cache store with desired timeout)
	return nil
}

// userFindByAuthToken find the user by the provided token, and returns the user ID
//
// retrieve the userID from your selected store  (i.e. session store or the cache store)
//
func userFindByAuthToken(token string) (userID string, err error) {
    // your code here
	return "yourUserId", nil
}
  • Setup the auth settings
auth, err := auth.NewPasswordlessAuth(auth.ConfigPasswordless{
	EnableRegistration:		true,				// optional, required only if registration is required
	Endpoint:			"/",
	UrlRedirectOnSuccess:		"http://localhost/user/dashboard",
	FuncUserFindByAuthToken:	userFindByAuthToken,
	FuncUserFindByEmail:		userFindByEmail,
	FuncUserLogout:			userLogout,
	FuncUserRegister:		userRegister,			// optional, required only if registration is enabled
	FuncUserStoreAuthToken:		userStoreAuthToken,
	FuncEmailSend:			emailSend,
	FuncEmailTemplateLoginCode:	emailLoginCodeTemplate,		// optional, if you want to customize the template
	FuncEmailTemplateRegisterCode:	emailRegisterCodeTemplate,	// optional, if you want to customize the template
	FuncTemporaryKeyGet:        	tempKeyGet,
	FuncTemporaryKeySet:		tempKeySet,
})
  • Attach to router
mux := http.NewServeMux()

// Example index page with login link
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("This is the index page visible to anyone on the internet. Login at: " + auth.LinkLogin()))
})

// Attach the authentication URLs
mux.HandleFunc("/auth/", auth.Router)
  • Used the AuthMiddleware to protect the authenticated routes
// Put your auth routes after the Auth middleware
mux.Handle("/user/dashboard", auth.AuthMiddleware(dashboardHandler("IN AUTHENTICATED DASHBOARD")))

Frequently Asked Questions

  1. Can I use email and password instead of username and password to login users?

Yes you absolutely can.

  1. Can I use username and password flow for regular users and passwordless flow for admin users?

Yes you can. You just instantiate two separate instances, and atatch each separate HTTP handler to listen on its own path. For instance you may use /auth for regular users and /auth-admin for administrators

Other Noteable Auth Projects

Documentation

Index

Constants

View Source
const (
	CookieName = "authtoken"

	// PathApiLogin contains the path to api login endpoint
	PathApiLogin string = "api/login"

	// PathApiLoginCodeVerify contains the path to api login code verification endpoint
	PathApiLoginCodeVerify string = "api/login-code-verify"

	// PathApiLogout contains the path to api logout endpoint
	PathApiLogout string = "api/logout"

	// PathApiRegister contains the path to api register endpoint
	PathApiRegister string = "api/register"

	// PathApiRegisterCodeVerify contains the path to api register code verification endpoint
	PathApiRegisterCodeVerify string = "api/register-code-verify"

	// PathApiRestorePassword contains the path to api restore password endpoint
	PathApiRestorePassword string = "api/restore-password"

	// PathApiResetPassword contains the path to api reset password endpoint
	PathApiResetPassword string = "api/reset-password"

	// PathLogin contains the path to login page
	PathLogin string = "login"

	// PathLoginCodeVerify contains the path to login code verification page
	PathLoginCodeVerify string = "login-code-verify"

	// PathLogout contains the path to logout page
	PathLogout string = "logout"

	// PathRegister contains the path to logout page
	PathRegister string = "register"

	// PathRegisterCodeVerify contains the path to registration code verification page
	PathRegisterCodeVerify string = "register-code-verify"

	// PathRestore contains the path to password restore page
	PathPasswordRestore string = "password-restore"

	// PathReset contains the path to password reset page
	PathPasswordReset string = "password-reset"

	// LoginCodeLength specified the length of the login code
	LoginCodeLength int = 8

	// LoginCodeGamma specifies the characters to be used for building the login code
	LoginCodeGamma string = "BCDFGHJKLMNPQRSTVXYZ"
)

Variables

This section is empty.

Functions

func AuthCookieGet

func AuthCookieGet(r *http.Request) string

func AuthCookieRemove

func AuthCookieRemove(w http.ResponseWriter, r *http.Request)

func AuthCookieSet

func AuthCookieSet(w http.ResponseWriter, r *http.Request, token string)

func AuthTokenRetrieve

func AuthTokenRetrieve(r *http.Request, useCookies bool) string

authTokenRetrieve retrieves the auth token from the request Several attempts are made:

  1. From cookie
  2. Authorization header (aka Bearer token)
  3. Request param "api_key"
  4. Request param "token"

func BearerTokenFromHeader

func BearerTokenFromHeader(authHeader string) string

BearerTokenFromHeader extracts the bearer token from the passed authorization header value. If a bearer token is not found, an empty string is returned.

Parameters:

  • authHeader: a string representing the authorization header

Returns:

  • a string representing the extracted bearer token

Example:

	authHeader := r.Header.Get("Authorization")
	authTokenFromBearerToken := BearerTokenFromHeader(authHeader)

 or simplified

	authTokenFromBearerToken := BearerTokenFromHeader(r.Header.Get("Authorization"))

Types

type Auth

type Auth struct {
	// contains filtered or unexported fields
}

Auth defines the structure for the authentication

func NewPasswordlessAuth

func NewPasswordlessAuth(config ConfigPasswordless) (*Auth, error)

func NewUsernameAndPasswordAuth

func NewUsernameAndPasswordAuth(config ConfigUsernameAndPassword) (*Auth, error)

func (Auth) ApiAuthOrErrorMiddleware

func (a Auth) ApiAuthOrErrorMiddleware(next http.Handler) http.Handler

ApiAuthOrErrorMiddleware checks that an authentication token exists, and then finds the userID based on it. On success appends the user ID to the context. On failure it will return an unauthenticated JSON response.

func (Auth) AuthHandler

func (a Auth) AuthHandler(w http.ResponseWriter, r *http.Request)

Router routes the requests

func (Auth) AuthMiddleware

func (a Auth) AuthMiddleware(next http.Handler) http.Handler

DEPRECATED use the Web or the API middleware instead

func (Auth) GetCurrentUserID

func (a Auth) GetCurrentUserID(r *http.Request) string

func (Auth) Handler

func (a Auth) Handler() http.Handler

func (Auth) LinkApiLogin

func (a Auth) LinkApiLogin() string

func (Auth) LinkApiLoginCodeVerify

func (a Auth) LinkApiLoginCodeVerify() string

func (Auth) LinkApiLogout

func (a Auth) LinkApiLogout() string

func (Auth) LinkApiPasswordReset

func (a Auth) LinkApiPasswordReset() string

func (Auth) LinkApiPasswordRestore

func (a Auth) LinkApiPasswordRestore() string

func (Auth) LinkApiRegister

func (a Auth) LinkApiRegister() string

func (Auth) LinkApiRegisterCodeVerify

func (a Auth) LinkApiRegisterCodeVerify() string

func (Auth) LinkLogin

func (a Auth) LinkLogin() string

func (Auth) LinkLoginCodeVerify

func (a Auth) LinkLoginCodeVerify() string

func (Auth) LinkLogout

func (a Auth) LinkLogout() string

func (Auth) LinkPasswordReset

func (a Auth) LinkPasswordReset(token string) string

LinkPasswordReset - returns the password reset URL

func (Auth) LinkPasswordRestore

func (a Auth) LinkPasswordRestore() string

func (Auth) LinkRedirectOnSuccess

func (a Auth) LinkRedirectOnSuccess() string

LinkRedirectOnSuccess - returns the URL to where the user will be redirected after successful registration

func (Auth) LinkRegister

func (a Auth) LinkRegister() string

LinkRegister - returns the registration URL

func (Auth) LinkRegisterCodeVerify

func (a Auth) LinkRegisterCodeVerify() string

LinkRegisterCodeVerify - returns the registration code verification URL

func (Auth) LoginWithUsernameAndPassword

func (a Auth) LoginWithUsernameAndPassword(email string, password string, options UserAuthOptions) (response LoginUsernameAndPasswordResponse)

func (Auth) RegisterWithUsernameAndPassword

func (a Auth) RegisterWithUsernameAndPassword(email string, password string, firstName string, lastName string, options UserAuthOptions) (response RegisterUsernameAndPasswordResponse)

func (Auth) RegistrationDisable

func (a Auth) RegistrationDisable()

RegistrationDisable - disables registration

func (Auth) RegistrationEnable

func (a Auth) RegistrationEnable()

RegistrationEnable - enables registration

func (Auth) Router

func (a Auth) Router() *http.ServeMux

func (Auth) WebAppendUserIdIfExistsMiddleware

func (a Auth) WebAppendUserIdIfExistsMiddleware(next http.Handler) http.Handler

WebAppendUserIdIfExistsMiddleware appends the user ID to the context if an authentication token exists in the requests. This middleware does not have a side effect like for instance redirecting to the login endpoint. This is why it is important to be added to places which can be used by both guests and users (i.e. website pages), where authenticated users may have some extra privileges

If you need to redirect the user if authentication token not found, or the user does not exist, take a look at the WebAuthOrRedirectMiddleware middleware, which does exactly that

func (Auth) WebAuthOrRedirectMiddleware

func (a Auth) WebAuthOrRedirectMiddleware(next http.Handler) http.Handler

WebAuthOrRedirectMiddleware checks that an authentication token exists, and then finds the userID based on it. On success appends the user ID to the context. On failure it will redirect the user to the login endpoint to reauthenticate.

If you need to only find if the authentication token is successful without redirection please use the WebAppendUserIdIfExistsMiddleware which does exactly that without side effects

type AuthenticatedUserID

type AuthenticatedUserID struct{}

type ConfigPasswordless

type ConfigPasswordless struct {

	// ===== START: shared by all implementations
	EnableRegistration      bool
	Endpoint                string
	FuncLayout              func(content string) string
	FuncTemporaryKeyGet     func(key string) (value string, err error)
	FuncTemporaryKeySet     func(key string, value string, expiresSeconds int) (err error)
	FuncUserFindByAuthToken func(sessionID string, options UserAuthOptions) (userID string, err error)
	FuncUserLogout          func(userID string, options UserAuthOptions) (err error)
	FuncUserStoreAuthToken  func(sessionID string, userID string, options UserAuthOptions) error
	UrlRedirectOnSuccess    string
	UseCookies              bool
	UseLocalStorage         bool

	// ===== START: passwordless options
	FuncUserFindByEmail           func(email string, options UserAuthOptions) (userID string, err error)
	FuncEmailTemplateLoginCode    func(email string, logingLink string, options UserAuthOptions) string   // optional
	FuncEmailTemplateRegisterCode func(email string, registerLink string, options UserAuthOptions) string // optional
	FuncEmailSend                 func(email string, emailSubject string, emailBody string) (err error)
	FuncUserRegister              func(email string, firstName string, lastName string, options UserAuthOptions) (err error)
}

type ConfigUsernameAndPassword

type ConfigUsernameAndPassword struct {
	// ===== START: shared by all implementations
	EnableRegistration      bool
	Endpoint                string
	FuncLayout              func(content string) string
	FuncTemporaryKeyGet     func(key string) (value string, err error)
	FuncTemporaryKeySet     func(key string, value string, expiresSeconds int) (err error)
	FuncUserStoreAuthToken  func(sessionID string, userID string, options UserAuthOptions) error
	FuncUserFindByAuthToken func(sessionID string, options UserAuthOptions) (userID string, err error)
	UrlRedirectOnSuccess    string
	UseCookies              bool
	UseLocalStorage         bool

	// ===== START: username(email) and password options
	EnableVerification               bool
	FuncEmailTemplatePasswordRestore func(userID string, passwordRestoreLink string, options UserAuthOptions) string // optional
	FuncEmailTemplateRegisterCode    func(userID string, passwordRestoreLink string, options UserAuthOptions) string // optional
	FuncEmailSend                    func(userID string, emailSubject string, emailBody string) (err error)
	FuncUserFindByUsername           func(username string, firstName string, lastName string, options UserAuthOptions) (userID string, err error)
	FuncUserLogin                    func(username string, password string, options UserAuthOptions) (userID string, err error)
	FuncUserLogout                   func(username string, options UserAuthOptions) (err error)
	FuncUserPasswordChange           func(username string, newPassword string, options UserAuthOptions) (err error)
	FuncUserRegister                 func(username string, password string, first_name string, last_name string, options UserAuthOptions) (err error)
	LabelUsername                    string
}

Config defines the available configuration options for authentication

type LoginUsernameAndPasswordResponse

type LoginUsernameAndPasswordResponse struct {
	ErrorMessage   string
	SuccessMessage string
	Token          string
}

type RegisterUsernameAndPasswordResponse

type RegisterUsernameAndPasswordResponse struct {
	ErrorMessage   string
	SuccessMessage string
	Token          string
}

type UserAuthOptions

type UserAuthOptions struct {
	UserIp    string
	UserAgent string
}

Directories

Path Synopsis
scribble
Package scribble is a tiny JSON database
Package scribble is a tiny JSON database

Jump to

Keyboard shortcuts

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