Should I save passwords in shared web credentials AND (local) keychain
Asked Answered
R

1

12

I am in the process to design a login for a new app that will be associated with a domain, i.e. be the counterpart to an SPA. Obviously I want to use

  • iOS 11 Password Autofill, and
  • Shared Web Credentials

I have read the documentation on autofill as well as watched the WWDC video about it. Also, I checked the article on Shared Web credentials, which I think is older than the new, reworked autofill. Said article recommends:

Do not use the shared web credentials as your primary storage for secure user credentials. Instead, save the user’s credentials in the keychain, and only use the shared web credentials when you can’t find the login credentials in the keychain.

This strikes me a little odd, because it - Means I have to cover more possible inconsistencies, i.e. synchronize the keychain somehow wit the shared web credentials (what if I have credentials in the keychain as well as the shared web credentials, but they're different?) - Potentially leaves "garbage" behind in the keychain if my user user uninstalls my app (naturally I hope they won't ever do this, but let's be realistic, some will)

Especially the last point had always bothered me in the past (before shared web credentials and autofill were a thing, or when my app doesn't have an associated domain). Unlike on macOS, the iOS Accounts & Passwords feature (in the Settings app) doesn't list ALL passwords, but only the ones used by Safari (i.e. the shared web credentials), correct? Keychain Access on macOS instead offers a means to view and manage all credentials, even those that aren't synchronized over iCloud.

I understand why the same is not offered on iOS, but it also means that for those passwords that my app saves (locally) to "its" keychain "part" can only be managed if I offer a UI for this in my app. And if the user uninstalls the app before using this, the item will stay in the keychain, at least it was that way when I tried it a couple of years ago.

My main question now is, wouldn't it be easier to disregard the article's advice and only rely on the shared web credentials for password storage? That's the part they can edit in Settings (if ever need be) and also it will reflect any password changes done on the website. I would design my app like this then:

  • First launch: App starts on the Login screen and offers the username/password via Autofill
  • User logs in: App saves a simple flag in the shared user defaults indicating the user is logged in.
  • App gets relaunched, e.g. after a device reboot: The app skips the login screen due to the flag and gets the password and user name from the shared web credentials (assuming the user previously granted it permission, of course)
  • User explicitly logs out: The app deletes the flag, basically setting everything back to first launch
  • User deletes the username and password from the shared web credentials (e.g. in the Settings app or with Keychain Access on macOS): The app falls back to the login screen as soon as it detects this (e.g. when attempting a remote request, or after relaunch), regardless of the flag. I think this matches the user intention best (if you delete a password you don't want some apps to hold onto it until you log them out)

This setup would avoid any issues with different items in the keychain and shared web storage and it would immediately propagate updates done in the webpage to the app as well (which is what I'd intent for my app anyways). Is there anything that would keep this app flow from working?

(Note: I asked the same question on the apple developer forums, so if you see that as well don't be confused. I will update any potential answers from there to here and vice versa.)


Edit to address @Aaron's answer:

Thank you so much for the info. Your answer helped me realize I misunderstood something about shared web credentials: I assumed that for an app with associated domain, you can access the credentials without user interaction (after perhaps an initial authorization). Like you can set the checkbox on macOS when an application requests credentials. I now realize this is wrong and on iOS you would always have to verify with the user, thanks.

For completeness sake, I still want to point out some of the other things you said:

  • You are right, we will eventually use token based authentication, so I will save that in the keychain (probably in addition to the password, see below). I just tried to keep the question simple enough at first.
  • Our app is like an email client where you update new incoming "mail". The mentioned "login flag" in something like the user defaults would thus just indicate whether the app should behave as if subscribed to an inbox or not. Like in Mail, you wouldn't expect to have to login even after relaunch.
  • For this reason I will probably eventually save the user's password in the (local) keychain along with a token. If the token expires, I can request a new one without user interaction, that's important in our general site and app design. Only if that request fails I would use the shared web credentials (updating my local copy of the creds in the process).
  • For what it's worth, the last point you mentioned is probably debatable. On macOS, for example (where you can edit the entire keychain, not just Safari passwords) de facto logs you out of an app. Mail, again, as an example. If the keychain item for an inbox is gone, Mail re-asks that the next time it is launched and tries to access the content (effectively a "kind of" login in a way).

Again, thank you a lot for answering, now I can close an open todo. :) Also thanks to @HamZa for giving out a bounty!

Rosendorosene answered 30/1, 2018 at 8:49 Comment(4)
I would say this question is quite interesting, yet it's opinion-based. It's not easy for average users to manage saved password via this mechanism. In my opinion, I think this mechanism is excellent for users. If I were you, I will follow the article's advice as best practice, but be sure to explain to your user how they can manage their saved credentials.Defiant
Thanks for the comment. Whether the app flow I sketched is the best is opinion-based, yes. But the actual core question is whether you have to save credentials in the (app's) keychain as well for a technical reason (shared web credentials not reliable, caching, permissions). Also, I am not sure which mechanism you mean is excellent, the one I propose or the one explained in the article. Note that the latter doesn't mention how to manage the (keychain) passwords. Most apps simply never manage that, leaving behind garbage on uninstall. Users don't realize, but that's not excellent imo. :)Rosendorosene
Did you ever get a response to this on the App dev forums? If so, do you mind posting the answer?Interpellation
Very unfortunately I haven't. This is still an open issue for me, but for now I rely on the Keychain only as a first WIP step. If I don't get an answer from Apple or some experience tale from another dev I will probably adhere to the Apple documentation and save the credentials as recommended. I might also spend our "Apple inquiry" for this year on it if nothing else comes up. I have a reminder on my machine so once I have an update I will post it here as well.Rosendorosene
L
8

Considering this advice:

Do not use the shared web credentials as your primary storage for secure user credentials. Instead, save the user’s credentials in the keychain, and only use the shared web credentials when you can’t find the login credentials in the keychain.

The main issue here is that the shared web credentials process is a little clunky — it requires user interaction and takes time to resolve the credentials. So if the user has already authenticated with your app you want to avoid showing them the login page at all. You can do this by storing credentials in your app's keychain where you can access them immediately without a network connection or user permission.

This doesn't mean you need to store the user's password in the keychain. Typically you would store something like an OAuth access token in the keychain. The presence of this token means the user is authenticated - and if an API endpoint rejects your token then you can take them back to the login page.

This suggestion:

User logs in: App saves a simple flag in the shared user defaults indicating the user is logged in.

is possibly insecure depending on what you're hiding behind the login page, but typically any content belonging to the user should require a valid token to access, not just a bool in the user defaults.


I think this matches the user intention best (if you delete a password you don't want some apps to hold onto it until you log them out)

I disagree with this; I would not expect an iOS app to log out because I deleted a password from my Safari keychain.

Leptophyllous answered 6/6, 2018 at 21:35 Comment(1)
Thanks for this. I felt the need (well, "urge") to reply to some of your points, so I edited the question. That does not change the validity of your answer, of course, so I accepted. Cheers!Rosendorosene

© 2022 - 2024 — McMap. All rights reserved.