Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
projects:sso [2025/07/09 10:30] – created samp20projects:sso [2025/07/09 16:33] (current) – Magic link code samp20
Line 21: Line 21:
  
 Email login will send a "magic link" to your registered email address. When clicked this will log you in to the original page you were on, not the page opened when clicking the link. This will allow you to login on your phone while clicking the email on your desktop for example. This could also work on the Hackspace portal if desired. Email login will send a "magic link" to your registered email address. When clicked this will log you in to the original page you were on, not the page opened when clicking the link. This will allow you to login on your phone while clicking the email on your desktop for example. This could also work on the Hackspace portal if desired.
 +
 +In order to avoid mis-clicking a "magic link" triggered by a potential attacker, both the email and login page should display a code so the member can check they are clicking the correct link.
  
 ==== Keyfob/card login ==== ==== Keyfob/card login ====
Line 27: Line 29:
  
 An additional security measure will be required to ensure these keyfob logins only come from the Hackspace network. For now an IP allowlist should be sufficient, along with a global lockout if a significant number of keyfob login attempts are spotted. It is recognised that IP addresses can theoretically be spoofed, but quite difficult in practice. The global lockout would be a nuclear countermeasure in the extremely rare instance someone does figure this out. An additional security measure will be required to ensure these keyfob logins only come from the Hackspace network. For now an IP allowlist should be sufficient, along with a global lockout if a significant number of keyfob login attempts are spotted. It is recognised that IP addresses can theoretically be spoofed, but quite difficult in practice. The global lockout would be a nuclear countermeasure in the extremely rare instance someone does figure this out.
 +
 +===== Login state machine =====
 +
 +Logins shall be handled by a state machine stored in the Database which is created upon receiving a login flow from Hydra. Each web request will process the state machine in the following order:
 +  - Create a state object for the current state
 +  - Validate that object against the current request (e.g. checking form fields)
 +  - If validated then use a transition table to update the current state
 +  - Use the current state to render the appropriate form (if the validation had failed then this will render any error messages to the user too)
 +
 +The following states will be supported:
 +
 +  * Email entry (this will also validate a passkey if submitted)
 +  * Magic link (this page will poll in the background until the link has been clicked)
 +  * Keyfob scan
 +  * TOTP
 +  * Finish
 +
 +Here is the proposed transition table:
 +^ Current state ^ Condition (assumes validated) ^ Next state ^ Comments ^
 +| None | | Email entry | |
 +| Email entry | email submitted | Magic link | We treat all emails as valid to prevent this page being used to check if an email exists | |
 +| Email entry | passkey submitted | Finish | |
 +| Email entry | portal cookie set | Keyfob scan | |
 +| Magic link | member has TOTP | TOTP | |
 +| Magic link | member doesn't have TOTP | Finish | While the login might succeed, the OAuth application may still reject the login if additional security is required |
 +| Keyfob scan | Member has TOTP | TOTP | If a member has setup TOTP then we assume they always want the extra security |
 +| Keyfob scan | member doesn't have TOTP | Finish | |
 +| Keyfob scan | Email login requested | Magic link | If a member gets their keyfob locked out or doesn't have it on them then this gives another option |
 +| TOTP | | Finish | |
 +
 +Below is the same table in diagram form:
 +
 +{{drawio>projects:sso_transitions.png}}
 +
 +As well as the explicit transitions there will also be the option to reset everything back to the start.
 +
 +===== Permissions model =====
 +
 +Permissions shall be granted through OAuth scopes or other custom claims. As these claims can sometimes be application specific, a general purpose approach is proposed using Members, Roles and ClaimSets with the following relationships:
 +
 +  * Many-to-many between Members and Roles
 +  * One-to-many between Roles and ClaimSets
 +
 +A Role describes a high-level role a member has, for example "onboarding". A ClaimSet describes the specific OAuth claims associated with that role. The reason for separating ClaimSets from Roles is to be able to limit a ClaimSet to a single OAuth client without requiring a member to join multiple Roles if that Role involves multiple clients.
 +
 +An example ClaimSet for Grafana access to the "viewer" team may look like the following:
 +
 +<code>
 +{
 +    "scope": ["openid", "email"],
 +    "groups": ["viewer"]
 +}
 +</code>
 +
 +This ClaimSet would be restricted to the Grafana OAuth client in order to avoid granting the "openid" scope to other clients and inadvertently giving access to them.
 +
  • projects/sso.1752057032
  • Last modified: 14 hours ago
  • by samp20