From 4640d8cbc2458b7ed872fd04f3c6b072a659ae40 Mon Sep 17 00:00:00 2001 From: Alex Grin Date: Fri, 22 Oct 2021 10:41:27 -0400 Subject: [PATCH] Created auth flows (markdown) --- auth-flows.md | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 auth-flows.md diff --git a/auth-flows.md b/auth-flows.md new file mode 100644 index 0000000..6191ca5 --- /dev/null +++ b/auth-flows.md @@ -0,0 +1,85 @@ +# Desktop Flows + +## Anonymous + +1. If no auth_token is present, `internal-api/user/new` is called by `lbryinc.Lbryio.authenticate` +2. An auth_token is returned, which looks like this: `738oP7hAK71Qfexd3urfd9nyCyxPkgoG` +3. `response.auth_token` is kept and sent with all subsequent requests as a POST query `auth_token`parameter + +## Registration + +1. `internal-api/user_email/new` method is called with user’s email as an argument +2. An email with a confirmation link is sent to the user +3. Desktop starts querying `internal-api/user_email/status` +4. User clicks the link in the confirmation email, calling `internal-api/user_email/confirm` + +## Passwordless Authentication (with Merging) + +The passwordless authentication allows users to "login" without concern for a password. In this system the ownership of an email account replaces the password for an account. This is more secure than a password because even with a password an account can in almost all cases be reset with access to the email associated with the account. + +LBRY has implemented a passwordless system that creates an `auth_token` for each user when an account is registered as described above. + +The login process starts from a state where the user is not logged in. This is described in the anonymous section above. From this point the user logs in by providing their email address. This triggers a call to the `internal-api/user_email/new` api. Inside the call we check if the email exists already or not. If it does and belongs to a different account, a verification token is generated and sent to the email address as a link to click. The user has 15 minutes to click the link to prove ownership of the email. This is done by passing back the sent verification token to `internal-api/user_email/confirm` via the link provided in the email. + +Once ownership is confirmed we now know that the anonymous user and the user associated with the email are the same person. At this point internal-apis merges the two users into one. This is a complex transaction in the database: + +[https://github.com/lbryio/sqlboiler/blob/master/templates/singleton/boil_queries.tpl#L23](https://github.com/lbryio/sqlboiler/blob/master/templates/singleton/boil_queries.tpl#L23) + +There are some pre-merge cleanup operations performed here: + +[https://github.com/lbryio/internal-apis/blob/84616366561e4192e9bb45781f6412e92de43de5/app/actions/shared/merge.go#L10](https://github.com/lbryio/internal-apis/blob/84616366561e4192e9bb45781f6412e92de43de5/app/actions/shared/merge.go#L10) + +## Authentication + +1. On every api call that requires authentication, the `auth_token` that is sent with api call is used to validate permissions and constraints based on scope. The `auth_token` is grabbed from the db and its scope is checked. These scopes dictate permissions and constraints. If the token is a scoped token (i.i `scope` is not `all` ) then requirements of the api are validated against the permissions and constraints approved for that scope. If not approved an authentication error is returned. + +# LBRYweb Flows v0.1 + +## Anonymous + +1. If no session is present, internal-api’s `internal-api/user/new` is called +2. Lbryweb forwards the call to internal-apis and returns back the full API response, saving `auth_token` for the current client session + +## Registration + +1. UI submits user credentials (email/password) to lbryweb +2. lbryweb calls `internal-api/user_2fa/new`with user’s email and password +3. internal-apis send the confirmation email, including a link to the lbryweb confirmation address instead of lbry.com. +4. UI starts querying `internal-api/user_email/status` +5. User clicks the link in the confirmation email, calling `lbryweb/confirm`, which forwards the data to `internal-api/user_email/confirm`and marks user as registered in the lbryweb database in case of a successful response + +## Authentication + +1. UI submits user credentials (email/password) to `lbryweb/user/auth` . +2. lbryweb calls `internal-api/user_2fa/new` providing user credentials. +3. In case of successful password authentication, UI starts querying `internal-apis/user_email/status` and an email sent with a link to lbryweb. +4. User clicks the link in the confirmation email, calling `lbryweb/user/2fa_auth` , which forwards the data to `internal-apis/user_email/confirm` and marks user as authenticated in the lbryweb database in case of a successful response. + +# Lbryweb/Internal-API Authentication Workflow + +1. Certain APIs will be protected by 2FA. For example wallet apis. A new global parameter for the password will be passed via the respective apis. If these APIs have a 2FA constraint, then it will need to pass the constraint. This constraint requires the primary email to be verified as well as the password to be authenticated. + +## List of internal-api endpoints to be implemented + +1. `internal-api/user_2fa/new` + +# Open Questions + +1. What do we do about the password resets? This could be solved with the signal SDK which allows for asynchronous key exchange. Since we are dealing with wallet data we want any password reset to be secure. The device which creates the password should create a key pair and pass the public key along with the password which internal-apis stores on init. This public key proves we are talking with with the device we created the password on. It also allows us to accept a signed password reset request without relying solely on email. This private key can be asynchronously exchanged with the other devices so the password reset can come from any registered device. + +# LBRYTV Flows v0.2 + +## Anonymous + +1. If no session is present UI calls `internal-api/user/new` and `auth_token` is retrieved +2. UI forwards `auth_token` to lbryweb, a user record is created and an account is registered with the SDK + +## Registration + +1. `internal-api/user_email/new` method is called with user’s email as an argument +2. An email with a confirmation link is sent to the user +3. UI starts querying `internal-api/user_email/status` +4. User clicks the link in the confirmation email, calling `internal-api/user_email/confirm` +5. UI sends `auth_token` to lbryweb, a user is marked as registered + +[lbrytv Authentication Spec](https://www.notion.so/lbrytv-Authentication-Spec-7ebc47ddfc524080b450057943699de9) \ No newline at end of file