server package¶
Module contents¶
The server module implements an authentication server.
It is a WSGI app implemented in falcon and exposes an app variable that can be called from any WSGI server, like gunicorn.
A typical invocation is:
gunicorn -b 0.0.0.0:8005 server:create_app()
On import a sqlite database is initialized and logging is started.
For more information see the GitHub repo
The following attributes will be initialized to the values defined in the corresponding environment variables
-
server.
DEBUGLEVEL
¶ can be CRITICAL, ERROR, SUCCESS, INFO, DEBUG, TRACE. Defaults to DEBUG
-
server.
DATABASE_FILE
¶ path to database file, default to user.db
-
server.
DATABASE_BACKOFF
¶ number of seconds to wait between database connection retries, defaults to 1, doubles every retry.
-
server.
DATABASE_RETRIES
¶ number of times to retry a database connection. Defaults to 3.
-
server.
create_app
()[source]¶ An WSGI app factory.
- Returns
falcon.API
When the app is created, a SQLAlchemy/sqlite database is initialized with
server.get_sessionmaker()
.The initialization will also create an admin user with
server.add_superuser()
.
Submodules¶
server.server module¶
This module handles the http requests related to user and session management.
It also provides utility functions to initialize the database and admin user.
The attributes listed below configure the authserver and are initialized from environment variables with the same name.
Additional attributes are defined at the package level (in server
) and in smtp
.
Attributes:
The following environment variables define credentials but are not present in the module as attributes.
ADMIN_USER_FILE point to a file containing admin user name.
ADMIN_USER admin user name, overrides ADMIN_USER_FILE
ADMIN_PASSWORD_FILE point to a file containing admin password.
ADMIN_PASSWORD admin password, overrides ADMIN_PASSWORD_FILE
-
server.server.
number
(variable, default)[source]¶ Return the integer in the environment variable.
- Parameters
variable (str) – the name of the environment variable
default (int) – the default value to return if variable is not defined
- Returns
An integer value.
-
server.server.
getvar
(variable, default='<unknown>')[source]¶ Return the value of the environment variable.
- Parameters
variable (str) – the name of the environment variable
default (str) – the default value to return if variable is not defined
- Returns
A string.
-
server.server.
getfile
(variable, defaultfilename, default='Hi {name}, click {link}, Regards {website}')[source]¶ Return the contents of the file specified in the environment variable.
- Parameters
variable (str) – the name of the environment variable
defaultfilename (str) – the filename to use if the variable is not defined
default (str) – the string to return if the file couldn’t be found
The default contains the following placeholders that can be used in the actual files as well
{name} the full name of the user
{link} a confirmation link to click
{website} the name of the application/website
- Returns
A string.
-
server.server.
DOMAIN
= 'yourdomain.org'¶ Domain to be used in session cookie, e.g. yourdomain.org
-
server.server.
APPLICATION
= '/books'¶ Redirect locations for successful logon, e.g. /books
-
server.server.
LOGINSCREEN
= ''¶ Location of login screen, e.g. /books/login.html
-
server.server.
CONFIRMREGISTRATION
= 'https//server.yourdomain.org/auth/confirmregistration'¶ Base url in email registration confirmation, e.g.
https://server.yourdomain.org/auth/confirmregistration
-
server.server.
RESETPASSWORD
= 'https://server.yourdomain.org/auth/resetpassword'¶ Base url in password reset request confirmation, e.g.
https://server.yourdomain.org/auth/resetpassword
-
server.server.
WEBSITE
= '"Book Collection"'¶ The name of the app/website, e.g. Book Collection
-
server.server.
SOFTTIMEOUT
= 30¶ Session soft limit in minutes
-
server.server.
HARDTIMEOUT
= 480¶ Session hard limit in minutes
-
server.server.
PWRESETTIMEOUT
= 60¶ Password reset request confirmation limit in minutes
-
server.server.
REGISTERTIMEOUT
= 60¶ Registration confirmation limit in minutes
-
server.server.
EMAILTEMPLATE_FORGOTPASSWORD
= 'Hi {name}, click {link}, Regards {website}'¶ File containing email template for password reset confirmation email
See
getfile()
for allowed template variables inside the text.
-
server.server.
EMAILTEMPLATE_REGISTER
= 'Hi {name}, click {link}, Regards {website}'¶ File containing email template for registration confirmation email
See
getfile()
for allowed template variables inside the text.
-
server.server.
SESSIONID_pattern
= regex.Regex('[01-9a-f]{32}', flags=regex.V0)¶ Legal pattern for a session id and confirmation ids
-
server.server.
PASSWORD_lower
= regex.Regex('[a-z]', flags=regex.V0)¶ These characters are considered lowercase in passwords
-
server.server.
PASSWORD_upper
= regex.Regex('[A-Z]', flags=regex.V0)¶ These characters are considered uppercase in passwords
-
server.server.
PASSWORD_digit
= regex.Regex('[01-9]', flags=regex.V0)¶ These characters are considered digits in passwords
-
server.server.
PASSWORD_special
= regex.Regex('[ !|@#$%^&*()\\-_.,<>?/\\\\{}\\[\\]]', flags=regex.V0)¶ These characters are considered special in passwords
-
server.server.
newpassword
(password)[source]¶ Return a cryptographic hash of password as a string of hex digits.
The password is salted with 16 random bytes. The salt is prepended as 32 hex digits to the returned hash.
- Parameters
password (str) – the password to hash.
- Returns
A string consisting of 32 + 64 hexadecimal characters.
-
server.server.
checkpassword
(password, reference)[source]¶ Compare a plaintext password to a hashed reference.
The reference is a string of hex digits, the first 32 being the salt.
-
server.server.
allowed_password
(s)[source]¶ Check if a password meets the complexity criteria:
between 8 and 64 characters,
contain at least 1 lowercase, 1 uppercase, 1 digit and 1 special character
it may not contain characters outside those classes
character classes _are_ unicode aware
-
class
server.server.
ParameterSet
(specs={})[source]¶ Bases:
object
Defines allowable input parameters for a POST or GET request.
-
__init__
(specs={})[source]¶ Creates a ParameterSet instance based on a dictionary of parameters.
- Parameters
specs (dict) –
specifies a mapping name –> (ex, maxlength) name is a case sensitive name of an allowed input parameter
ex is either a string, a regular expression or a callable that specifies the validity of a value.
maxlength is an integer that specifies the maximum length of a parameter value
If ex is a string it is converted to a regular expression.
If ex is a callable it should return a boolean indicating the validity of a value.
-
check
(params)[source]¶ Return true if all params are all allowed.
- Parameters
params (dict) –
is a mapping name –> value, where name and value are strings Each value should match the requirements specified for ‘name’.
If params contains extra parameters or it is missing items it is considered invalid.
-
-
server.server.
alchemyencoder
(obj)[source]¶ A JSON encoder for SQLAlchemy
declarative_base()
objects,date
andDecimal
objects.Base
objects are returned asdict
object with a key for each column. A column with a name equal to password is _not_ included. If a Base object has a user column, an extra key email is added that contains user.email.date
objects are returned as an isoformat string.Decimal
objects are returned as a float.- Parameters
obj (object) – an object to decode
- Returns
A
dict
,str
,float
or None.
Like all default encoders for json it returns objects which are then encoded to json strings by the main encoder.
an example:
import json jsonstring = json.dumps(someobject, default=alchemyencoder)
-
class
server.server.
User
(**kwargs)[source]¶ Bases:
sqlalchemy.ext.declarative.api.Base
ORM representation of a User.
-
id
¶ Primary key
-
email
¶ user name (a valid email address)
-
password
¶ hashed password
-
name
¶ full name
-
superuser
¶ role, true if superuser
-
created
¶ timestamp
-
active
¶ true if user account is enabled
-
attempts
¶ number of failed login attempts
-
accessed
¶ timestamp of last access
-
locked
¶ timestamp of user lockout
-
__init__
(**kwargs)¶ A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and values in
kwargs
.Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.
-
-
class
server.server.
Session
(**kwargs)[source]¶ Bases:
sqlalchemy.ext.declarative.api.Base
ORM representation of a Session.
Any session will be deleted if the corresponding user is deleted.
-
id
¶ primary key holds a guid
-
created
¶ timestamp
-
softlimit
¶ timestamp, session must show activity before this time to be renewed
-
hardlimit
¶ timestamp, after this time the session will be removed regardless
-
userid
¶ foreign key to User, on cascade delete is on
-
user
¶ ORM link to User
-
__init__
(**kwargs)¶ A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and values in
kwargs
.Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.
-
-
class
server.server.
PendingUser
(**kwargs)[source]¶ Bases:
sqlalchemy.ext.declarative.api.Base
ORM representation of a PendingUser (a newly registered user awaiting confirmation).
-
id
¶ primary key holds a guid
-
email
¶ user name (a valid email address)
-
name
¶ full name
-
password
¶ hashed password
-
created
¶ timestamp
-
expires
¶ timestamp, after this time the session will be removed regardless
-
__init__
(**kwargs)¶ A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and values in
kwargs
.Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.
-
-
class
server.server.
PasswordReset
(**kwargs)[source]¶ Bases:
sqlalchemy.ext.declarative.api.Base
ORM representation of a PasswordReset event awaiting confirmation.
This PasswordReset will be deleted if the corresponding user is deleted.
-
__init__
(**kwargs)¶ A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and values in
kwargs
.Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.
-
id
¶ primary key holds a guid
-
created
¶ timestamp
-
expires
¶ timestamp, after this time the session will be removed regardless
-
userid
¶ foreign key to User, on cascade delete is on
-
user
¶ ORM link to User
-
-
server.server.
max_body
(limit)[source]¶ A
falcon.before()
hook to limit the size of request body.- Parameters
limit (int) – maximum size in bytes of the request body
- Raises
falcon.HTTPPayloadTooLarge –
- Returns
a hook function
-
class
server.server.
LoginResource
[source]¶ Bases:
object
Routing endpoint that serves the action of a login form.
-
on_post
(req, resp)[source]¶ Handle a logon POST request.
- Parameters
req – the request
resp – the response
- Returns
None
The method expects its input as www-formencoded parameters in the request body.
On success it will set the Location header to
APPLICATION
and return a session cookie.On failure it will set the Location header to
LOGINSCREEN
.It will always set the response status to
falcon.HTTP_303
.- Other Parameters
email – the username of the user (a valid email address)
password – the password
login – the literal text Login
Typically these parameters would correspond to input fields in an HTML form and a submit button with a name=Login attribute and send as input parameters in the body of the request.
-
-
class
server.server.
RegisterResource
[source]¶ Bases:
object
Routing endpoint that serves the action of a registration form.
-
on_post
(req, resp)[source]¶ Handle a register POST request.
- Parameters
req – the request
resp – the response
- Returns
None
The method expects its input as www-formencoded parameters in the request body.
On success it will create a pending user request and send an email with a confirmation link.
On failure it will do nothing.
It will always set the Location header to
LOGINSCREEN
.It will always set the response status to
falcon.HTTP_303
.- Other Parameters
email – the username of the user (a valid email address)
name – the full name of the user
password – the password ( 8 >= length <= 64, must contain at lease 1 lowercase, 1 uppercase, 1 digit and 1 special char.
password2 – must be identical to the password parameter
login – the literal text Register
Typically these parameters would correspond to input fields in an HTML form and a submit button with a name=Register attribute and send as input parameters in the body of the request.
-
-
class
server.server.
ForgotPasswordResource
[source]¶ Bases:
object
Routing endpoint that serves the action of a forgot password form.
-
on_post
(req, resp)[source]¶ Handle a forgotpassword POST request.
- Parameters
req – the request
resp – the response
- Returns
None
The method expects its input as www-formencoded parameters in the request body.
On success it will create a password reset request and send an email with a confirmation link.
On failure it will do nothing.
It will always set the Location header to
LOGINSCREEN
.It will always set the response status to ;attr:falcon.HTTP_303.
- Other Parameters
email – the username of the user (a valid email address)
login – the literal text Forgot
Typically these parameters would correspond to input fields in an HTML form and a submit button with a name=Forgot attribute and send as input parameters in the body of the request.
-
-
class
server.server.
VerifySessionResource
[source]¶ Bases:
object
Routing endpoint that serves as the internal endpoint to verify the existence of a valid session.
-
on_post
(req, resp)[source]¶ Handle a verifysession POST request.
- Parameters
req – the request
resp – the response
- Returns
email(str)
id(int)
name(str)
superuser(bool)
- Return type
On success the response body will contain the following key=value pairs separated by newline characters
The method expects its input as www-formencoded parameters in the request body.
On success it will the session data and set the response status to
falcon.HTTP_200
.On failure it will do nothing and return a response status of
falcon.HTTP_404
.- Other Parameters
email – the username of the user (a valid email address)
login – the literal text Forgot
This method should not be called from the browser. It is typically called by other backend servers to verify the validity of a session and get the email address, name and superuser status of that session.
It does not accept requests that have an X-Forwarded-Host header defined, so if the authserver and the backend server are positioned behind a reverse proxy that adds these headers (like traefik) all things will be fine.
-
session_active
(session, sessionid)[source]¶ Check whether a sessionid represents an active session.
A session is active
if the sessionid exists
its
Session.softlimit
is in the future.
If a session is found to be valid, its
Session.softlimit
is set toSOFTTIMEOUT
minutes from now.- Parameters
session (DBSession) – SQLAlchemy session
sessionid (str) – a sessionid
- Returns
a bytes object with a newline separated list of key=value pairs
On failure: None
- Return type
On success
-
-
class
server.server.
LogoutResource
[source]¶ Bases:
object
Routing endpoint that serves the action of a logout form.
-
on_post
(req, resp)[source]¶ Handle a logout POST request.
- Parameters
req – the request
resp – the response
- Returns
None
The method expects no input parameters in the request body. A valid sessionid cookie should be present.
On success it will remove the session.
On failure it will do nothing.
It will always set the Location header to
LOGINSCREEN
.It will always set the response status to ;attr:falcon.HTTP_303.
-
-
class
server.server.
ChoosePasswordResource
[source]¶ Bases:
object
Routing endpoint that serves the action of a choose new password form.
-
on_post
(req, resp)[source]¶ Handle a choose password POST request.
- Parameters
req – the request
resp – the response
- Returns
None
The method expects its input as www-formencoded parameters in the request body. It also
On success it will change the password of the user.
On failure it will do nothing.
It will always set the Location header to
LOGINSCREEN
.It will always set the response status to
falcon.HTTP_303
.- Other Parameters
resetid – an id that should be present in the
PendingUser
tablepassword – the password ( 8 >= length <= 64, must contain at lease 1 lowercase, 1 uppercase, 1 digit and 1 special char.
password2 – must be identical to the password parameter
choose – the literal text Choose
Typically these parameters would correspond to input fields in an HTML form and a submit button with a choose=Choose attribute and send as input parameters in the body of the request.
-
-
class
server.server.
StatsResource
[source]¶ Bases:
object
Routing endpoint that serves as the REST endpoint for user information overviews.
It can return information in JSON format on
User
,PendingUser
,PasswordReset
andSession
.Access is restricted to logged in users woth the superuser role.
-
on_post
(req, resp, item)[source]¶ Handle a stats/{item} POST request, typically one initialed by an AJAX call.
- Parameters
req – the request
resp – the response
item (str) – the kind of item for which a list should be returned
- Returns
None
Even though this is a POST handler, it should have no input parameters in the body. The items that can be requested are:
users: to return a JSON encoded list of
User
objectssessions: to return a JSON encoded list of
Session
objectspendingusers: to return a JSON encoded list of
PendingUser
objectspasswordreset: to return a JSON encoded list of
PasswordReset
objects
On success the response body will contain a bytes object that is JSON data (in UTF-8 encoding). Note that any password attributes will be stripped form the output.
Example
JSON data is returned an object with a data attribute:
{ "data": [ {"id": 165675, "email": "abc@example.org", ...}, {"id": 365625, "email": "def@example.org", ...}, ... ] }
-
-
class
server.server.
ConfirmRegistrationResource
[source]¶ Bases:
object
Routing endpoint that serves the registration confirmation link.
-
on_get
(req, resp)[source]¶ - Parameters
req – the request
resp – the response
- Returns
None
The method expects its input as query parameters in the url.
On success it will create a
User
from the correspondingPendingUser
.On failure it will do nothing.
It will always set the Location header to
LOGINSCREEN
.It will always set the response status to
falcon.HTTP_303
.- Other Parameters
confirmationid – an id that should be present in the
PendingUser
table
-
-
class
server.server.
ConfirmForgotPasswordResource
[source]¶ Bases:
object
Routing endpoint that serves the password reset confirmation link.
-
on_get
(req, resp)[source]¶ - Parameters
req – the request
resp – the response
- Returns
None
The method expects its input as query parameters in the url.
On success it will create a
User
from the correspondingPendingUser
.On failure it will do nothing.
It will always set the Location header to
LOGINSCREEN
. If a pending request was found, ?choosepassword=id will be appended to the url. If not ?expired will be added.It will always set the response status to
falcon.HTTP_303
.- Other Parameters
confirmationid – an id that should be present in the
PasswordReset
table
-
-
server.server.
fetch_admin_params
()[source]¶ Get admin variables from file or environment.
Enviroment variables overrule variables in files.
- Returns
tuple(admin_user, admin_password)
Module level attributes referenced:
ADMIN_USER_FILE
filename of file containing super user username (valid email address)ADMIN_USER
username (valid email address) of super user, will override ADMIN_USER_FILEADMIN_PASSWORD_FILE
filename of file containing super user password in plaintextADMIN_PASSWORD
super user password in plaintext, will override ADMIN_PASSWORD_FILE
-
server.server.
add_superuser
()[source]¶ Add superuser account to
User
table.Will remove any user account with the same name along with any associated session.
-
server.server.
set_sqlite_pragma
(dbapi_connection, connection_record)[source]¶ Enable cascading constraint on the SQLAlchemy tables.
See: https://docs.sqlalchemy.org/en/13/dialects/sqlite.html#foreign-key-support
-
server.server.
get_sessionmaker
(connection, timeout, retries)[source]¶ Create and initialize a global
sqlalchemy.orm.sessionmaker
.- Parameters
connection (str) – a sqlite connection string
timeout (int) – number of seconds to wait between connection retries. doubles with evert attempt.
retries (int) – number of times to retry a connection to the database.
- Returns
bool
The
sqlalchemy.orm.sessionmaker
object is stored in the globalDBSession
.