You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Discuss/Define authentication mechansim for "magiclinks" #2517
Here's the plan for the authentication workflow of magic guest links as discussed with @JammingBen
Authentication workflow
Accessing a resource shared using a magic guest link works like this:
Share creation
The sharer creates a magic guest link for a specific email address. A magic token is stored in the backend for that email.
An email with the according magic link is sent to the user
Authentication
The user clicks the link in their email
The web page loads, retrieves the token from the URL and trades it for a cookie by sending it to a verify endpoint in the backend (e.g. /magic_guest_link_auth/verify/token)
The backend looks up the token and either
marks the token as used and sends a signed jwt with a 24h expiry as a httponly, secure cookie. The jwt includes the share id and the role.
returns a structured 401 error if the token has expired, e.g.
In this case the frontend uses the renew endpoint to create a new token as described in the Token refresh section. The web app also shows a form to enter the PIN to gain access.
Access
Requests to the actual resource now transport the jwt cookie
A backend middleware verifies the jwt and
grants access if the jwt is fine
returns a structured 401 error if the jwt has expired.
When the frontend retrieves a token_expired or session_expired 401 error it POSTs the share id from the 401 to a renewal endpoint (e.g. /magic_guest_link_auth/renew)which will generate a new magic token AND a PIN and sends an according email to the user. The web app shows a form to enter the PIN to regain access.
The user can either click the magic guest link in the email or enter the pin in the existing browser tab. The link restarts a new authentication flow as described above while the PIN makes a request to a different verify endpoint (e.g. /magic_guest_link_auth/verify/pin) which expects both the PIN and some contextual information like the share id from the 401 response to create a new jwt.
Endpoints
POST /magic_guest_link_auth/verify/token
Purpose: Trades a token for a fresh 24h JWT cookie.
Payload: { "token": "abc123xyz..." }
Response: 200 OK (+ Set-Cookie header) OR 401 Unauthorized (+ token_expired error).
POST /magic_guest_link_auth/verify/pin
Purpose: Trades a PIN and share ID combo for a fresh 24h JWT cookie.
Payload: { "pin": "123456", "share_id": "" }
Response: 200 OK (+ Set-Cookie header) OR 401 Unauthorized (if PIN is wrong).
POST /magic_guest_link_auth/renew
Purpose: Generates a new magic token/PIN set and sends it out by email.
Payload: { "share_id": "" }
Response: 200 OK (Indicates the email was successfully dispatched).
Activity
rhafer commentedon Mar 24, 2026
cc @kulmann
aduffeck commentedon Apr 15, 2026
Here's the plan for the authentication workflow of magic guest links as discussed with @JammingBen
Authentication workflow
Accessing a resource shared using a magic guest link works like this:
Share creation
Authentication
The user clicks the link in their email
The web page loads, retrieves the token from the URL and trades it for a cookie by sending it to a verify endpoint in the backend (e.g.
/magic_guest_link_auth/verify/token)The backend looks up the token and either
In this case the frontend uses the
renewendpoint to create a new token as described in theToken refreshsection. The web app also shows a form to enter the PIN to gain access.Access
Requests to the actual resource now transport the jwt cookie
A backend middleware verifies the jwt and
grants access if the jwt is fine
returns a structured 401 error if the jwt has expired.
Token refresh
token_expiredorsession_expired401 error it POSTs the share id from the 401 to arenewalendpoint (e.g./magic_guest_link_auth/renew)which will generate a new magic token AND a PIN and sends an according email to the user. The web app shows a form to enter the PIN to regain access./magic_guest_link_auth/verify/pin) which expects both the PIN and some contextual information like the share id from the 401 response to create a new jwt.Endpoints
POST
/magic_guest_link_auth/verify/tokenPurpose: Trades a token for a fresh 24h JWT cookie.
Payload: { "token": "abc123xyz..." }
Response: 200 OK (+ Set-Cookie header) OR 401 Unauthorized (+ token_expired error).
POST
/magic_guest_link_auth/verify/pinPurpose: Trades a PIN and share ID combo for a fresh 24h JWT cookie.
Payload: { "pin": "123456", "share_id": "" }
Response: 200 OK (+ Set-Cookie header) OR 401 Unauthorized (if PIN is wrong).
POST
/magic_guest_link_auth/renewPurpose: Generates a new magic token/PIN set and sends it out by email.
Payload: { "share_id": "" }
Response: 200 OK (Indicates the email was successfully dispatched).
aduffeck commentedon Apr 15, 2026
Documented as part of this issue for now. We'll merge this into more sophisticated documentation of the whole feature when we get there.