This module contains all the central authentication functionality.
It exports a number of high-level functions to be used directly in your application handlers.
We also export a number of mid-level functions that should be helpful when you are integrating with another way of confirming the authentication of login requests.
- createUser :: Text -> ByteString -> Handler b (AuthManager b) AuthUser
- usernameExists :: Text -> Handler b (AuthManager b) Bool
- saveUser :: AuthUser -> Handler b (AuthManager b) AuthUser
- destroyUser :: AuthUser -> Handler b (AuthManager b) ()
- loginByUsername :: ByteString -> Password -> Bool -> Handler b (AuthManager b) (Either AuthFailure AuthUser)
- loginByRememberToken :: Handler b (AuthManager b) (Maybe AuthUser)
- forceLogin :: AuthUser -> Handler b (AuthManager b) (Either AuthFailure AuthUser)
- logout :: Handler b (AuthManager b) ()
- currentUser :: Handler b (AuthManager b) (Maybe AuthUser)
- isLoggedIn :: Handler b (AuthManager b) Bool
- markAuthSuccess :: AuthUser -> Handler b (AuthManager b) AuthUser
- markAuthFail :: AuthUser -> Handler b (AuthManager b) AuthUser
- checkPasswordAndLogin :: AuthUser -> Password -> Handler b (AuthManager b) (Either AuthFailure AuthUser)
- data AuthManager b = forall r . IAuthBackend r => AuthManager {
- backend :: r
- session :: Lens b (Snaplet SessionManager)
- activeUser :: Maybe AuthUser
- minPasswdLen :: Int
- rememberCookieName :: ByteString
- rememberPeriod :: Maybe Int
- siteKey :: Key
- lockout :: Maybe (Int, NominalDiffTime)
- class IAuthBackend r where
- data AuthSettings = AuthSettings {}
- defAuthSettings :: AuthSettings
- data AuthUser = AuthUser {
- userId :: Maybe UserId
- userLogin :: Text
- userPassword :: Maybe Password
- userActivatedAt :: Maybe UTCTime
- userSuspendedAt :: Maybe UTCTime
- userRememberToken :: Maybe Text
- userLoginCount :: Int
- userFailedLoginCount :: Int
- userLockedOutUntil :: Maybe UTCTime
- userCurrentLoginAt :: Maybe UTCTime
- userLastLoginAt :: Maybe UTCTime
- userCurrentLoginIp :: Maybe ByteString
- userLastLoginIp :: Maybe ByteString
- userCreatedAt :: Maybe UTCTime
- userUpdatedAt :: Maybe UTCTime
- userRoles :: [Role]
- userMeta :: HashMap Text Value
- defAuthUser :: AuthUser
- newtype UserId = UserId {}
- data Password
- data AuthFailure
- data BackendError
- data Role = Role ByteString
- withBackend :: (forall r. IAuthBackend r => r -> Handler b (AuthManager v) a) -> Handler b (AuthManager v) a
- encryptPassword :: Password -> IO Password
- checkPassword :: Password -> Password -> Bool
- authenticatePassword :: AuthUser -> Password -> Maybe AuthFailure
- setPassword :: AuthUser -> ByteString -> IO AuthUser
- registerUser :: ByteString -> ByteString -> Handler b (AuthManager b) AuthUser
- loginUser :: ByteString -> ByteString -> Maybe ByteString -> (AuthFailure -> Handler b (AuthManager b) ()) -> Handler b (AuthManager b) () -> Handler b (AuthManager b) ()
- logoutUser :: Handler b (AuthManager b) () -> Handler b (AuthManager b) ()
- requireUser :: Lens b (Snaplet (AuthManager b)) -> Handler b v a -> Handler b v a -> Handler b v a
- addAuthSplices :: HasHeist b => Lens b (Snaplet (AuthManager b)) -> Initializer b v ()
- ifLoggedIn :: Lens b (Snaplet (AuthManager b)) -> SnapletSplice b v
- ifLoggedOut :: Lens b (Snaplet (AuthManager b)) -> SnapletSplice b v
Higher Level Handler Functions
createUser :: Text -> ByteString -> Handler b (AuthManager b) AuthUserSource
Create a new user from just a username and password
May throw a DuplicateLogin if given username is not unique
:: Text | The username to be checked |
-> Handler b (AuthManager b) Bool |
Check whether a user with the given username exists.
saveUser :: AuthUser -> Handler b (AuthManager b) AuthUserSource
Create or update a given user
May throw a BackendError
if something goes wrong.
destroyUser :: AuthUser -> Handler b (AuthManager b) ()Source
Destroy the given user
May throw a BackendError
if something goes wrong.
:: ByteString | Username/login for user |
-> Password | Should be ClearText |
-> Bool | Set remember token? |
-> Handler b (AuthManager b) (Either AuthFailure AuthUser) |
Lookup a user by her username, check given password and perform login
loginByRememberToken :: Handler b (AuthManager b) (Maybe AuthUser)Source
Remember user from the remember token if possible and perform login
:: AuthUser | An existing user, somehow looked up from db |
-> Handler b (AuthManager b) (Either AuthFailure AuthUser) |
Login and persist the given AuthUser
in the active session
Meant to be used if you have other means of being sure that the person is who she says she is.
logout :: Handler b (AuthManager b) ()Source
Logout the active user
currentUser :: Handler b (AuthManager b) (Maybe AuthUser)Source
Return the current user; trying to remember from cookie if possible.
isLoggedIn :: Handler b (AuthManager b) BoolSource
Convenience wrapper around rememberUser
that returns a bool result
Lower Level Functions
markAuthSuccess :: AuthUser -> Handler b (AuthManager b) AuthUserSource
Mutate an AuthUser
, marking successful authentication
This will save the user to the backend.
markAuthFail :: AuthUser -> Handler b (AuthManager b) AuthUserSource
Mutate an AuthUser
, marking failed authentication
This will save the user to the backend.
:: AuthUser | An existing user, somehow looked up from db |
-> Password | A ClearText password |
-> Handler b (AuthManager b) (Either AuthFailure AuthUser) |
Authenticate and log the user into the current session if successful.
This is a mid-level function exposed to allow roll-your-own ways of looking up a user from the database.
This function will:
- Check the password
- Login the user into the current session
- Mark success/failure of the authentication trial on the user record
Types
data AuthManager b Source
Abstract data type holding all necessary information for auth operation
forall r . IAuthBackend r => AuthManager | |
|
class IAuthBackend r whereSource
All storage backends need to implement this typeclass
Backend operations may throw BackendError
s
save :: r -> AuthUser -> IO AuthUserSource
Needs to create or update the given AuthUser
record
lookupByUserId :: r -> UserId -> IO (Maybe AuthUser)Source
lookupByLogin :: r -> Text -> IO (Maybe AuthUser)Source
lookupByRememberToken :: r -> Text -> IO (Maybe AuthUser)Source
IAuthBackend JsonFileAuthManager |
data AuthSettings Source
Authetication settings defined at initialization time
AuthSettings | |
|
defAuthSettings :: AuthSettingsSource
Default settings for Auth.
asMinPasswdLen = 8 asRememberCookieName = "_remember" asRememberPeriod = Just (2*7*24*60*60) = 2 weeks asLockout = Nothing asSiteKey = "site_key.txt"
Type representing the concept of a User in your application.
Default AuthUser that has all empty values.
Internal representation of a User
. By convention, we demand that the
application is able to directly fetch a User
using this identifier.
Think of this type as a secure, authenticated user. You should normally never see this type unless a user has been authenticated.
Password is clear when supplied by the user and encrypted later when returned from the db.
data AuthFailure Source
Authentication failures indicate what went wrong during authentication. They may provide useful information to the developer, although it is generally not advisable to show the user the exact details about why login failed.
UserNotFound | |
IncorrectPassword | |
PasswordMissing | |
LockedOut UTCTime | Locked out until given time |
AuthError String |
data BackendError Source
This will be replaced by a role-based permission system.
Other Utilities
:: (forall r. IAuthBackend r => r -> Handler b (AuthManager v) a) | The function to run with the handler. |
-> Handler b (AuthManager v) a |
Run a function on the backend, and return the result.
This uses an existential type so that the backend type doesn't
escape
AuthManager. The reason that the type is Handler b
(AuthManager v) a and not a is because anything that uses the
backend will return an IO something, which you can liftIO, or a
Handler b (AuthManager v) a if it uses other handler things.
checkPassword :: Password -> Password -> BoolSource
:: AuthUser | Looked up from the back-end |
-> Password | Check against this password |
-> Maybe AuthFailure |
Check password for a given user.
Returns Nothing if check is successful and an IncorrectPassword error otherwise
setPassword :: AuthUser -> ByteString -> IO AuthUserSource
Set a new password for the given user. Given password should be
clear-text; it will be encrypted into a Encrypted
.
Handlers
registerUser :: ByteString -> ByteString -> Handler b (AuthManager b) AuthUserSource
Register a new user by specifying login and password Param
fields
:: ByteString | Username field |
-> ByteString | Password field |
-> Maybe ByteString | Remember field; Nothing if you want no remember function. |
-> (AuthFailure -> Handler b (AuthManager b) ()) | Upon failure |
-> Handler b (AuthManager b) () | Upon success |
-> Handler b (AuthManager b) () |
A MonadSnap
handler that processes a login form.
The request paremeters are passed to performLogin
:: Handler b (AuthManager b) () | What to do after logging out |
-> Handler b (AuthManager b) () |
Simple handler to log the user out. Deletes user from session.
:: Lens b (Snaplet (AuthManager b)) | |
-> Handler b v a | Do this if no authenticated user is present. |
-> Handler b v a | Do this if an authenticated user is present. |
-> Handler b v a |
Require that an authenticated AuthUser
is present in the current
session.
This function has no DB cost - only checks to see if a user_id is present in the current session.
Splice helpers
:: HasHeist b | |
=> Lens b (Snaplet (AuthManager b)) | A lens reference to |
-> Initializer b v () |
Add all standard auth splices to a Heist-enabled application.
This adds the following splices: <ifLoggedIn> <ifLoggedOut>
ifLoggedIn :: Lens b (Snaplet (AuthManager b)) -> SnapletSplice b vSource
A splice that can be used to check for existence of a user. If a user is present, this will run the contents of the node.
<ifLoggedIn> Show this when there is a logged in user </ifLoggedIn>
ifLoggedOut :: Lens b (Snaplet (AuthManager b)) -> SnapletSplice b vSource
A splice that can be used to check for absence of a user. If a user is not present, this will run the contents of the node.
<ifLoggedOut> Show this when there is a logged in user </ifLoggedOut>