Skip to content

Instantly share code, notes, and snippets.

@jacobobryant
Last active February 17, 2023 03:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jacobobryant/527ce48a66a5138ea907c0307793e140 to your computer and use it in GitHub Desktop.
Save jacobobryant/527ce48a66a5138ea907c0307793e140 to your computer and use it in GitHub Desktop.
authentication plugin docstring
(com.biffweb/authentication-plugin
{:biff.auth/keys [app-path
check-state
new-user-tx
single-opt-in
email-validator]})
A Biff plugin that includes backend routes for passwordless authentication.
Email links are used for signup, and six-digit email codes are used for
signin. Sign-in links have a bit less friction, while sign-in codes are
resilient to embedded browsers and PWAs on mobile devices.
Returns a features map that can be included with the rest of your app's
features.
OPTIONS
=======
:biff.auth/app-path (default: "/app")
Users will be redirected here after they sign in successfully.
:biff.auth/check-state (default: true)
If true and the user opens the signup link on a different device or browser
from the one the link was requested on, then the user will have to re-enter
their email address before being authenticated. This helps to prevent people
from being tricked into signing into someone else's account.
:biff.auth/new-user-tx
A function that returns a transaction for creating a new user. Default:
(fn [ctx email]
[{:db/doc-type :user
:db.op/upsert {:user/email email}
:user/joined-at :db/now}])
:biff.auth/single-opt-in (default: false)
If true, the user's account will be created immediately after they submit
their email address. Otherwise, their account will only be created after they
verify their address by clicking the signup link.
:biff.auth/email-validator
A predicate function that checks if a given email address is valid. Default:
(fn [ctx email]
(and email (re-matches #".+@.+\..+" email)))
For extra protection, you can supply a function that calls out to an email
validation API, like Mailgun's.
ROUTES
======
All routes that are protected by Recaptcha take a required
g-recaptcha-response form parameter, which should be set automatically by the
Recaptcha client library.
POST /auth/signup
-----------------
Sends a signup link to the user's email address. The link goes to
/verify-link/:token.
Form parameters:
- email: The user's email address.
Redirects:
- /welcome?email={email}: Success.
- /?error=recaptcha: The recaptcha test failed.
- /?error=invalid-email: The :biff.auth/email-validator function returned
false.
- /?error=send-failed: The :biff/send-email function returned false.
Protected by Recaptcha.
GET /auth/verify-link/:token
----------------------------
A link to this endpoint is generated and sent to the user by the /auth/signup
endpoint. On success, assigns the :uid parameter in the user's session to
their user ID. If the user doesn't exist yet, creates a new account.
Path parameters:
- token: A JWT generated by the /auth/signup endpoint. Expires after one
hour.
Redirects:
- {:biff.auth/app-path}: Success
- /?error=invalid-link: The token was invalid or expired.
- /signup/link?token={token}: The user needs to provide their email address
again so we can ensure it matches the address
contained in the token.
POST /auth/verify-link
----------------------
Verifies that the user's email address matches one contained in the token. On
success, assigns the :uid parameter in the user's session to their user ID.
If the user doesn't exist yet, creates a new account.
Form parameters:
- token: A JWT generated by the /auth/signup endpoint. Expires after one
hour.
- email: The user's email address.
Redirects:
- {:biff.auth/app-path}: Success
- /?error=invalid-link: The token was invalid or expired.
- /signup/link?token={token}&error=incorrect-email:
The email address provided didn't match the one in
the token.
POST /auth/signin
-----------------
Sends a six-digit (numeric) sign-in code to the user's email address. The
code expires after three minutes or three failed verification attempts.
Form parameters:
- email: The user's email address.
Redirects:
- /signin/code?email={email}: Success.
- /signin?error=recaptcha: The recaptcha test failed.
- /signin?error=no-user: The user needs to create an account first.
- /signin?error=send-failed: The :biff/send-email function returned false.
Protected by Recaptcha.
POST /auth/verify-code
----------------------
Verifies that the code provided by the user matches the one they were sent.
On success, assigns the :uid parameter in the user's session to their user
ID.
Form parameters:
- email: The user's email address.
- code: A six-digit code.
Redirects:
- {:biff.auth/app-path}: Success.
- /signin/code?error=invalid-code&email={email}:
The given code was incorrect or expired.
Protected by Recaptcha.
POST /auth/signout
------------------
Removes the :uid from the user's session. Redirects to /.
SCHEMA
======
:biff.auth/code documents are used to store users' signin codes:
{:biff.auth.code/id :uuid
:biff.auth/code [:map {:closed true}
[:xt/id :biff.auth.code/id]
[:biff.auth.code/user :user/id]
[:biff.auth.code/code :string]
[:biff.auth.code/created-at inst?]
[:biff.auth.code/failed-attempts integer?]]}
User documents must include a :user/email key.
INSTRUCTIONS
============
You should provide the following pages in your app:
- /: Posts to /auth/signup with Recaptcha and shows messages
for the following errors: recaptcha, invalid-email,
send-failed, and invalid-link.
- /welcome: Tells the user to check their inbox for a signup link.
- /signup/link: Asks the user to verify their email address. Posts to
/auth/verify-link.
- /signin: Posts to /auth/signin with Recaptcha and shows messages
for the following errors: recaptcha, no-user, and
send-failed.
- /signin/code: Asks the user for the six-digit code that was sent to their
email address. Posts to /auth/verify with Recaptcha. Also
posts to /auth/signin with Recaptcha if the user requests
another sign-in code.
Your :biff/send-email function must accept the following templates:
- :signup-link, with parameters :to, :url, and :user-exists.
- :signin-code, with parameters :to and :code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment