-
Notifications
You must be signed in to change notification settings - Fork 985
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enabling biometry without password during sync #17960
Changes from all commits
3fd7c2f
e6cea47
cd85f72
c63c80d
357ee4e
2963ece
78f7598
ec1f7b6
3ec23ae
8a8d9ab
151262f
a73e1e3
4038c83
52a7adb
da0f986
05e72d1
04d8bca
326db65
721aee0
331f2cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,16 +49,15 @@ | |
|
||
(defn save-auth-method! | ||
[key-uid method] | ||
(keychain/save-credentials | ||
(str key-uid "-auth") | ||
key-uid | ||
method | ||
#(when-not % | ||
(log/error | ||
(str "Error while saving auth method." | ||
" " | ||
"The app will continue to work normally, " | ||
"but you will have to login again next time you launch it."))))) | ||
(-> (keychain/save-credentials | ||
(str key-uid "-auth") | ||
key-uid | ||
method) | ||
(.catch (fn [err] | ||
(log/error "Failed to save auth method in the keychain" | ||
{:error err | ||
:key-uid key-uid | ||
:auth-method method}))))) | ||
|
||
(re-frame/reg-fx | ||
:keychain/save-auth-method | ||
|
@@ -79,33 +78,88 @@ | |
(if can-save? | ||
(keychain/get-credentials | ||
(str key-uid "-auth") | ||
#(callback (if % (oops/oget % "password") auth-method-none))) | ||
(fn [value] | ||
(callback (if value (oops/oget value "password") auth-method-none)))) | ||
(callback nil)))))) | ||
|
||
(defn save-user-password! | ||
[key-uid password] | ||
(keychain/save-credentials key-uid key-uid (security/safe-unmask-data password) #())) | ||
|
||
(defn get-user-password! | ||
[key-uid callback] | ||
(keychain/get-credentials key-uid | ||
(fn [value] | ||
(callback (when value | ||
(-> value | ||
(oops/oget "password") | ||
(security/mask-data))))))) | ||
|
||
(re-frame/reg-fx | ||
:keychain/get-user-password | ||
(fn [[key-uid callback]] | ||
(keychain/get-credentials | ||
key-uid | ||
#(if % (callback (security/mask-data (oops/oget % "password"))) (callback nil))))) | ||
(get-user-password! key-uid callback))) | ||
|
||
(rf/defn get-user-password | ||
[_ key-uid callback] | ||
{:keychain/get-user-password [key-uid callback]}) | ||
|
||
(defn- password-migration-key-name | ||
[key-uid] | ||
(str key-uid "-password-migration")) | ||
|
||
(defn save-password-migration! | ||
[key-uid] | ||
(-> (keychain/save-credentials | ||
(password-migration-key-name key-uid) | ||
key-uid | ||
;; NOTE: using the key-uid as the password, but we don't really care about the | ||
;; value, we only care that it's there | ||
key-uid) | ||
(.catch (fn [error] | ||
(log/error "Failed to get the keychain password migration flag" | ||
{:error error | ||
:key-uid key-uid}))))) | ||
|
||
(defn get-password-migration! | ||
[key-uid callback] | ||
(keychain/get-credentials | ||
(password-migration-key-name key-uid) | ||
(comp callback boolean))) | ||
|
||
(re-frame/reg-fx | ||
:keychain/clear-user-password | ||
(fn [key-uid] | ||
(keychain/reset-credentials (password-migration-key-name key-uid)) | ||
(keychain/reset-credentials key-uid))) | ||
|
||
(re-frame/reg-fx | ||
:keychain/save-password-and-auth-method | ||
(fn [{:keys [key-uid masked-password on-success on-error]}] | ||
(-> (save-user-password! key-uid masked-password) | ||
(.then #(save-auth-method! key-uid auth-method-biometric)) | ||
(.then #(save-password-migration! key-uid)) | ||
(.then #(when on-success (on-success))) | ||
(.catch #(when on-error (on-error %)))))) | ||
|
||
;; NOTE: migrating the plaintext password in the keychain | ||
;; with the hashed one. Added due to the sync onboarding | ||
;; flow, where the password arrives already hashed. | ||
(re-frame/reg-fx | ||
:keychain/password-hash-migration | ||
(fn [{:keys [key-uid callback] | ||
:or {callback identity}}] | ||
(-> (get-password-migration! key-uid identity) | ||
(.then (fn [migrated?] | ||
(if migrated? | ||
(callback) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If calling You can move the You may also use |
||
(-> (get-user-password! key-uid identity) | ||
(.then security/hash-masked-password) | ||
(.then #(save-user-password! key-uid %)) | ||
(.then #(save-password-migration! key-uid)) | ||
(.then callback))))) | ||
(.catch (fn [err] | ||
(log/error "Failed to migrate the keychain password" | ||
{:error err | ||
:key-uid key-uid | ||
:event :keychain/password-hash-migration})))))) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,15 +35,6 @@ | |
{:biometric/authenticate {:on-success #(rf/dispatch [:onboarding-2/biometrics-done]) | ||
:on-fail #(rf/dispatch [:onboarding-2/biometrics-fail %])}}) | ||
|
||
(rf/defn authenticate-enable-biometrics | ||
{:events [:onboarding-2/authenticate-enable-biometrics]} | ||
[{:keys [db]} password] | ||
{:db (-> db | ||
(assoc-in [:onboarding-2/profile :password] password) | ||
(assoc-in [:onboarding-2/profile :syncing?] true)) | ||
:biometric/authenticate {:on-success #(rf/dispatch [:onboarding-2/biometrics-done]) | ||
:on-fail #(rf/dispatch [:onboarding-2/biometrics-fail %])}}) | ||
|
||
(rf/defn navigate-to-enable-notifications | ||
{:events [:onboarding-2/navigate-to-enable-notifications]} | ||
[{:keys [db]}] | ||
|
@@ -154,7 +145,9 @@ | |
biometric-enabled? | ||
(assoc :keychain/save-password-and-auth-method | ||
{:key-uid key-uid | ||
:masked-password masked-password | ||
:masked-password (if syncing? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this reads a bit funny is the variable actually "masked" if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So it's masked regardless of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. seems good as is so 👍 |
||
masked-password | ||
(security/hash-masked-password masked-password)) | ||
:on-success (fn [] | ||
(if syncing? | ||
(rf/dispatch [:onboarding-2/navigate-to-enable-notifications]) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should "password" be in a private def ? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So seems like
oops
considers const vars as "dynamic values" and throws warnings at compiled time, although it shouldn't for string constants. It would work withoops/oget+
, but apparently it's slower .There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not the same, but still related, I prefer to pass keywords to
oget
because they only need to be allocated once. It's not important really, just a nano optimization, but feels more idiomatic to me 🤷🏼