README ¶
Authboss
Authboss is a modular authentication system for the web.
It has several modules that represent authentication and authorization features that are common to websites in general so that you can enable as many as you need, and leave the others out. It makes it easy to plug in authentication to an application and get a lot of functionality for (hopefully) a smaller amount of integration effort.
New to v2?
v1 -> v2 was a very big change. If you're looking to upgrade there is a general guide in tov2.md in this project.
Why use Authboss?
Every time you'd like to start a new web project, you really want to get to the heart of what you're trying to accomplish very quickly and it would be a sure bet to say one of the systems you're excited about implementing and innovating on is not authentication. In fact it's very much the opposite: it's one of those things that you have to do and one of those things you loathe to do. Authboss is supposed to remove a lot of the tedium that comes with this, as well as a lot of the chances to make mistakes. This allows you to care about what you're intending to do, rather than care about ancillary support systems required to make what you're intending to do happen.
Here are a few bullet point reasons you might like to try it out:
- Saves you time (Authboss integration time should be less than re-implementation time)
- Saves you mistakes (at least using Authboss, people can bug fix as a collective and all benefit)
- Should integrate with or without any web framework
Readme Table of Contents
- Authboss
- New to v2?
- Why use Authboss?
- Readme Table of Contents
- Getting Started
- Available Modules
- Middlewares
- Use Cases
Getting Started
To get started with Authboss in the simplest way, is to simply create a Config, populate it with the things that are required, and start implementing use cases. The use cases describe what's required to be able to use a particular piece of functionality, or the best practice when implementing a piece of functionality. Please note the app requirements for your application as well integration requirements that follow.
Of course the standard practice of fetching the library is just the beginning:
# Get the latest, keep in mind you should be vendoring with dep or using vgo at this point
# To ensure versions don't get messed up underneath you
go get -u github.com/volatiletech/authboss
Here's a bit of starter code that was stolen from the sample.
ab := authboss.New()
ab.Config.Storage.Server = myDatabaseImplementation
ab.Config.Storage.SessionState = mySessionImplementation
ab.Config.Storage.CookieState = myCookieImplementation
ab.Config.Paths.Mount = "/authboss"
ab.Config.Paths.RootURL = "https://www.example.com/"
// This is using the renderer from: github.com/volatiletech/authboss
ab.Config.Core.ViewRenderer = abrenderer.New("/auth")
// Probably want a MailRenderer here too.
// Set up defaults for basically everything besides the ViewRenderer/MailRenderer in the HTTP stack
defaults.SetCore(&ab.Config, false)
if err := ab.Init(); err != nil {
panic(err)
}
// Mount the router to a path (this should be the same as the Mount path above)
// mux in this example is a chi router, but it could be anything that can route to
// the Core.Router.
mux.Mount("/authboss", http.StripPrefix("/authboss", ab.Config.Core.Router))
For a more in-depth look you definitely should look at the authboss sample to see what a full implementation looks like. This will probably help you more than any of this documentation.
https://github.com/volatiletech/authboss-sample
App Requirements
Authboss does a lot of things, but it doesn't do some of the important things that are required by a typical authentication system, because it can't guarantee that you're doing many of those things in a different way already, so it punts the responsibility.
CSRF Protection
What this means is you should apply a middleware that can protect the application from crsf attacks or you may be vulnerable. Authboss previously handled this but it took on a dependency that was unnecessary and it complicated the code. Because Authboss does not render views nor consumes data directly from the user, it no longer does this.
Request Throttling
Currently Authboss is vulnerable to brute force attacks because there are no protections on it's endpoints. This again is left up to the creator of the website to protect the whole website at once (as well as Authboss) from these sorts of attacks.
Integration Requirements
In terms of integrating Authboss into your app, the following things must be considered.
Middleware
There are middlewares that are required to be installed in your middleware stack if it's all to function properly, please see Middlewares for more information.
Configuration
There are some required configuration variables that have no sane defaults and are particular to your app:
- Config.Paths.Mount
- Config.Paths.RootURL
Storage and Core implementations
Everything under Config.Storage and Config.Core are required and you must provide them,
however you can optionally use default implementations from the
defaults package.
This also provides an easy way to share implementations of certain stack pieces (like HTML Form Parsing).
As you saw in the example above these can be easily initialized with the SetCore
method in that
package.
The following is a list of storage interfaces, they must be provided by the implementer. Server is a very involved implementation, please see the additional documentation below for more details.
- Config.Storage.Server
- Config.Storage.SessionState
- Config.Storage.CookieState (only for "remember me" functionality)
The following is a list of the core pieces, these typically are abstracting the HTTP stack. Out of all of these you'll probably be mostly okay with the default implementations in the defaults package but there are two big exceptions to this rule and that's the ViewRenderer and the MailRenderer. For more information please see the use case Rendering Views
- Config.Core.Router
- Config.Core.ErrorHandler
- Config.Core.Responder
- Config.Core.Redirector
- Config.Core.BodyReader
- Config.Core.ViewRenderer
- Config.Core.MailRenderer
- Config.Core.Mailer
- Config.Core.Logger
ServerStorer implementation
The ServerStorer is
meant to be upgraded to add capabilities depending on what modules you'd like to use.
It starts out by only knowing how to save and load users, but the remember
module as an example
needs to be able to find users by remember me tokens, so it upgrades to a
RememberingServerStorer
which adds these abilities.
Your ServerStorer
implementation does not need to implement all these additional interfaces
unless you're using a module that requires it. See the Use Cases documentation to know what the requirements are.
User implementation
Users in Authboss are represented by the User interface. The user interface is a flexible notion, because it can be upgraded to suit the needs of the various modules.
Initially the User must only be able to Get/Set a PID
or primary identifier. This allows the authboss
modules to know how to refer to him in the database. The ServerStorer
also makes use of this
to save/load users.
As mentioned, it can be upgraded, for example suppose now we want to use the confirm
module,
in that case the e-mail address now becomes a requirement. So the confirm
module will attempt
to upgrade the user (and panic if it fails) to a
ConfirmableUser
which supports retrieving and setting of confirm tokens, e-mail addresses, and a confirmed state.
Your User
implementation does not need to implement all these additional user interfaces unless you're
using a module that requires it. See the Use Cases documentation to know what the
requirements are.
Values implementation
The BodyReader interface in the Config returns Validator implementations which can be validated. But much like the storer and user it can be upgraded to add different capabilities.
A typical BodyReader
(like the one in the defaults package) implementation checks the page being
requested and switches on that to parse the body in whatever way
(msgpack, json, url-encoded, doesn't matter), and produce a struct that has the ability to
Validate()
it's data as well as functions to retrieve the data necessary for the particular
valuer required by the module.
An example of an upgraded Valuer
is the
UserValuer
which stores and validates the PID and Password that a user has provided for the modules to use.
Your body reader implementation does not need to implement all valuer types unless you're using a module that requires it. See the Use Cases documentation to know what the requirements are.
Config
The config struct is an important part of Authboss. It's the key to making Authboss do what you want with the implementations you want. Please look at it's code definition as you read the documentation below, it will make much more sense.
Paths
Paths are the paths that should be redirected to or used in whatever circumstance they describe.
Two special paths that are required are Mount
and RootURL
without which certain authboss
modules will not function correctly. Most paths get defaulted to /
such as after login success
or when a user is locked out of their account.
Modules
Modules are module specific configuration options. They mostly control the behavior of modules.
For example RegisterPreserveFields
decides a whitelist of fields to allow back into the data
to be re-rendered so the user doesn't have to type them in again.
Mail sending related options.
Storage
These are the implementations of how storage on the server and the client are done in your app. There are no default implementations for these at this time. See the Godoc for more information about what these are.
Core
These are the implementations of the HTTP stack for your app. How do responses render? How are they redirected? How are errors handled?
For most of these there are default implementations from the defaults package available, but not for all. See the package documentation for more information about what's available.
Available Modules
Each module can be turned on simply by importing it and the side-effects take care of the rest. Not all the capabilities of authboss are represented by a module, see Use Cases to view the supported use cases as well as how to use them in your app.
Note: The two factor packages do not enable via side-effect import, see their documentation for more information.
Name | Import Path | Description |
---|---|---|
Auth | github.com/volatiletech/authboss/auth | Database password authentication for users. |
Confirm | github.com/volatiletech/authboss/confirm | Prevents login before e-mail verification. |
Expire | github.com/volatiletech/authboss/expire | Expires a user's login |
Lock | github.com/volatiletech/authboss/lock | Locks user accounts after authentication failures. |
Logout | github.com/volatiletech/authboss/logout | Destroys user sessions for auth/oauth2. |
OAuth2 | github.com/volatiletech/authboss/oauth2 | Provides oauth2 authentication for users. |
Recover | github.com/volatiletech/authboss/recover | Allows for password resets via e-mail. |
Register | github.com/volatiletech/authboss/register | User-initiated account creation. |
Remember | github.com/volatiletech/authboss/remember | Persisting login sessions past session cookie expiry. |
OTP | github.com/volatiletech/authboss/otp | One time passwords for use instead of passwords. |
Twofactor | github.com/volatiletech/authboss/otp/twofactor | Regenerate recovery codes for 2fa. |
Totp2fa | github.com/volatiletech/authboss/otp/twofactor/totp2fa | Use Google authenticator-like things for a second auth factor. |
Sms2fa | github.com/volatiletech/authboss/otp/twofactor/sms2fa | Use a phone for a second auth factor. |
Middlewares
The only middleware that's truly required is the LoadClientStateMiddleware
, and that's because it
enables session and cookie handling for Authboss. Without that, it's not a very useful piece of
software.
The remaining middlewares are either the implementation of an entire module (like expire), or a key part of a module. For example you probably wouldn't want to use the lock module without the middleware that would stop a locked user from using an authenticated resource, because then locking wouldn't be useful unless of course you had your own way of dealing with locking, which is why it's only recommended, and not required. Typically you will use the middlewares if you use the module.
Name | Requirement | Description |
---|---|---|
Middleware | Recommended | Prevents unauthenticated users from accessing routes. |
LoadClientStateMiddleware | Required | Enables cookie and session handling |
ModuleListMiddleware | Optional | Inserts a loaded module list into the view data |
confirm.Middleware | Recommended with confirm | Ensures users are confirmed or rejects request |
expire.Middleware | Required with expire | Expires user sessions after an inactive period |
lock.Middleware | Recommended with lock | Rejects requests from locked users |
remember.Middleware | Recommended with remember | Logs a user in from a remember cookie |
Use Cases
Get Current User
CurrentUser can be retrieved by calling Authboss.CurrentUser but a pre-requisite is that Authboss.LoadClientState has been called first to load the client state into the request context. This is typically achieved by using the Authboss.LoadClientStateMiddleware, but can be done manually as well.
Reset Password
Updating a user's password is non-trivial for several reasons:
- The bcrypt algorithm must have the correct cost, and also be being used.
- The user's remember me tokens should all be deleted so that previously authenticated sessions are invalid
- Optionally the user should be logged out (not taken care of by UpdatePassword)
In order to do this, we can use the Authboss.UpdatePassword method. This ensures the above facets are taken care of which the exception of the logging out part.
If it's also desirable to have the user logged out, please use the following methods to erase all known sessions and cookies from the user.
Note: DelKnownSession has been deprecated for security reasons
User Auth via Password
Info and Requirements | |
---|---|
Module | auth |
Pages | login |
Routes | /login |
Emails | None |
Middlewares | LoadClientStateMiddleware |
ClientStorage | Session and Cookie |
ServerStorer | ServerStorer |
User | AuthableUser |
Values | UserValuer |
Mailer | None |
To enable this side-effect import the auth module, and ensure that the requirements above are met. It's very likely that you'd also want to enable the logout module in addition to this.
Direct a user to GET /login
to have them enter their credentials and log in.
User Auth via OAuth2
Info and Requirements | |
---|---|
Module | oauth2 |
Pages | None |
Routes | /oauth2/{provider}, /oauth2/callback/{provider} |
Emails | None |
Middlewares | LoadClientStateMiddleware |
ClientStorage | Session |
ServerStorer | OAuth2ServerStorer |
User | OAuth2User |
Values | None |
Mailer | None |
This is a tougher implementation than most modules because there's a lot going on. In addition to the
requirements stated above, you must also configure the OAuth2Providers
in the config struct.
The providers require an oauth2 configuration that's typical for the Go oauth2 package, but in addition
to that they need a FindUserDetails
method which has to take the token that's retrieved from the oauth2
provider, and call an endpoint that retrieves details about the user (at LEAST user's uid).
These parameters are returned in map[string]string
form and passed into the OAuth2ServerStorer
.
Please see the following documentation for more details:
User Registration
Info and Requirements | |
---|---|
Module | register |
Pages | register |
Routes | /register |
Emails | None |
Middlewares | LoadClientStateMiddleware |
ClientStorage | Session |
ServerStorer | CreatingServerStorer |
User | AuthableUser, optionally ArbitraryUser |
Values | UserValuer, optionally also ArbitraryValuer |
Mailer | None |
Users can self-register for a service using this module. You may optionally want them to confirm themselves, which can be done using the confirm module.
The complicated part in implementing registrations are around the RegisterPreserveFields
. This is to
help in the case where a user fills out many fields, and then say enters a password
which doesn't meet minimum requirements and it fails during validation. These preserve fields should
stop the user from having to type in all that data again (it's a whitelist). This must be used
in conjuction with ArbitraryValuer
and although it's not a hard requirement ArbitraryUser
should be used otherwise the arbitrary values cannot be stored in the database.
When the register module sees arbitrary data from an ArbitraryValuer
, it sets the data key
authboss.DataPreserve
with a map[string]string
in the data for when registration fails.
This means the (whitelisted) values entered by the user previously will be accessible in the
templates by using .preserve.field_name
. Preserve may be empty or nil so use
{{with ...}}
to make sure you don't have template errors.
There is additional Godoc documentation on the RegisterPreserveFields
config option as well as
the ArbitraryUser
and ArbitraryValuer
interfaces themselves.
Confirming Registrations
Info and Requirements | |
---|---|
Module | confirm |
Pages | confirm |
Routes | /confirm |
Emails | confirm_html, confirm_txt |
Middlewares | LoadClientStateMiddleware, confirm.Middleware |
ClientStorage | Session |
ServerStorer | ConfirmingServerStorer |
User | ConfirmableUser |
Values | ConfirmValuer |
Mailer | Required |
Confirming registrations via e-mail can be done with this module (whether or not done via the register module).
A hook on register kicks off the start of a confirmation which sends an e-mail with a token for the user.
When the user re-visits the page, the BodyReader
must read the token and return a type that returns
the token.
Confirmations carry two values in the database to prevent a timing attack. The selector and the verifier, always make sure in the ConfirmingServerStorer you're searching by the selector and not the verifier.
Password Recovery
Info and Requirements | |
---|---|
Module | recover |
Pages | recover_start, recover_middle (not used for renders, only values), recover_end |
Routes | /recover, /recover/end |
Emails | recover_html, recover_txt |
Middlewares | LoadClientStateMiddleware |
ClientStorage | Session |
ServerStorer | RecoveringServerStorer |
User | RecoverableUser |
Values | RecoverStartValuer, RecoverMiddleValuer, RecoverEndValuer |
Mailer | Required |
The flow for password recovery is that the user is initially shown a page that wants their PID
to
be entered. The RecoverStartValuer
retrieves that on POST
to /recover
.
An e-mail is sent out, and the user clicks the link inside it and is taken back to /recover/end
as a GET
, at this point the RecoverMiddleValuer
grabs the token and will insert it into the data
to be rendered.
They enter their password into the form, and POST
to /recover/end
which sends the token and
the new password which is retrieved by RecoverEndValuer
which sets their password and saves them.
Password recovery has two values in the database to prevent a timing attack. The selector and the verifier, always make sure in the RecoveringServerStorer you're searching by the selector and not the verifier.
Remember Me
Info and Requirements | |
---|---|
Module | remember |
Pages | None |
Routes | None |
Emails | None |
Middlewares | LoadClientStateMiddleware, |
Middlewares | LoadClientStateMiddleware, remember.Middleware |
ClientStorage | Session, Cookies |
ServerStorer | RememberingServerStorer |
User | User |
Values | RememberValuer (not a Validator) |
Mailer | None |
Remember uses cookie storage to log in users without a session via the remember.Middleware
.
Because of this this middleware should be used high up in the stack, but it also needs to be after
the LoadClientStateMiddleware
so that client state is available via the authboss mechanisms.
There is an intricacy to the RememberingServerStorer
, it doesn't use the User
struct at all,
instead it simply instructs the storer to save tokens to a pid and recall them just the same. Typically
in most databases this will require a separate table, though you could implement using pg arrays
or something as well.
A user who is logged in via Remember tokens is also considered "half-authed" which is a session
key (authboss.SessionHalfAuthKey
) that you can query to check to see if a user should have
full rights to more sensitive data, if they are half-authed and they want to change their user
details for example you may want to force them to go to the login screen and put in their
password to get a full auth first. The authboss.Middleware
has a boolean flag to forceFullAuth
which prevents half-authed users from using that route.
Locking Users
Info and Requirements | |
---|---|
Module | lock |
Pages | None |
Routes | None |
Emails | None |
Middlewares | LoadClientStateMiddleware, lock.Middleware |
ClientStorage | Session |
ServerStorer | ServerStorer |
User | LockableUser |
Values | None |
Mailer | None |
Lock ensures that a user's account becomes locked if authentication (both auth, oauth2, otp) are failed enough times.
The middleware protects resources from locked users, without it, there is no point to this module. You should put in front of any resource that requires a login to function.
Expiring User Sessions
Info and Requirements | |
---|---|
Module | expire |
Pages | None |
Routes | None |
Emails | None |
Middlewares | LoadClientStateMiddleware, expire.Middleware |
ClientStorage | Session |
ServerStorer | None |
User | User |
Values | None |
Mailer | None |
Note: Unlike most modules in Authboss you must call expire.Setup()
to enable this module. See the sample to see how to do this. This may be changed in the future.
Expire simply uses sessions to track when the last action of a user is, if that action is longer than configured then the session is deleted and the user removed from the request context.
This middleware should be inserted at a high level (closer to the request) in the middleware chain to ensure that "activity" is logged properly, as well as any middlewares down the chain do not attempt to do anything with the user before it's removed from the request context.
One Time Passwords
Info and Requirements | |
---|---|
Module | otp |
Pages | otp, otpadd, otpclear |
Routes | /otp/login, /otp/add, /otp/clear |
Emails | None |
Middlewares | LoadClientStateMiddleware |
ClientStorage | Session and Cookie |
ServerStorer | ServerStorer |
User | otp.User |
Values | UserValuer |
Mailer | None |
One time passwords can be useful if users require a backup password in case they lose theirs, or they're logging in on an untrusted computer. This module allows users to add one time passwords, clear them, or log in with them.
Logging in with a one time password instead of a password is identical to having logged in normally with their typical password with the exception that the one time passwords are consumed immediately upon use and cannot be used again.
otp
should not be confused with two factor authentication. Although 2fa also uses one-time passwords
the otp
module has nothing to do with it and is strictly a mechanism for logging in with an alternative
to a user's regular password.
Two Factor Authentication
2FA in Authboss is implemented in a few separate modules: twofactor, totp2fa and sms2fa.
You should use two factor authentication in your application if you want additional security beyond that of just simple passwords. Each 2fa module supports a different mechanism for verifying a second factor of authentication from a user.
Two-Factor Recovery
Info and Requirements | |
---|---|
Module | twofactor |
Pages | recovery2fa |
Routes | /2fa/recovery/regen |
Emails | None |
Middlewares | LoadClientStateMiddleware |
ClientStorage | Session |
ServerStorer | ServerStorer |
User | twofactor.User |
Values | None |
Mailer | None |
Note: Unlike most modules in Authboss you must construct a twofactor.Recovery
and call .Setup()
on it to enable this module. See the sample to see how to do this. This may be changed in the future.
Package twofactor is all about the common functionality of providing backup codes for two factor mechanisms. Instead of each module implementing backup codes on it's own, common functionality has been put here including a route to regenerate backup codes.
Backup codes are useful in case people lose access to their second factor for authentication. This happens when users lose their phones for example. When this occurs, they can use one of their backup-codes.
Backup codes are one-time use, they are bcrypted for security, and they only allow bypassing the 2fa
authentication part, they cannot be used in lieu of a user's password, for that sort of recovery see
the otp
module.
Two-Factor Setup E-mail Authorization
Info and Requirements | |
---|---|
Module | twofactor |
Pages | twofactor_verify |
Routes | /2fa/recovery/regen |
Emails | twofactor_verify_email_html, twofactor_verify_email_txt |
Middlewares | LoadClientStateMiddleware |
ClientStorage | Session |
ServerStorer | ServerStorer |
User | twofactor.User |
Values | twofactor.EmailVerifyTokenValuer |
Mailer | Required |
To enable this feature simply turn on
authboss.Config.Modules.TwoFactorEmailAuthRequired
and new routes and
middlewares will be installed when you set up one of the 2fa modules.
When enabled, the routes for setting up 2fa on an account are protected by a
middleware that will redirect to /2fa/{totp,sms}/email/verify
where
Page twofactor_verify
is displayed. The user is prompted to authorize the
addition of 2fa to their account. The data for this page contains email
and
a url
for the POST. The url is required because this page is shared between
all 2fa types.
Once they POST to the url, a token is stored in their session and an e-mail is
sent with that token. When they click the link that goes to
/2fa/{totp,sms}/email/verify/end
with a token in the query string the session
token is verified and exchanged for a value that says they're verified and
lastly it redirects them to the setup URL for the type of 2fa they were
attempting to setup.
Time-Based One Time Passwords 2FA (totp)
Info and Requirements | |
---|---|
Module | totp2fa |
Pages | totp2fa_{setup,confirm,remove,validate}, totp2fa_{confirm,remove}_success |
Routes | /2fa/totp/{setup,confirm,qr,remove,validate} |
Emails | None |
Middlewares | LoadClientStateMiddleware |
ClientStorage | Session (SECURE!) |
ServerStorer | ServerStorer |
User | totp2fa.User |
Values | TOTPCodeValuer |
Mailer | None |
Note: Unlike most modules in Authboss you must construct a totp2fa.TOTP
and call .Setup()
on it to enable this module. See the sample to see how to do this This may be changed in the future.
Note: To allow users to regenerate their backup codes, you must also use the twofactor
module.
Note: Routes are protected by authboss.Middleware
so only logged in users can access them.
You can configure whether unauthenticated users should be redirected to log in or are 404'd using
the authboss.Config.Modules.RoutesRedirectOnUnathed
configuration flag.
Adding 2fa to a user
When a logged in user would like to add 2fa to their account direct them GET /2fa/totp/setup
, the GET
on this page does virtually nothing so you don't have to use it, just POST
immediately to have
a smoother flow for the user. This puts the 2fa secret in their session temporarily meaning you must
have proper secure sessions for this to be secure.
They will be redirected to GET /2fa/totp/confirm
where the data will show totp2fa.DataTOTPSecret
,
this is the key that user's should enter into their Google Authenticator or similar app. Once they've
added it they need to send a POST /2fa/totp/confirm
with a correct code which removes the 2fa secret
from their session and permanently adds it to their totp2fa.User
and 2fa is now enabled for them.
The data from the POST
will contain a key twofactor.DataRecoveryCodes
that contains an array
of recovery codes for the user.
If you wish to show the user a QR code, GET /2fa/totp/qr
at any time during or after totp2fa setup
will return a 200x200 png QR code that they can scan.
Removing 2fa from a user
A user begins by going to GET /2fa/totp/remove
and enters a code which posts to POST /2fa/totp/remove
and if it's correct they're shown a success page and 2fa is removed from them, if not they get
validation errors.
Logging in with 2fa
When a user goes to log in, the totp
module checks the user after they log in for the presence of
a totp2fa secret, if there is one it does not give them a logged in session value immediately and
redirects them to GET /2fa/totp/validate
where they must enter a correct code to POST /2fa/totp/validate
if the code is correct they're logged in normally as well as they get the session value
authboss.Session2FA
set to "totp"
to prove that they've authenticated with two factors.
Using Recovery Codes
Both when logging in and removing totp2fa from an account, a recovery code may be used instead. They can
POST
to the same url, they simply send a different form field. The recovery code is consumed on use
and may not be used again.
Text Message 2FA (sms)
Package sms2fa uses sms shared secrets as a means to authenticate a user with a second factor: their phone number.
Info and Requirements | |
---|---|
Module | sms2fa |
Pages | sms2fa_{setup,confirm,remove,validate}, sms2fa_{confirm,remove}_success |
Routes | /2fa/{setup,confirm,remove,validate} |
Emails | None |
Middlewares | LoadClientStateMiddleware |
ClientStorage | Session (SECURE!) |
ServerStorer | ServerStorer |
User | sms2fa.User, sms2fa.SMSNumberProvider |
Values | SMSValuer, SMSPhoneNumberValuer |
Mailer | None |
Note: Unlike most modules in Authboss you must construct a sms2fa.SMS
and call .Setup()
on it to enable this module. See the sample to see how to do this. This may be changed in the future.
Note: To allow users to regenerate their backup codes, you must also use the twofactor
module.
Note: Routes are protected by authboss.Middleware
so only logged in users can access them.
You can configure whether unauthenticated users should be redirected to log in or are 404'd using
the authboss.Config.Modules.RoutesRedirectOnUnathed
configuration flag.
Note: sms2fa always stores the code it's expecting in the user's session therefore you must have secure sessions or the code itself is not secure!
Note: sms2fa pages all send codes via sms on POST
when no data code is given. This is also how
users can resend the code in case they did not get it (for example a second
POST /2fa/sms/{confirm,remove}
with no form-fields filled in will end up resending the code).
Note: Sending sms codes is rate-limited to 1 sms/10 sec for that user, this is controlled by placing a timestamp in their session to prevent abuse.
Adding 2fa to a user
When a logged in user would like to add 2fa to their account direct them GET /2fa/sms/setup
where
they must enter a phone number. If the logged in user also implements sms2fa.SMSNumberProvider
then
this interface will be used to retrieve a phone number (if it exists) from the user and put it in
sms2fa.DataSMSPhoneNumber
so that the user interface can populate it for the user, making it convenient
to re-use an already saved phone number inside the user.
Once they POST /2fa/sms/setup
with a phone number, the sms2fa.Sender
interface will be
invoked to send the SMS code to the user and they will be redirected to GET /2fa/sms/confirm
where
they enter the code they received which does a POST /2fa/sms/confirm
to store the phone number
they were confirming permanently on their user using sms2fa.User
which enables sms2fa for them.
The data from the POST
will contain a key twofactor.DataRecoveryCodes
that contains an array
of recovery codes for the user.
Removing 2fa from a user
A user begins by going to GET /2fa/sms/remove
. This page does nothing on it's own. In order to
begin the process POST /2fa/sms/remove
with no data (or a recovery code to skip needing the sms code)
to send the sms code to the user. Then they can POST /2fa/sms/remove
again with the correct code
to have it permanently removed.
Logging in with 2fa
When a user goes to log in, the sms
module checks the user after they log in for the presence of
a sms2fa phone number, if there is one it does not give them a logged in session value but instead
sends an SMS code to their configured number and and redirects them to GET /2fa/sms/validate
where they must enter a correct code to POST /2fa/totp/validate
. If the code is correct they're
logged in normally as well as they get the session value authboss.Session2FA
set to "sms"
to prove
that they've authenticated with two factors.
Using Recovery Codes
Same as totp2fa above.
Rendering Views
The authboss rendering system is simple. It's defined by one interface: Renderer
The renderer knows how to load templates, and how to render them with some data and that's it. So let's examine the most common view types that you might want to use.
HTML Views
When your app is a traditional web application and is generating it's HTML serverside using templates
this becomes a small wrapper on top of your rendering setup. For example if you're using html/template
then you could just use template.New()
inside the Load()
method and store that somewhere and
call template.Execute()
in the Render()
method.
There is also a very basic renderer: Authboss Renderer which has some very ugly built in views and the ability to override them with your own if you don't want to integrate your own rendering system into that interface.
JSON Views
If you're building an API that's mostly backed by a javascript front-end, then you'll probably want to use a renderer that converts the data to JSON. There is a simple json renderer available in the defaults package package if you wish to use that.
Data
The most important part about this interface is the data that you have to render. There are several keys that are used throughout authboss that you'll want to render in your views.
They're in the file html_data.go
and are constants prefixed with Data
. See the documentation in that file for more information on
which keys exist and what they contain.
The default responder also happens to collect data from the Request context, and hence this is a great place to inject data you'd like to render (for example data for your html layout, or csrf tokens).
Documentation ¶
Overview ¶
Package authboss is a modular authentication system for the web. It tries to remove as much boilerplate and "hard things" as possible so that each time you start a new web project in Go, you can plug it in, configure and be off to the races without having to think about how to store passwords or remember tokens.
Index ¶
- Constants
- Variables
- func DelAllSession(w http.ResponseWriter, whitelist []string)
- func DelCookie(w http.ResponseWriter, key string)
- func DelKnownCookie(w http.ResponseWriter)
- func DelKnownSession(w http.ResponseWriter)
- func DelSession(w http.ResponseWriter, key string)
- func ErrorMap(e []error) map[string][]string
- func FlashError(w http.ResponseWriter, r *http.Request) string
- func FlashSuccess(w http.ResponseWriter, r *http.Request) string
- func GetCookie(r *http.Request, key string) (string, bool)
- func GetSession(r *http.Request, key string) (string, bool)
- func IsFullyAuthed(r *http.Request) bool
- func IsTwoFactored(r *http.Request) bool
- func MakeOAuth2PID(provider, uid string) string
- func MergeDataInRequest(r **http.Request, other HTMLData)
- func Middleware(ab *Authboss, redirectToLogin bool, forceFullAuth bool, force2fa bool) func(http.Handler) http.Handler
- func Middleware2(ab *Authboss, requirements MWRequirements, failureResponse MWRespondOnFailure) func(http.Handler) http.Handler
- func ModuleListMiddleware(ab *Authboss) func(http.Handler) http.Handler
- func MountedMiddleware(ab *Authboss, mountPathed, redirectToLogin, forceFullAuth, force2fa bool) func(http.Handler) http.Handler
- func MountedMiddleware2(ab *Authboss, mountPathed bool, reqs MWRequirements, ...) func(http.Handler) http.Handler
- func ParseOAuth2PID(pid string) (provider, uid string, err error)
- func ParseOAuth2PIDP(pid string) (provider, uid string)
- func PutCookie(w http.ResponseWriter, key, val string)
- func PutSession(w http.ResponseWriter, key, val string)
- func RegisterModule(name string, m Moduler)
- func RegisteredModules() []string
- func VerifyPassword(user AuthableUser, password string) error
- type ArbitraryUser
- type ArbitraryValuer
- type AuthableUser
- type Authboss
- func (a *Authboss) CurrentUser(r *http.Request) (User, error)
- func (a *Authboss) CurrentUserID(r *http.Request) (string, error)
- func (a *Authboss) CurrentUserIDP(r *http.Request) string
- func (a *Authboss) CurrentUserP(r *http.Request) User
- func (a *Authboss) Email(ctx context.Context, email Email, ro EmailResponseOptions) error
- func (a *Authboss) Init(modulesToLoad ...string) error
- func (a *Authboss) IsLoaded(mod string) bool
- func (a *Authboss) LoadClientState(w http.ResponseWriter, r *http.Request) (*http.Request, error)
- func (a *Authboss) LoadClientStateMiddleware(h http.Handler) http.Handler
- func (a *Authboss) LoadCurrentUser(r **http.Request) (User, error)
- func (a *Authboss) LoadCurrentUserID(r **http.Request) (string, error)
- func (a *Authboss) LoadCurrentUserIDP(r **http.Request) string
- func (a *Authboss) LoadCurrentUserP(r **http.Request) User
- func (a *Authboss) LoadedModules() []string
- func (a *Authboss) Logger(ctx context.Context) FmtLogger
- func (a *Authboss) NewResponse(w http.ResponseWriter) *ClientStateResponseWriter
- func (a *Authboss) RequestLogger(r *http.Request) FmtLogger
- func (a *Authboss) UpdatePassword(ctx context.Context, user AuthableUser, newPassword string) error
- type BodyReader
- type ClientState
- type ClientStateEvent
- type ClientStateEventKind
- type ClientStateReadWriter
- type ClientStateResponseWriter
- func (c ClientStateResponseWriter) Header() http.Header
- func (c ClientStateResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error)
- func (c *ClientStateResponseWriter) UnderlyingResponseWriter() http.ResponseWriter
- func (c *ClientStateResponseWriter) Write(b []byte) (int, error)
- func (c *ClientStateResponseWriter) WriteHeader(code int)
- type Config
- type ConfirmValuer
- type ConfirmableUser
- type ConfirmingServerStorer
- type ContextLogger
- type CreatingServerStorer
- type Email
- type EmailResponseOptions
- type ErrorHandler
- type ErrorList
- type Event
- type EventHandler
- type Events
- type FieldError
- type FmtLogger
- type HTMLData
- type HTTPRedirector
- type HTTPResponder
- type LockableUser
- type Logger
- type MWRequirements
- type MWRespondOnFailure
- type Mailer
- type Moduler
- type OAuth2Provider
- type OAuth2ServerStorer
- type OAuth2User
- type RecoverEndValuer
- type RecoverMiddleValuer
- type RecoverStartValuer
- type RecoverableUser
- type RecoveringServerStorer
- type RedirectOptions
- type RememberValuer
- type RememberingServerStorer
- type Renderer
- type RequestLogger
- type Router
- type ServerStorer
- type UnderlyingResponseWriter
- type User
- type UserValuer
- type Validator
Constants ¶
const ( // SessionKey is the primarily used key by authboss. SessionKey = "uid" // SessionHalfAuthKey is used for sessions that have been authenticated by // the remember module. This serves as a way to force full authentication // by denying half-authed users acccess to sensitive areas. SessionHalfAuthKey = "halfauth" // SessionLastAction is the session key to retrieve the // last action of a user. SessionLastAction = "last_action" // Session2FA is set when a user has been authenticated with a second factor Session2FA = "twofactor" // Session2FAAuthToken is a random token set in the session to be verified // by e-mail. Session2FAAuthToken = "twofactor_auth_token" // Session2FAAuthed is in the session (and set to "true") when the user // has successfully verified the token sent via e-mail in the two factor // e-mail authentication process. Session2FAAuthed = "twofactor_authed" // SessionOAuth2State is the xsrf protection key for oauth. SessionOAuth2State = "oauth2_state" // SessionOAuth2Params is the additional settings for oauth // like redirection/remember. SessionOAuth2Params = "oauth2_params" // CookieRemember is used for cookies and form input names. CookieRemember = "rm" // FlashSuccessKey is used for storing sucess flash messages on the session FlashSuccessKey = "flash_success" // FlashErrorKey is used for storing sucess flash messages on the session FlashErrorKey = "flash_error" )
const ( CTXKeyPID contextKey = "pid" CTXKeyUser contextKey = "user" CTXKeySessionState contextKey = "session" CTXKeyCookieState contextKey = "cookie" // CTXKeyData is a context key for the accumulating // map[string]interface{} (authboss.HTMLData) to pass to the // renderer CTXKeyData contextKey = "data" // CTXKeyValues is to pass the data submitted from API request or form // along in the context in case modules need it. The only module that needs // user information currently is remember so only auth/oauth2 are currently // going to use this. CTXKeyValues contextKey = "values" )
CTX Keys for authboss
const ( // DataErr is for one off errors that don't really belong to // a particular field. It should be a string. DataErr = "error" // DataValidation is for validation errors, it should always // have been created using the Map() style functions in the // validation method so that html/text template users don't // struggle in displaying them. // // It is: map[string][]string, where the key in the map is the field // and the []string on the other side is the list of problems // with that field. // // It's also important to note that if the errors that were Map()'d // did not implement FieldError or for generic errors // the empty string ("") is used as a key in the map for those // errors that couldn't be fit to a specific field. DataValidation = "errors" // DataPreserve preserves fields during large form exercises // like user registration so we don't have to re-type safe // information like addresses etc. // // This data looks like map[string]string, and is simply // keyed by the field name, and the value is the field value. DataPreserve = "preserve" // DataModules contains a map[string]bool of which modules are loaded // The bool is largely extraneous and can be ignored, if the module is // loaded it will be present in the map, if not it will be missing. DataModules = "modules" )
Keys for use in HTMLData that are meaningful
const (
// ConfirmPrefix is prepended to names of confirm fields.
ConfirmPrefix = "confirm_"
)
const ( // FormValueRedirect should be honored by HTTPRedirector implementations // as the value from the URL that overrides the typical redirect when // FollowRedirParam is set to true. FormValueRedirect = "redir" )
Variables ¶
var ( // ErrUserFound should be returned from Create (see ConfirmUser) // when the primaryID of the record is found. ErrUserFound = errors.New("user found") // ErrUserNotFound should be returned from Get when the record is not found. ErrUserNotFound = errors.New("user not found") // ErrTokenNotFound should be returned from UseToken when the // record is not found. ErrTokenNotFound = errors.New("token not found") )
Functions ¶
func DelAllSession ¶ added in v2.3.0
func DelAllSession(w http.ResponseWriter, whitelist []string)
DelAllSession deletes all variables in the session except for those on the whitelist.
The whitelist is typically provided directly from the authboss config.
This is the best way to ensure the session is cleaned up after use for a given user. An example is when a user is expired or logged out this method is called.
func DelCookie ¶
func DelCookie(w http.ResponseWriter, key string)
DelCookie deletes a key-value from the session.
func DelKnownCookie ¶
func DelKnownCookie(w http.ResponseWriter)
DelKnownCookie deletes all known cookie variables, which can be used to delete remember me pieces.
func DelKnownSession ¶
func DelKnownSession(w http.ResponseWriter)
DelKnownSession is deprecated. See DelAllSession for an alternative. DelKnownSession deletes all known session variables, effectively logging a user out.
func DelSession ¶
func DelSession(w http.ResponseWriter, key string)
DelSession deletes a key-value from the session.
func ErrorMap ¶
ErrorMap is a shortcut to change []error into ErrorList and call Map on it since this is a common operation.
func FlashError ¶
func FlashError(w http.ResponseWriter, r *http.Request) string
FlashError returns FlashError from the session and removes it.
func FlashSuccess ¶
func FlashSuccess(w http.ResponseWriter, r *http.Request) string
FlashSuccess returns FlashSuccessKey from the session and removes it.
func GetSession ¶
GetSession fetches a value from the session
func IsFullyAuthed ¶
IsFullyAuthed returns false if the user has a SessionHalfAuth in his session.
func IsTwoFactored ¶
IsTwoFactored returns false if the user doesn't have a Session2FA in his session.
func MakeOAuth2PID ¶
MakeOAuth2PID is used to create a pid for users that don't have an e-mail address or username in the normal system. This allows all the modules to continue to working as intended without having a true primary id. As well as not having to divide the regular and oauth stuff all down the middle.
func MergeDataInRequest ¶
MergeDataInRequest edits the request pointer to point to a new request with a modified context that contains the merged data.
func Middleware ¶
func Middleware(ab *Authboss, redirectToLogin bool, forceFullAuth bool, force2fa bool) func(http.Handler) http.Handler
Middleware is deprecated. See Middleware2.
func Middleware2 ¶ added in v2.2.0
func Middleware2(ab *Authboss, requirements MWRequirements, failureResponse MWRespondOnFailure) func(http.Handler) http.Handler
Middleware2 prevents someone from accessing a route that should be only allowed for users who are logged in. It allows the user through if they are logged in (SessionKey is present in the session).
requirements are set by logical or'ing together requirements. eg:
authboss.RequireFullAuth | authboss.Require2FA
failureResponse is how the middleware rejects the users that don't meet the criteria. This should be chosen from the MWRespondOnFailure constants.
func ModuleListMiddleware ¶
ModuleListMiddleware puts a map in the data that can be used to provide the renderer with information about which pieces of the views to show. The bool is extraneous, as presence in the map is the indication of wether or not the module is loaded. Data looks like: map[modulename] = true
oauth2 providers are also listed here using the syntax: oauth2.google for an example. Be careful since this doesn't actually mean that the oauth2 module has been loaded so you should do a conditional that checks for both.
func MountedMiddleware ¶
func MountedMiddleware(ab *Authboss, mountPathed, redirectToLogin, forceFullAuth, force2fa bool) func(http.Handler) http.Handler
MountedMiddleware is deprecated. See MountedMiddleware2.
func MountedMiddleware2 ¶ added in v2.2.0
func MountedMiddleware2(ab *Authboss, mountPathed bool, reqs MWRequirements, failResponse MWRespondOnFailure) func(http.Handler) http.Handler
MountedMiddleware2 hides an option from typical users in "mountPathed". Normal routes should never need this only authboss routes (since they are behind mountPath typically). This method is exported only for use by Authboss modules, normal users should use Middleware instead.
If mountPathed is true, then before redirecting to a URL it will add the mountpath to the front of it.
func ParseOAuth2PID ¶
ParseOAuth2PID returns the uid and provider for a given OAuth2 pid
func ParseOAuth2PIDP ¶
ParseOAuth2PIDP returns the uid and provider for a given OAuth2 pid
func PutCookie ¶
func PutCookie(w http.ResponseWriter, key, val string)
PutCookie puts a value into the session
func PutSession ¶
func PutSession(w http.ResponseWriter, key, val string)
PutSession puts a value into the session
func RegisterModule ¶
RegisterModule with the core providing all the necessary information to integrate into authboss.
func RegisteredModules ¶
func RegisteredModules() []string
RegisteredModules returns a list of modules that are currently registered.
func VerifyPassword ¶ added in v2.3.0
func VerifyPassword(user AuthableUser, password string) error
VerifyPassword uses authboss mechanisms to check that a password is correct. Returns nil on success otherwise there will be an error. Simply a helper to do the bcrypt comparison.
Types ¶
type ArbitraryUser ¶
type ArbitraryUser interface { User // GetArbitrary is used only to display the arbitrary data back to the user // when the form is reset. GetArbitrary() (arbitrary map[string]string) // PutArbitrary allows arbitrary fields defined by the authboss library // consumer to add fields to the user registration piece. PutArbitrary(arbitrary map[string]string) }
ArbitraryUser allows arbitrary data from the web form through. You should definitely only pull the keys you want from the map, since this is unfiltered input from a web request and is an attack vector.
type ArbitraryValuer ¶
ArbitraryValuer provides the "rest" of the fields that aren't strictly needed for anything in particular, address, secondary e-mail, etc.
There are two important notes about this interface:
1. That this is composed with Validator, as these fields should both be validated and culled of invalid pieces as they will be passed into ArbitraryUser.PutArbitrary()
2. These values will also be culled according to the RegisterPreserveFields whitelist and sent back in the data under the key DataPreserve.
type AuthableUser ¶
AuthableUser is identified by a password
func MustBeAuthable ¶
func MustBeAuthable(u User) AuthableUser
MustBeAuthable forces an upgrade to an AuthableUser or panic.
type Authboss ¶
Authboss contains a configuration and other details for running.
func (*Authboss) CurrentUser ¶
CurrentUser retrieves the current user from the session and the database. Before the user is loaded from the database the context key is checked. If the session doesn't have the user ID ErrUserNotFound will be returned.
func (*Authboss) CurrentUserID ¶
CurrentUserID retrieves the current user from the session. TODO(aarondl): This method never returns an error, one day we'll change the function signature.
func (*Authboss) CurrentUserIDP ¶
CurrentUserIDP retrieves the current user but panics if it's not available for any reason.
func (*Authboss) CurrentUserP ¶
CurrentUserP retrieves the current user but panics if it's not available for any reason.
func (*Authboss) Email ¶
Email renders the e-mail templates for the given email and sends it using the mailer.
func (*Authboss) LoadClientState ¶
LoadClientState loads the state from sessions and cookies into the ResponseWriter for later use.
func (*Authboss) LoadClientStateMiddleware ¶
LoadClientStateMiddleware wraps all requests with the ClientStateResponseWriter as well as loading the current client state into the context for use.
func (*Authboss) LoadCurrentUser ¶
LoadCurrentUser takes a pointer to a pointer to the request in order to change the current method's request pointer itself to the new request that contains the new context that has the user in it. Calls LoadCurrentUserID so the primary id is also put in the context.
func (*Authboss) LoadCurrentUserID ¶
LoadCurrentUserID takes a pointer to a pointer to the request in order to change the current method's request pointer itself to the new request that contains the new context that has the pid in it.
func (*Authboss) LoadCurrentUserIDP ¶
LoadCurrentUserIDP loads the current user id and panics if it's not found
func (*Authboss) LoadCurrentUserP ¶
LoadCurrentUserP does the same as LoadCurrentUser but panics if the current user is not found.
func (*Authboss) LoadedModules ¶
LoadedModules returns a list of modules that are currently loaded.
func (*Authboss) Logger ¶
Logger returns an appopriate logger for the context: If context is nil, then it simply returns the configured logger. If context is not nil, then it will attempt to upgrade the configured logger to a ContextLogger, and create a context-specific logger for use.
func (*Authboss) NewResponse ¶
func (a *Authboss) NewResponse(w http.ResponseWriter) *ClientStateResponseWriter
NewResponse wraps the ResponseWriter with a ClientStateResponseWriter
func (*Authboss) RequestLogger ¶
RequestLogger returns a request logger if possible, if not it calls Logger which tries to do a ContextLogger, and if that fails it will finally get a normal logger.
func (*Authboss) UpdatePassword ¶
UpdatePassword updates the password field of a user using the same semantics that register/auth do to create and verify passwords. It saves this using the storer.
In addition to that, it also invalidates any remember me tokens, if the storer supports that kind of operation.
If it's also desirable to log the user out, use: authboss.DelKnown(Session|Cookie)
type BodyReader ¶
BodyReader reads data from the request and returns it in an abstract form. Typically used to decode JSON responses or Url Encoded request bodies.
The first parameter is the page that this request was made on so we can tell what kind of JSON object or form was present as well as create the proper validation mechanisms.
A typical example of this is taking the request and turning it into a JSON struct that knows how to validate itself and return certain fields.
type ClientState ¶
ClientState represents the client's current state and can answer queries about it.
type ClientStateEvent ¶
type ClientStateEvent struct { Kind ClientStateEventKind Key string Value string }
ClientStateEvent are the different events that can be recorded during a request.
type ClientStateEventKind ¶
type ClientStateEventKind int
ClientStateEventKind is an enum.
const ( // ClientStateEventPut means you should put the key-value pair into the // client state. ClientStateEventPut ClientStateEventKind = iota // ClientStateEventPut means you should delete the key-value pair from the // client state. ClientStateEventDel // ClientStateEventDelAll means you should delete EVERY key-value pair from // the client state - though a whitelist of keys that should not be deleted // may be passed through as a comma separated list of keys in // the ClientStateEvent.Key field. ClientStateEventDelAll )
ClientStateEvent kinds
type ClientStateReadWriter ¶
type ClientStateReadWriter interface { // ReadState should return a map like structure allowing it to look up // any values in the current session, or any cookie in the request ReadState(*http.Request) (ClientState, error) // WriteState can sometimes be called with a nil ClientState in the event // that no ClientState was read in from LoadClientState WriteState(http.ResponseWriter, ClientState, []ClientStateEvent) error }
ClientStateReadWriter is used to create a cookie storer from an http request. Keep in mind security considerations for your implementation, Secure, HTTP-Only, etc flags.
There's two major uses for this. To create session storage, and remember me cookies.
type ClientStateResponseWriter ¶
type ClientStateResponseWriter struct { http.ResponseWriter // contains filtered or unexported fields }
ClientStateResponseWriter is used to write out the client state at the last moment before the response code is written.
func MustClientStateResponseWriter ¶
func MustClientStateResponseWriter(w http.ResponseWriter) *ClientStateResponseWriter
MustClientStateResponseWriter tries to find a csrw inside the response writer by using the UnderlyingResponseWriter interface.
func (ClientStateResponseWriter) Header ¶
func (c ClientStateResponseWriter) Header() http.Header
Header retrieves the underlying headers
func (ClientStateResponseWriter) Hijack ¶ added in v2.3.0
func (c ClientStateResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error)
Hijack implements the http.Hijacker interface by calling the underlying implementation if available.
func (*ClientStateResponseWriter) UnderlyingResponseWriter ¶
func (c *ClientStateResponseWriter) UnderlyingResponseWriter() http.ResponseWriter
UnderlyingResponseWriter for this instance
func (*ClientStateResponseWriter) Write ¶
func (c *ClientStateResponseWriter) Write(b []byte) (int, error)
Write ensures that the client state is written before any writes to the body occur (before header flush to http client)
func (*ClientStateResponseWriter) WriteHeader ¶
func (c *ClientStateResponseWriter) WriteHeader(code int)
WriteHeader writes the header, but in order to handle errors from the underlying ClientStateReadWriter, it has to panic.
type Config ¶
type Config struct { Paths struct { // Mount is the path to mount authboss's routes at (eg /auth). Mount string // NotAuthorized is the default URL to kick users back to when // they attempt an action that requires them to be logged in and // they're not auth'd NotAuthorized string // AuthLoginOK is the redirect path after a successful authentication. AuthLoginOK string // ConfirmOK once a user has confirmed their account // this says where they should go ConfirmOK string // ConfirmNotOK is used by the middleware, when a user is still supposed // to confirm their account, this is where they should be redirected to. ConfirmNotOK string // LockNotOK is a path to go to when the user fails LockNotOK string // LogoutOK is the redirect path after a log out. LogoutOK string // OAuth2LoginOK is the redirect path after a successful oauth2 login OAuth2LoginOK string // OAuth2LoginNotOK is the redirect path after // an unsuccessful oauth2 login OAuth2LoginNotOK string // RecoverOK is the redirect path after a successful recovery of a // password. RecoverOK string // RegisterOK is the redirect path after a successful registration. RegisterOK string // RootURL is the scheme+host+port of the web application // (eg https://www.happiness.com:8080) for url generation. // No trailing slash. RootURL string // TwoFactorEmailAuthNotOK is where a user is redirected when // the user attempts to add 2fa to their account without verifying // their e-mail OR when they've completed the first step towards // verification and need to check their e-mail to proceed. TwoFactorEmailAuthNotOK string } Modules struct { // BCryptCost is the cost of the bcrypt password hashing function. BCryptCost int // ConfirmMethod IS DEPRECATED! See MailRouteMethod instead. // // ConfirmMethod controls which http method confirm expects. // This is because typically this is a GET request since it's a link // from an e-mail, but in api-like cases it needs to be able to be a // post since there's data that must be sent to it. ConfirmMethod string // ExpireAfter controls the time an account is idle before being // logged out by the ExpireMiddleware. ExpireAfter time.Duration // LockAfter this many tries. LockAfter int // LockWindow is the waiting time before the number of attemps are reset. LockWindow time.Duration // LockDuration is how long an account is locked for. LockDuration time.Duration // LogoutMethod is the method the logout route should use // (default should be DELETE) LogoutMethod string // MailRouteMethod is used to set the type of request that's used for // routes that require a token from an e-mail link's query string. // This is things like confirm and two factor e-mail auth. // // You should probably set this to POST if you are building an API // so that the user goes to the frontend with their link & token // and the front-end calls the API with the token in a POST JSON body. // // This configuration setting deprecates ConfirmMethod. // If ConfirmMethod is set to the default value (GET) then // MailRouteMethod is used. If ConfirmMethod is not the default value // then it is used until Authboss v3 when only MailRouteMethod will be // used. MailRouteMethod string // MailNoGoroutine is used to prevent the mailer from being launched // in a goroutine by the Authboss modules. // // This behavior will become the default in Authboss v3 and each // Mailer implementation will be required to use goroutines if it sees // fit. // // It's important that this is the case if you are using contexts // as the http request context will be cancelled by the Go http server // and it may interrupt your use of the context that the Authboss module // is passing to you, preventing proper use of it. MailNoGoroutine bool // RegisterPreserveFields are fields used with registration that are // to be rendered when post fails in a normal way // (for example validation errors), they will be passed back in the // data of the response under the key DataPreserve which // will be a map[string]string. // // All fields that are to be preserved must be able to be returned by // the ArbitraryValuer.GetValues() // // This means in order to have a field named "address" you would need // to have that returned by the ArbitraryValuer.GetValues() method and // then it would be available to be whitelisted by this // configuration variable. RegisterPreserveFields []string // RecoverTokenDuration controls how long a token sent via // email for password recovery is valid for. RecoverTokenDuration time.Duration // RecoverLoginAfterRecovery says for the recovery module after a // user has successfully recovered the password, are they simply // logged in, or are they redirected to the login page with an // "updated password" message. RecoverLoginAfterRecovery bool // OAuth2Providers lists all providers that can be used. See // OAuthProvider documentation for more details. OAuth2Providers map[string]OAuth2Provider // TwoFactorEmailAuthRequired forces users to first confirm they have // access to their e-mail with the current device by clicking a link // and confirming a token stored in the session. TwoFactorEmailAuthRequired bool // TOTP2FAIssuer is the issuer that appears in the url when scanning // a qr code for google authenticator. TOTP2FAIssuer string // DEPRECATED: See ResponseOnUnauthed // RoutesRedirectOnUnauthed controls whether or not a user is redirected // or given a 404 when they are unauthenticated and attempting to access // a route that's login-protected inside Authboss itself. // The otp/twofactor modules all use authboss.Middleware to protect // their routes and this is the redirectToLogin parameter in that // middleware that they pass through. RoutesRedirectOnUnauthed bool // ResponseOnUnauthed controls how a user is responded to when // attempting to access a route that's login-protected inside Authboss // itself. The otp/twofactor modules all use authboss.Middleware2 to // protect their routes and this is the failResponse parameter in that // middleware that they pass through. // // This deprecates RoutesRedirectOnUnauthed. If RoutesRedirectOnUnauthed // is true, the value of this will be set to RespondRedirect until // authboss v3. ResponseOnUnauthed MWRespondOnFailure } Mail struct { // RootURL is a full path to an application that is hosting a front-end // Typically using a combination of Paths.RootURL and Paths.Mount // MailRoot will be assembled if not set. // Typically looks like: https://our-front-end.com/authenication // No trailing slash. RootURL string // From is the email address authboss e-mails come from. From string // FromName is the name authboss e-mails come from. FromName string // SubjectPrefix is used to add something to the front of the authboss // email subjects. SubjectPrefix string } Storage struct { // Storer is the interface through which Authboss accesses the web apps // database for user operations. Server ServerStorer // CookieState must be defined to provide an interface capapable of // storing cookies for the given response, and reading them from the // request. CookieState ClientStateReadWriter // SessionState must be defined to provide an interface capable of // storing session-only values for the given response, and reading them // from the request. SessionState ClientStateReadWriter // SessionStateWhitelistKeys are set to preserve keys in the session // when authboss.DelAllSession is called. A correct implementation // of ClientStateReadWriter will delete ALL session key-value pairs // unless that key is whitelisted here. SessionStateWhitelistKeys []string } Core struct { // Router is the entity that controls all routing to authboss routes // modules will register their routes with it. Router Router // ErrorHandler wraps http requests with centralized error handling. ErrorHandler ErrorHandler // Responder takes a generic response from a controller and prepares // the response, uses a renderer to create the body, and replies to the // http request. Responder HTTPResponder // Redirector can redirect a response, similar to Responder but // responsible only for redirection. Redirector HTTPRedirector // BodyReader reads validatable data from the body of a request to // be able to get data from the user's client. BodyReader BodyReader // ViewRenderer loads the templates for the application. ViewRenderer Renderer // MailRenderer loads the templates for mail. If this is nil, it will // fall back to using the Renderer created from the ViewLoader instead. MailRenderer Renderer // Mailer is the mailer being used to send e-mails out via smtp Mailer Mailer // Logger implies just a few log levels for use, can optionally // also implement the ContextLogger to be able to upgrade to a // request specific logger. Logger Logger } }
Config holds all the configuration for both authboss and it's modules.
type ConfirmValuer ¶
ConfirmValuer allows us to pull out the token from the request
func MustHaveConfirmValues ¶
func MustHaveConfirmValues(v Validator) ConfirmValuer
MustHaveConfirmValues upgrades a validatable set of values to ones specific to a user that needs to be confirmed.
type ConfirmableUser ¶
type ConfirmableUser interface { User GetEmail() (email string) GetConfirmed() (confirmed bool) GetConfirmSelector() (selector string) GetConfirmVerifier() (verifier string) PutEmail(email string) PutConfirmed(confirmed bool) PutConfirmSelector(selector string) PutConfirmVerifier(verifier string) }
ConfirmableUser can be in a state of confirmed or not
func MustBeConfirmable ¶
func MustBeConfirmable(u User) ConfirmableUser
MustBeConfirmable forces an upgrade to a ConfirmableUser or panic.
type ConfirmingServerStorer ¶
type ConfirmingServerStorer interface { ServerStorer // LoadByConfirmSelector finds a user by his confirm selector field // and should return ErrUserNotFound if that user cannot be found. LoadByConfirmSelector(ctx context.Context, selector string) (ConfirmableUser, error) }
ConfirmingServerStorer can find a user by a confirm token
func EnsureCanConfirm ¶
func EnsureCanConfirm(storer ServerStorer) ConfirmingServerStorer
EnsureCanConfirm makes sure the server storer supports confirm-lookup operations
type ContextLogger ¶
ContextLogger creates a logger from a request context
type CreatingServerStorer ¶
type CreatingServerStorer interface { ServerStorer // New creates a blank user, it is not yet persisted in the database // but is just for storing data New(ctx context.Context) User // Create the user in storage, it should not overwrite a user // and should return ErrUserFound if it currently exists. Create(ctx context.Context, user User) error }
CreatingServerStorer is used for creating new users like when Registration or OAuth2 is being done.
func EnsureCanCreate ¶
func EnsureCanCreate(storer ServerStorer) CreatingServerStorer
EnsureCanCreate makes sure the server storer supports create operations
type Email ¶
type Email struct {
To, Cc, Bcc []string
ToNames, CcNames, BccNames []string
FromName, From string
ReplyToName, ReplyTo string
Subject string
TextBody string
HTMLBody string
}
Email all the things. The ToNames and friends are parallel arrays and must be 0-length or the same length as their counterpart. To omit a name for a user at an index in To simply use an empty string at that index in ToNames.
type EmailResponseOptions ¶
EmailResponseOptions controls how e-mails are rendered and sent
type ErrorHandler ¶
type ErrorHandler interface {
Wrap(func(w http.ResponseWriter, r *http.Request) error) http.Handler
}
ErrorHandler allows routing to http.HandlerFunc's that additionally return an error for a higher level error handling mechanism.
type Event ¶
type Event int
Event type is for describing events
const ( EventRegister Event = iota EventAuth // EventAuthHijack is used to steal the authentication process after a // successful auth but before any session variable has been put in. // Most useful for defining an additional step for authentication // (like 2fa). It needs to be separate to EventAuth because other modules // do checks that would also interrupt event handlers with an authentication // failure so there's an ordering problem. EventAuthHijack EventOAuth2 EventAuthFail EventOAuth2Fail EventRecoverStart EventRecoverEnd EventGetUser EventGetUserSession EventPasswordReset EventLogout )
Event kinds
type EventHandler ¶
EventHandler reacts to events that are fired by Authboss controllers. These controllers will normally process a request by themselves, but if there is special consideration for example a successful login, but the user is locked, the lock module's controller may seize control over the request.
Very much a controller level middleware.
type Events ¶
type Events struct {
// contains filtered or unexported fields
}
Events is a collection of Events that fire before and after certain methods.
func (*Events) FireAfter ¶
FireAfter event to all the Events with a context. The error can safely be ignored as it is logged.
func (*Events) FireBefore ¶
FireBefore executes the handlers that were registered to fire before the event passed in.
If it encounters an error it will stop immediately without calling other handlers.
If a handler handles the request, it will pass this information both to handlers further down the chain (to let them know that w has been used) as well as set w to nil as a precaution.
type FieldError ¶
FieldError describes an error on a field Typically .Error() has both Name() and Err() together, hence the reason for separation.
type FmtLogger ¶
type FmtLogger struct {
Logger
}
FmtLogger adds convenience functions on top of the logging methods for formatting.
type HTMLData ¶
type HTMLData map[string]interface{}
HTMLData is used to render templates with.
func NewHTMLData ¶
func NewHTMLData(data ...interface{}) HTMLData
NewHTMLData creates HTMLData from key-value pairs. The input is a key-value slice, where odd elements are keys, and the following even element is their value.
type HTTPRedirector ¶
type HTTPRedirector interface {
Redirect(w http.ResponseWriter, r *http.Request, ro RedirectOptions) error
}
HTTPRedirector redirects http requests to a different url (must handle both json and html) When an authboss controller wants to redirect a user to a different path, it will use this interface.
type HTTPResponder ¶
type HTTPResponder interface {
Respond(w http.ResponseWriter, r *http.Request, code int, templateName string, data HTMLData) error
}
HTTPResponder knows how to respond to an HTTP request Must consider: - Flash messages - XSRF handling (template data) - Assembling template data from various sources
Authboss controller methods (like the one called in response to POST /auth/login) will call this method to write a response to the user.
type LockableUser ¶
type LockableUser interface { User GetAttemptCount() (attempts int) GetLastAttempt() (last time.Time) GetLocked() (locked time.Time) PutAttemptCount(attempts int) PutLastAttempt(last time.Time) PutLocked(locked time.Time) }
LockableUser is a user that can be locked
func MustBeLockable ¶
func MustBeLockable(u User) LockableUser
MustBeLockable forces an upgrade to a LockableUser or panic.
type MWRequirements ¶ added in v2.2.0
type MWRequirements int
MWRequirements are user requirements for authboss.Middleware in order to access the routes in protects. Requirements is a bit-set integer to be able to easily combine requirements like so:
authboss.RequireFullAuth | authboss.Require2FA
const ( RequireNone MWRequirements = 0x00 // RequireFullAuth means half-authed users will also be rejected RequireFullAuth MWRequirements = 0x01 // Require2FA means that users who have not authed with 2fa will // be rejected. Require2FA MWRequirements = 0x02 )
Middleware requirements
type MWRespondOnFailure ¶ added in v2.2.0
type MWRespondOnFailure int
MWRespondOnFailure tells authboss.Middleware how to respond to a failure to meet the requirements.
const ( // RespondNotFound does not allow users who are not logged in to know a // route exists by responding with a 404. RespondNotFound MWRespondOnFailure = iota // RespondRedirect redirects users to the login page RespondRedirect // exists unlike the 404 option. RespondUnauthorized )
Middleware response types
type OAuth2Provider ¶
type OAuth2Provider struct { OAuth2Config *oauth2.Config AdditionalParams url.Values FindUserDetails func(context.Context, oauth2.Config, *oauth2.Token) (map[string]string, error) }
OAuth2Provider is the entire configuration required to authenticate with this provider.
The OAuth2Config does not need a redirect URL because it will be automatically created by the route registration in the oauth2 module.
AdditionalParams can be used to specify extra parameters to tack on to the end of the initial request, this allows for provider specific oauth options like access_type=offline to be passed to the provider.
FindUserDetails gives the config and the token allowing an http client using the authenticated token to be created, a call is then made to a known endpoint that will return details about the user we've retrieved the token for. Those details are returned as a map[string]string and subsequently passed into OAuth2ServerStorer.NewFromOAuth2. API this must be handled for each provider separately.
type OAuth2ServerStorer ¶
type OAuth2ServerStorer interface { ServerStorer // NewFromOAuth2 should return an OAuth2User from a set // of details returned from OAuth2Provider.FindUserDetails // A more in-depth explanation is that once we've got an access token // for the service in question (say a service that rhymes with book) // the FindUserDetails function does an http request to a known endpoint // that provides details about the user, those details are captured in a // generic way as map[string]string and passed into this function to be // turned into a real user. // // It's possible that the user exists in the database already, and so // an attempt should be made to look that user up using the details. // Any details that have changed should be updated. Do not save the user // since that will be done later by OAuth2ServerStorer.SaveOAuth2() NewFromOAuth2(ctx context.Context, provider string, details map[string]string) (OAuth2User, error) // SaveOAuth2 has different semantics from the typical ServerStorer.Save, // in this case we want to insert a user if they do not exist. // The difference must be made clear because in the non-oauth2 case, // we know exactly when we want to Create vs Update. However since we're // simply trying to persist a user that may have been in our database, // but if not should already be (since you can think of the operation as // a caching of what's on the oauth2 provider's servers). SaveOAuth2(ctx context.Context, user OAuth2User) error }
OAuth2ServerStorer has the ability to create users from data from the provider.
func EnsureCanOAuth2 ¶
func EnsureCanOAuth2(storer ServerStorer) OAuth2ServerStorer
EnsureCanOAuth2 makes sure the server storer supports oauth2 creation and lookup
type OAuth2User ¶
type OAuth2User interface { User // IsOAuth2User checks to see if a user was registered in the site as an // oauth2 user. IsOAuth2User() bool GetOAuth2UID() (uid string) GetOAuth2Provider() (provider string) GetOAuth2AccessToken() (token string) GetOAuth2RefreshToken() (refreshToken string) GetOAuth2Expiry() (expiry time.Time) PutOAuth2UID(uid string) PutOAuth2Provider(provider string) PutOAuth2AccessToken(token string) PutOAuth2RefreshToken(refreshToken string) PutOAuth2Expiry(expiry time.Time) }
OAuth2User allows reading and writing values relating to OAuth2 Also see MakeOAuthPID/ParseOAuthPID for helpers to fullfill the User part of the interface.
func MustBeOAuthable ¶
func MustBeOAuthable(u User) OAuth2User
MustBeOAuthable forces an upgrade to an OAuth2User or panic.
type RecoverEndValuer ¶
RecoverEndValuer is used to get data back from the final page of password recovery, the user will provide a password and it must be accompanied by the token to authorize the changing of that password. Contrary to the RecoverValuer, this should have validation errors for bad tokens.
func MustHaveRecoverEndValues ¶
func MustHaveRecoverEndValues(v Validator) RecoverEndValuer
MustHaveRecoverEndValues upgrades a validatable set of values to ones specific to a user that needs to be recovered.
type RecoverMiddleValuer ¶
RecoverMiddleValuer provides the token that the user submitted via their link.
func MustHaveRecoverMiddleValues ¶
func MustHaveRecoverMiddleValues(v Validator) RecoverMiddleValuer
MustHaveRecoverMiddleValues upgrades a validatable set of values to ones specific to a user that's attempting to recover.
type RecoverStartValuer ¶
RecoverStartValuer provides the PID entered by the user.
func MustHaveRecoverStartValues ¶
func MustHaveRecoverStartValues(v Validator) RecoverStartValuer
MustHaveRecoverStartValues upgrades a validatable set of values to ones specific to a user that needs to be recovered.
type RecoverableUser ¶
type RecoverableUser interface { AuthableUser GetEmail() (email string) GetRecoverSelector() (selector string) GetRecoverVerifier() (verifier string) GetRecoverExpiry() (expiry time.Time) PutEmail(email string) PutRecoverSelector(selector string) PutRecoverVerifier(verifier string) PutRecoverExpiry(expiry time.Time) }
RecoverableUser is a user that can be recovered via e-mail
func MustBeRecoverable ¶
func MustBeRecoverable(u User) RecoverableUser
MustBeRecoverable forces an upgrade to a RecoverableUser or panic.
type RecoveringServerStorer ¶
type RecoveringServerStorer interface { ServerStorer // LoadByRecoverSelector finds a user by his recover selector field // and should return ErrUserNotFound if that user cannot be found. LoadByRecoverSelector(ctx context.Context, selector string) (RecoverableUser, error) }
RecoveringServerStorer allows users to be recovered by a token
func EnsureCanRecover ¶
func EnsureCanRecover(storer ServerStorer) RecoveringServerStorer
EnsureCanRecover makes sure the server storer supports confirm-lookup operations
type RedirectOptions ¶
type RedirectOptions struct { // Success & Failure are used to set Flash messages / JSON messages // if set. They should be mutually exclusive. Success string Failure string // Code is used when it's an API request instead of 200. Code int // When a request should redirect a user somewhere on completion, these // should be set. RedirectURL tells it where to go. And optionally set // FollowRedirParam to override the RedirectURL if the form parameter // defined by FormValueRedirect is passed in the request. // // Redirecting works differently whether it's an API request or not. // If it's an API request, then it will leave the URL in a "redirect" // parameter. RedirectPath string FollowRedirParam bool }
RedirectOptions packages up all the pieces a module needs to write out a response.
type RememberValuer ¶
type RememberValuer interface { // GetShouldRemember is the checkbox or what have you that // tells the remember module if it should remember that user's // authentication or not. GetShouldRemember() bool }
RememberValuer allows auth/oauth2 to pass along the remember bool from the user to the remember module unobtrusively.
type RememberingServerStorer ¶
type RememberingServerStorer interface { ServerStorer // AddRememberToken to a user AddRememberToken(ctx context.Context, pid, token string) error // DelRememberTokens removes all tokens for the given pid DelRememberTokens(ctx context.Context, pid string) error // UseRememberToken finds the pid-token pair and deletes it. // If the token could not be found return ErrTokenNotFound UseRememberToken(ctx context.Context, pid, token string) error }
RememberingServerStorer allows users to be remembered across sessions
func EnsureCanRemember ¶
func EnsureCanRemember(storer ServerStorer) RememberingServerStorer
EnsureCanRemember makes sure the server storer supports remember operations
type Renderer ¶
type Renderer interface { // Load the given templates, will most likely be called multiple times Load(names ...string) error // Render the given template Render(ctx context.Context, page string, data HTMLData) (output []byte, contentType string, err error) }
Renderer is a type that can render a given template with some data.
type RequestLogger ¶
RequestLogger creates a logger from a request
type Router ¶
type Router interface { http.Handler Get(path string, handler http.Handler) Post(path string, handler http.Handler) Delete(path string, handler http.Handler) }
Router can register routes to later be used by the web application
type ServerStorer ¶
type ServerStorer interface { // Load will look up the user based on the passed the PrimaryID Load(ctx context.Context, key string) (User, error) // Save persists the user in the database, this should never // create a user and instead return ErrUserNotFound if the user // does not exist. Save(ctx context.Context, user User) error }
ServerStorer represents the data store that's capable of loading users and giving them a context with which to store themselves.
type UnderlyingResponseWriter ¶
type UnderlyingResponseWriter interface {
UnderlyingResponseWriter() http.ResponseWriter
}
UnderlyingResponseWriter retrieves the response writer underneath the current one. This allows us to wrap and later discover the particular one that we want. Keep in mind this should not be used to call the normal methods of a responsewriter, just additional ones particular to that type because it's possible to introduce subtle bugs otherwise.
type User ¶
User has functions for each piece of data it requires. Data should not be persisted on each function call. User has a PID (primary ID) that is used on the site as a single unique identifier to any given user (very typically e-mail or username).
User interfaces return no errors or bools to signal that a value was not present. Instead 0-value = null = not present, this puts the onus on Authboss code to check for this.
type UserValuer ¶
UserValuer allows us to pull out the PID and Password from the request.
func MustHaveUserValues ¶
func MustHaveUserValues(v Validator) UserValuer
MustHaveUserValues upgrades a validatable set of values to ones specific to an authenticating user.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package auth implements password based user logins.
|
Package auth implements password based user logins. |
Package confirm implements confirmation of user registration via e-mail
|
Package confirm implements confirmation of user registration via e-mail |
Package defaults houses default implementations for the very many interfaces that authboss has.
|
Package defaults houses default implementations for the very many interfaces that authboss has. |
Package expire helps expire user's logged in sessions
|
Package expire helps expire user's logged in sessions |
Package lock implements user locking after N bad sign-in attempts.
|
Package lock implements user locking after N bad sign-in attempts. |
Package logout allows users to log out (from auth or oauth2 logins)
|
Package logout allows users to log out (from auth or oauth2 logins) |
Package mocks defines implemented interfaces for testing modules
|
Package mocks defines implemented interfaces for testing modules |
Package oauth2 allows users to be created and authenticated via oauth2 services like facebook, google etc.
|
Package oauth2 allows users to be created and authenticated via oauth2 services like facebook, google etc. |
Package otp allows authentication through a one time password instead of a traditional password.
|
Package otp allows authentication through a one time password instead of a traditional password. |
twofactor
Package twofactor allows authentication via one time passwords
|
Package twofactor allows authentication via one time passwords |
twofactor/sms2fa
Package sms2fa implements two factor auth using sms-transmitted one time passwords.
|
Package sms2fa implements two factor auth using sms-transmitted one time passwords. |
twofactor/totp2fa
Package totp2fa implements two factor auth using time-based one time passwords.
|
Package totp2fa implements two factor auth using time-based one time passwords. |
Package recover implements password reset via e-mail.
|
Package recover implements password reset via e-mail. |
Package register allows for user registration.
|
Package register allows for user registration. |
Package remember implements persistent logins using cookies
|
Package remember implements persistent logins using cookies |