Authentication handlers¶
Base handler class¶
The Handler
class defines the abstract interface for an
authentication handler. Handlers are registered to an authl.Authl
instance which then selects the handler based on the provided identity.
The basic flow for how a handler is selected is:
- The
authl.Authl
instance checks to see if any handler knows how to handle the identity URL directly; if so, it returns the first match. - The instance retrieves the URL, and hands the parse tree and response headers off to each handler to see if it’s able to handle the URL based on that; if so, it returns the first match.
In the case of a Webfinger address (e.g. @user@example.com
) it repeats this
process for every profile URL provided by the Webfinger response until it finds
a match.
-
class
authl.handlers.
Handler
¶ Base class for authentication handlers
-
check_callback
(url: str, get: dict, data: dict) → authl.disposition.Disposition¶ Checks the authorization callback sent by the external provider.
Parameters: - url (str) – the full URL of the verification request
- get (dict) – the GET parameters for the verification
- data (dict) – the POST parameters for the verification
Returns: a
authl.disposition
object to be handled by the frontend. Any errors which get raised internally should be caught and returned as an appropriateauthl.disposition.Error
.
-
handles_page
(url: str, headers, content, links) → bool¶ Returns
True
/truthy if we can handle the page based on page contentParameters: - url (str) – the canonicized identity URL
- headers (dict) – the raw headers from the page request, as a MultiDict (as provided by the Requests library)
- content (bs4.BeautifulSoup) – the page content, as a BeautifulSoup4 parse tree
- links (dict) – the results of parsing the Link: headers, as a dict of rel -> dict of ‘url’ and ‘rel’, as provided by the Requests library
-
handles_url
(url: str) → Optional[str]¶ If this handler can handle this URL (or something that looks like it), return something truthy, e.g. a canonicized version of the URL. Otherwise, return None.
It is okay to check for an API endpoint (relative to the URL) in implementing this. However, if the content kept at the URL itself needs to be parsed to make the determination, implement that in
handles_page()
instead.Whatever value this returns will be passed back in to initiate_auth, so if that value matters, return a reasonable URL.
-
initiate_auth
(id_url: str, callback_uri: str, redir: str) → authl.disposition.Disposition¶ Initiates the authentication flow.
Parameters: - id_url (str) – Canonicized identity URL
- callback_uri (str) – Callback URL for verification
- redir (str) – Where to redirect the user to after verification
Returns: the
authl.disposition
to be handled by the frontend.
-
cb_id
¶ The callback ID for callback registration. Must be unique across all registered handlers, and should be short and stable.
-
description
¶ A description of the service, in HTML format.
-
generic_url
¶ A generic URL that can be used with this handler irrespective of identity.
-
logo_html
¶ A list of tuples of (html,label) for the login buttons.
The HTML should be an isolated
<svg>
element, or an<img src>
pointing to a publicly-usablehttps:
URL.
-
service_name
¶ The human-readable service name
-
url_schemes
¶ A list of supported URL schemes for the login UI to fill in with a placeholder.
The list is of tuples of
(format, default_placeholder)
, where the format string contains a'%'
indicating where the placeholder goes.
-
Email handler¶
This handler emails a “magic link” to the user so that they can log in that way. It requires an SMTP server of some sort; see your hosting provider’s documentation for the appropriate configuration. This should also be able to work with your regular email provider.
See from_config()
for the simplest configuration mechanism.
-
class
authl.handlers.email_addr.
EmailAddress
(sendmail, notify_cdata, token_store: authl.tokens.TokenStore, expires_time: int = None, pending_storage: dict = None, email_template_text: str = "Hello! Someone, possibly you, asked to log in using this email address. If thisnwas you, please visit the following link within the next {minutes} minutes:nn {url}nnIf this wasn't you, you can safely disregard this message.nn")¶ Authenticate using a “magic link” sent via email.
Parameters: - sendmail – A function that, given an
email.message
object, sends it. It is the responsibility of this function to set the From and Subject headers before it sends. - notify_cdata – the callback data to provide to the user for the next step instructions
- token_store (tokens.TokenStore) – Storage for the identity tokens
- expires_time (int) – how long the email link should be valid for, in seconds (default: 900)
- pending_storage (dict) – Storage to keep track of pending email addresses,
for DDOS/abuse mitigation. Defaults to an ExpiringDict that expires
after
expires_time
- email_template_text (str) – the plaintext template for the sent email, provided as a template string
Email templates are formatted with the following parameters:
{url}
: the URL that the user should visit to complete login{minutes}
: how long the URL is valid for, in minutes
-
handles_url
(url)¶ Accepts any email address formatted as
user@example.com
ormailto:user@example.com
. The actual address is validated usingvalidate_email
.
- sendmail – A function that, given an
-
authl.handlers.email_addr.
from_config
(config, token_store: authl.tokens.TokenStore)¶ Generate an
EmailAddress
handler from the provided configuration dictionary.Parameters: - config (dict) –
The configuration settings for the handler. Relevant keys:
EMAIL_SENDMAIL
: a function to call to send the email; if omitted, generates one usingsimple_sendmail()
configured with:EMAIL_FROM
: theFrom:
address to use when sending an emailEMAIL_SUBJECT
: theSubject:
to use for a login emailSMTP_HOST
: the outgoing SMTP hostSMTP_PORT
: the outgoing SMTP portSMTP_USE_SSL
: whether to use SSL for the SMTP connection (defaults toFalse
). It is highly recommended to set this to True if yourSMTP_HOST
is anything other thanlocalhost
.SMTP_USERNAME
: the username to use with the SMTP serverSMTP_PASSWORD
: the password to use with the SMTP server
EMAIL_CHECK_MESSAGE
: Theauthl.disposition.Notify
client data. Defaults to a simple string-based message.EMAIL_TEMPLATE_FILE
: A path to a text file for the email message; if not specified a default template will be used.EMAIL_EXPIRE_TIME
: How long a login email is valid for, in seconds (defaults to theEmailAddress
default value)
- token_store (tokens.TokenStore) – the authentication token storage
mechanism; see
authl.tokens
for more information.
- config (dict) –
-
authl.handlers.email_addr.
simple_sendmail
(connector, sender_address, subject)¶ A simple SMTP sendmail handler.
Parameters: - connector (function) – A factory-type function that returns an
smtplib.SMTP
-compatible object in the connected state. Usesmtplib_connector()
for an easy-to-use general-purpose connector. - sender_address (str) – The email address to use for the sender
- subject (str) – the subject line to attach to the message
:returns” a function that, when called with an
email.message.EmailMessage
, sets the From and Subject lines and sends the message via the provided connector.- connector (function) – A factory-type function that returns an
-
authl.handlers.email_addr.
smtplib_connector
(hostname, port, username=None, password=None, use_ssl=False)¶ A utility class that generates an SMTP connection factory.
Parameters: - hostname (str) – The SMTP server’s hostname
- port (int) – The SMTP server’s connection port
- username (str) – The SMTP server username
- password (str) – The SMTP server port
- use_ssl (bool) – Whether to use SSL
Fediverse handler¶
This handler allows login via Fediverse instances; currently Mastodon and Pleroma are supported, as is anything else with basic support for the Mastodon client API.
See from_config()
for the simplest configuration mechanism.
-
class
authl.handlers.fediverse.
Fediverse
(name: str, token_store: authl.tokens.TokenStore, timeout: Optional[int] = None, homepage: Optional[str] = None)¶ Handler for Fediverse services (Mastodon, Pleroma)
Instantiate a Fediverse handler.
Parameters: - name (str) – Human-readable website name
- homepage (str) – Homepage for the website
- token_store – Storage for session tokens
- timeout (int) – How long to allow a user to wait to log in, in seconds
-
handles_url
(url)¶ Checks for an
/api/v1/instance
endpoint to determine if this is a Mastodon-compatible instance
-
authl.handlers.fediverse.
from_config
(config, token_store: authl.tokens.TokenStore)¶ Generate a Fediverse handler from the given config dictionary.
Parameters: - config (dict) –
Configuration values; relevant keys:
FEDIVERSE_NAME
: the name of your website (required)FEDIVERSE_HOMEPAGE
: your website’s homepage (recommended)FEDIVERSE_TIMEOUT
: the maximum time to wait for login to complete
- token_store (tokens.TokenStore) – The authentication token storage
- config (dict) –
IndieAuth handler¶
This handler allows people to log in from their own websites using the
IndieAuth federated protocol. See
from_config()
for the simplest configuration mechanism.
Note that the client ID must match the domain name of your website. If you’re
using this with authl.flask
, there is a function,
authl.flask.client_id
, which provides this at runtime with no
configuration necessary. For other frameworks you will need to either configure
this with your public-facing domain name, or retrieve the domain name from
whatever framework you’re using. Please note also that the scheme (http
vs.
https
) must match.
-
class
authl.handlers.indieauth.
IndieAuth
(client_id: Union[str, Callable[[...], str]], token_store: authl.tokens.TokenStore, timeout: int = None)¶ Supports login via IndieAuth.
SECURITY NOTE: When used with tokens.Serializer, this is subject to certain classes of replay attack; for example, if the user endpoint uses irrevocable signed tokens for the code grant (which is done in many endpoints, e.g. SelfAuth), an attacker can replay a transaction that it intercepts. As such it is very important that the timeout be configured to a reasonably short time to mitigate this.
Parameters: - client_id – The client_id to send to the remote IndieAuth provider. Can be a string or a function that returns a string.
- token_store – Storage for the tokens
- timeout (int) – Maximum time to wait for login to complete (default: 600)
-
handles_page
(url, headers, content, links)¶ Returns: whether an authorization_endpoint
was found on the page.
-
handles_url
(url)¶ If this page is already known to have an IndieAuth endpoint, we reuse that; otherwise this returns
None
so the Authl instance falls through tohandles_page()
.
-
authl.handlers.indieauth.
find_endpoint
(id_url: str, links: Dict[KT, VT] = None, content: bs4.BeautifulSoup = None, rel: str = 'authorization_endpoint') → Tuple[Optional[str], str]¶ Given an identity URL, get its IndieAuth endpoint
Parameters: - id_url (str) – an identity URL to check
- links – a request.links object from a requests operation
- content (BeautifulSoup) – a BeautifulSoup parse tree of an HTML document
- rel (str) – the endpoint rel to retrieve
Returns: a tuple of
(endpoint_url, profile_url)
-
authl.handlers.indieauth.
find_endpoints
(id_url: str, links: Dict[KT, VT] = None, content: bs4.BeautifulSoup = None) → Tuple[Dict[str, str], str]¶ Given an identity URL, discover its IndieWeb endpoints
Parameters: - id_url (str) – an identity URL to check
- links – a request.links object from a requests operation
- content (BeautifulSoup) – a BeautifulSoup parse tree of an HTML document
Returns: a tuple of
({endpoint_name:endpoint_url}, profile_url)
-
authl.handlers.indieauth.
from_config
(config, token_store)¶ Generate an IndieAuth handler from the given config dictionary.
Possible configuration values:
INDIEAUTH_CLIENT_ID
: the client ID (URL) of your website (required)INDIEAUTH_PENDING_TTL
: timemout for a pending transction
-
authl.handlers.indieauth.
get_profile
(id_url: str, server_profile: dict = None, links=None, content: bs4.BeautifulSoup = None, endpoints=None) → dict¶ Given an identity URL, try to parse out an Authl profile
Parameters: - id_url (str) – The profile page to parse
- server_profile (dict) – An IndieAuth response profile
- links (dict) – Profile response’s links dictionary
- content – Pre-parsed page content
- endpoints (dict) – Pre-parsed page endpoints
-
authl.handlers.indieauth.
verify_id
(request_id: str, response_id: str) → str¶ Given an ID from an identity request and its verification response, ensure that the verification response is a valid URL for the request. A response is considered valid if it declares the same authorization_endpoint.
Parameters: - request_id (str) – The original requested identity
- response_id (str) – The authorized response identity
Returns: the verified response ID
Raises: ValueError
if verification failed
Twitter¶
This handler allows third-party login using Twitter.
To use it you will need to register your website as an application via the
Twitter developer portal and retrieve your
client_key
and client_secret
from there. You will also need to register
your website’s Twitter callback handler(s). Remember to include all URLs that
the callback might be accessed from, including test domains.
It is highly recommended that you only store the client_key
and
client_secret
in an environment variable rather than by checked-in code, as
a basic security precaution against credential leaks.
See from_config()
for the simplest configuration mechanism.
-
class
authl.handlers.twitter.
Twitter
(client_key: str, client_secret: str, timeout: int = None, storage: dict = None)¶ Twitter login handler.
Parameters: - client_key (str) – The Twitter
client_key
value - client_secret (str) – The Twitter
client_secret
value - timeout (int) – How long, in seconds, the user has to complete the login
- storage (dict) – A
dict
-like object that persistently stores the OAuth token and secret during the login transaction. This needs to persist on at least a per-user basis. It is safe to use the user session or browser cookies for this storage.
-
static
build_profile
(user_info: dict) → dict¶ Convert a Twitter userinfo JSON into an Authl profile
- client_key (str) – The Twitter
-
authl.handlers.twitter.
from_config
(config, storage)¶ Generate a Twitter handler from the given config dictionary.
Posible configuration values:
TWITTER_CLIENT_KEY
: The Twitter app’s client_keyTWITTER_CLIENT_SECRET
: The Twitter app’s client_secretTWITTER_TIMEOUT
: How long to wait for the user to log in
It is *HIGHLY RECOMMENDED* that the client key and secret be provided via environment variables or some other mechanism that doesn’t involve checking these values into source control and exposing them on the file system.
Test handler¶
This is a handler which always lets people log in as any URL with the fake
scheme of test:
, with the exception of test:error
which generates an
error. This is only to be used for testing locally and should not be enabled in
production.
-
class
authl.handlers.test_handler.
TestHandler
¶ An Authl handler which always returns True for any URI beginning with ‘test:’. Primarily for testing purposes.
-
handles_url
(url)¶ Returns
True
if the URL starts with'test:'
.
-
initiate_auth
(id_url, callback_uri, redir)¶ Immediately returns a
disposition.Verified
, unless the URL is'test:error'
in which case it returns adisposition.Error
.
-