Conversation
|
Thanks so much for this contribution 🙏 The one thing that's surprising to me is that "request OTP" seems to be its own independent flow. I'm still paging in, but naively I would have expected that for users with OTP enabled, the auth flow doesn't return an access token but rather an "upgradable token" that together with the OTP can be "upgraded" into a proper auth token. In other words, I'm surprised that this change doesn't touch the login flow. |
|
You mean to have multifactor authentification, sign in with password then ask for OTP ? It could also work like that. I made it the way I use it with firebase (which is more a magic link) and supabase where I receive an email with a code (a link for firebase) and use it to sign in without password. |
|
I see now - thanks. This is an alternative, not an expanded authentication flow 👍 I'll admit, that's not a flow i've ever used. Naively, I would expect this to be less secure and less convenient than a pw manager. Curious to hear what makes you favor this approach? To be transparent, what I originally had in mind was to add a second-factor for the added security. |
|
So I added passwordless TOTP signin. Now we can add settings to enable/disable those auth methods and maybe choose if we want 2 authentication factors. In my case I need passwordless signin but for sure we should be able to ask for 2 auth methods if they are setup. The login UI probably will change and I added the TOTP generation in the AuthButton, maybe it should be somewhere else and it needs also a verification step. In my company we switched from password auth to passwordless to have less support and firebase magic link works very well. I think it's good to have the option and for sensitive accounts use multifactor auth. Password manager are good but not everybody uses them and clients are happy to just receive a link or code rather than have to remember a password that they will forget and then do the "forget password" flow to sign in every time ^^. |
|
In Pocketbase if there's 2 factors enabled the first auth throws an error 400 and the second auth works (the order doesn't matter). We could enable 2FA and when someone sign in the first signin would respond that it worked but needs another signin method then if it succeed the user would be signed in. I'll check that this week. |
|
@ignatz what about:
Do you have preferences or suggestions? |
|
Sumary of what I did:
New TS client fonctions:
To generate/disable TOTP sign in in the admin then go in the auth button (bottom left). |
|
Sorry, for the radio silence - apologies! I fell down a cross-platform-build rabbit hole and must have banged my head. I'm back now and will look at this ASAP - thanks already 🙏
Thanks for the motivation. I guess I could see this work well for internal tooling 👍 . I'll also take a closer look at what firebase offers (and supabase apparently).
W/o yet having looked at it, I would assume we could do many digits. Isn't it just a link folks click on?
That sounds pretty much what I would have naively expected 👍
That's amazing 🎉 🙏 |
|
I've been researching more about the topic so there's things I'd do differently. The main points I found out are:
Since OTP/magic link are both short lived, random, reset after a couple of attempts, are not stored anywhere by the user I think they're way more secure than a password created and managed by a user (like storing password123 in a note app or using the same leaked password for everything ^^). I made a nuxt project to have a project with the basics stuff, if you want to look at the auth part https://github.com/maxirozay/nuxt-base/tree/master/server/api/auth. |
That sounds sensible.
You can round-trip the email or just pick-it up server side, given a secure token. Both seems fine. We already use the DB for reset codes, etc. I don't understand why a KV store would be more secure, in memory or persistent. Especially since you argue they should have a short lifetime. Persistence is a good thing, you want TB to be able to restart (e.g. update), while a user auths. Is there something I'm missing?
Disagree. You're just delegating the security to he user's email account, i.e. you cannot make any strong statements either way. It may be more secure, it may be less secure 🤷♀️ Coming back to the PR, I'll start taking a closer look. As you've already noticed, there's a lot of details, considerations and trade-offs. I'm not sure what the best way is to go about it. Breaking this PR up and tuning all those details, will probably require a lot of back-and-forth. My naive approach would be to pull out and modify bits and pieces, make sure that changes are properly attributed. Was this PR mostly prompted? No hate, this is not a college exam, I care about the destination, not the journey. It just seems silly to go back and forth between me and your LLM with you as a person-in-the-middle. Let me know what works for you, I'm flexible 🙏 |
|
Just a quick update (also for myself to organize my thoughts and remember) after looking at the PR. There's some good stuff, things that may require some work (just to be clear, I'm not trying to dump extra work on your lap, always happy to get my hands dirty):
|
For the KV store I'm not saying it's more secure just that it doesn't have to bother the DB with all the code requests. You can have the persistance with an external KV like redis that doesn't stop while you restart TB. All my points are general thought not necessarily things that should be done.
I don't know rust so the rust code yes, for some trivial code I use the autocomplete but everything was read, edited and cleaned, it's not just a dumb prompt dump. |
Appreciated. Just want to make sure, I'm understanding things alright. Oftentimes, I'm just confused
After reading your initial point again, you may have meant that pulling the tokens out, they're safe from any hypothetical SQL injection (in TB or users' WASM code). That makes a lot of sense. I like the idea. I'm not sure redis would be a good fit, TBs general approach but e.g. pulling them out into a separate db connection would have some nice properties. That's true for all tokens: otp, password reset, email verification, ... I will add this to my list of things to do 👍 🙏
👍 I've been thinking a bit more about how to best skin the cat. I think that some level of initial auth-ui support would be healthy to inform the flows. Email OTP and TOTP could be staggered. I'm leaning prioritizing TOTP, mostly because it's more complicated. We'd have to figure out the flows. PocketBase's approach for returning 401 on first-factor auth won't work for the auth-ui. Nice puzzle :) |
|
I don't know what can be done with the auth UI but if that can help, on the project i previously linked, I made a route to get all the sign in options. I only ask for the email then I get the options and show them to the user. So if a user has TOTP after validating their email I'll show the TOTP field. The route doesn't say if a user exist or not it just return the options so you can technically see if a user exist but you can't see if it doesn't exist. That's a point I'm still not sure if I should keep it this way. |
Appreciated. This works well for client-side JS. Ideally all auth UIs would work w/o JS purely relying on HTML forms and SSR. At the same time the auth APIs and UIs need to be decoupled. I ended up passing an mfa_redirect target to the login, so the API can hand back to the UI, when TOTP or other MFA is required, which can then pass an mfa_token plus second secret to a mfa_login endpoint. Not sure this is most elegant but it works :/. This is all turning out to be pretty big :hide: |
|
If it works it works ^^ it still an optional component anyway |
de57875 to
25ffbd0
Compare
|
Quick update. I have most parts in place including TOTP and OTP and a bunch of nice improvements. Besides some more testing and updating more clients, I'm primarily missing a good way to pass configuration/state to the admin SPA, specifically if OTP is enabled or not for the instance. I would either:
|
|
You can't check if OTP is enabled then render the button if it is, even with an env or an endpoint to get the config? |
I take this as a rhetorical question :). A build-time env variable wouldn't work, since enablement is a runtime property and the admin UI is currently fully client-rendered. We don't inject any state at least right now. With an endpoint we could. There just isn't a public settings endpoint yet. There are admin config endpoints but they require you to be logged in as an admin. I was considering to add a public auth settings endpoint, which is still an option, for now I just made the OTP UI less prominent and it will just yield an error if you try 🤷♀️ |
…gins UIs to admin dash and the auth-ui crate. Loosely based on maxirozay@'s #212.
|
v0.25.0 adds second-factor TOTP and OTP email support in the server, the two UIs and all 8 clients. It also changes how we handle session like state and OTP codes are moved to a separate |
This PR add OTP #208 by sending an email with a 8 characters code. It is implemented in the typescript client and in the admin login.