Page MenuHomePhabricator

API Portal: Document security best practices
Open, Needs TriagePublic

Description

Draft guidance for developers on how to manage OAuth secrets and app confidentiality, including guidance for mobile and desktop apps.

Client confidentiality

When creating a client, the OAuth extension supports a checkbox for "Client is confidential: A confidential client is an application that is capable of keeping a client password confidential to the world. Non-confidential clients are less secure". For the API Portal, our current working copy for this checkbox is: "I can keep my app credentials secure" with a link out to a documentation page.

From the backend perspective, this is a purely self-reported field. There's no way for the extension to know whether the credentials are actually secure or not. If a user doesn't check the box, two things happen:

  1. When using the authorization code flow, the client must use a PKCE code challenge[1] and the client credentials are not evaluated when exchanging an authorization code for an access token[2].
  2. The client cannot use the client credentials flow[3].

Notes:

  • From Reedy: It might be best having something more wordy; making it explicit that we expect some action in case of suspected compromise/breach/poor handling etc. And making it explicit (on the page) what difference checking it or not makes.
  • From Dejan: Actually, this was something that stood out to me as weird when implementing OAuth2.0. If you cannot keep your secret secure (client not confidential) Oauth says: "Ok, then i just wont check the secret", and grant you full functionality. PKCE CC is required, that is true, but that does not do much in the matter of security

Drafts for Create App flow:
"I agree to follow [[security best practices]] for key management. If I have reason to believe that the key may have been compromised, I also agree to revoke that key and replace it"

Guidance for mobile and desktop apps

From OAuth for Developers, "The application secret must be kept secret. Submitting it to source control or putting it into user-accessible code (such as mobile app or desktop application; even if it is obfuscated) undermines the security model and will result in admins forcefully disabling the application. Exceptions are made for example applications demoing OAuth usage, if they are explicitly labeled as such and request limited rights."

See also: T255370

Comparison of app types and OAuth flows
app typeauthorization code flowclient credentials flowowner-only authorization flow
confidentialallowedallowedallowed
publicallowed with PKCEnot allowednot allowed

confidential: "Clients capable of maintaining the confidentiality of their credentials (e.g., client implemented on a secure server with restricted access to the client credentials), or capable of secure client authentication using other means."(ref) Example: web server app

public: "Clients incapable of maintaining the confidentiality of their credentials (e.g., clients executing on the device used by the resource owner, such as an installed native application or a web browser-based application), and incapable of secure client authentication via any other means.”(ref) Examples: installed applications (mobile or desktop), client-side (JavaScript) applications

public + authorization code flow: As recommended by RFC 8252, the OAuth extension requires public clients to use a PKCE as part of the auth process. In addition, the RFC recommends that public apps open the authorization request in the system browser and use a redirect URI that returns the authorization response back to the app. We can easily include these best practices in the API Portal docs.

public + client credentials flow: If the client is marked as public during creation, the OAuth extension prohibits the client from using the client credentials flow. However, I can see a possible need for this use case. For example: a mobile-app developer might want to incorporate content from Wikimedia into their app, but they don't want their users to have to go through the Wikimedia authorization process just to see that content. The only option I see for these use cases (short of advising them to call the API without OAuth) is to ask them to re-architect their apps so that the app communicates with a server that they control, making it a confidential client. How much friction does it cause to make this recommendation? What percentage of API Portal developers fall into this use case?

public + owner-only authorization flow: This would be a bot running on a public client, which seems like an odd choice. Is there any chance someone would want to do this?

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald TranscriptMay 18 2020, 8:56 PM
apaskulin renamed this task from Define security best practices to API Portal: Document security best practices.Jun 15 2020, 8:31 PM
apaskulin updated the task description. (Show Details)Jun 30 2020, 12:05 AM
apaskulin updated the task description. (Show Details)Jun 30 2020, 3:42 PM
apaskulin updated the task description. (Show Details)Jul 14 2020, 12:43 AM
apaskulin awarded a token.
apaskulin updated the task description. (Show Details)Jul 14 2020, 6:36 PM
apaskulin updated the task description. (Show Details)
apaskulin updated the task description. (Show Details)Jul 17 2020, 7:55 PM

@eprodromou, Can you provide feedback on the last section of the task description? Specifically the questions under public + client credentials flow and public + owner-only authorization flow? Thanks!

The only option I see for these use cases (short of advising them to call the API without OAuth) is to ask them to re-architect their apps so that the app communicates with a server that they control, making it a confidential client. How much friction does it cause to make this recommendation? What percentage of API Portal developers fall into this use case?

I don't think this is an unreasonable expectation to make of developers and it's a fairly common pattern. I can't see what else we would advise in this situation that wouldn't run the risk of credentials open to being extracted and reused elsewhere.

A few notes:

It's probably worth noting what typical non-confidential clients are. A common example is browser-only Web apps. Some other examples that are worth noting:

  • For Open Source apps, the typical flow is to include the API key at build time for the "official" build. If that's not possible, another workaround that many Open Source apps use for API keys is to have the end user register for their own API key and add it to the app in a config file or a settings dialog box. (Long-term, it would be cool to automate this.)
  • For mobile apps, the standard technique is to use the secure storage available in the OS for maintaining keys.

I think in general we'll be less likely to give higher privileges (like higher rate limits, for example) to non-confidential API keys.

Thanks, @eprodromou! A few clarifying questions:

For Open Source apps, the typical flow is to include the API key at build time for the "official" build.

I'm not 100% sure what you're referring to here. Is this the standard process of storing config variables as part of the deployment process to keep it out of the source code?

If that's not possible, another workaround that many Open Source apps use for API keys is to have the end user register for their own API key and add it to the app in a config file or a settings dialog box. (Long-term, it would be cool to automate this.)

Can you clarify this? Who is the "end user" in this case?

For mobile apps, the standard technique is to use the secure storage available in the OS for maintaining keys.

In my research, I wasn't able to find a section in the OAuth docs that calls this method out as safe for storing client secrets. Do you have a link?

Thanks, @eprodromou! A few clarifying questions:

For Open Source apps, the typical flow is to include the API key at build time for the "official" build.

I'm not 100% sure what you're referring to here. Is this the standard process of storing config variables as part of the deployment process to keep it out of the source code?

Yeah, that's it.

If that's not possible, another workaround that many Open Source apps use for API keys is to have the end user register for their own API key and add it to the app in a config file or a settings dialog box. (Long-term, it would be cool to automate this.)

Can you clarify this? Who is the "end user" in this case?

If the app is, say, a KDE desktop tool for editing Wikivoyage, the end user would be the person editing.

For mobile apps, the standard technique is to use the secure storage available in the OS for maintaining keys.

In my research, I wasn't able to find a section in the OAuth docs that calls this method out as safe for storing client secrets. Do you have a link?

I don't! I talked to folks in the OAuth community, and that secure storage is only useful for when you're using SSL certificates as your authentication mechanism; it's a really obscure mechanism that nobody does.

When I asked Aaron Parecki, he told me "Android and iOS have secure storage APIs for storing stuff, but it's only secure if the data gets there in a secure way. Generating certificates or secrets within the app is fine for example. Just can't rely on client secrets in mobile apps in OAuth for anything really."

So I think saying that mobile apps and other native apps should be treated as non-confidential, without a client secret, is the way to go.

apaskulin added a comment.EditedAug 21 2020, 11:05 PM

Now that we've got a good understanding of the different app types and flows, I've put together some mockups for creating and managing apps in the API Portal with the goal of making these differences easy to understand and navigate. I'd love to get as much feedback as possible on these, especially around making the terminology as clear as possible. Feel free to make comments on the drawing or leave comments on this task.

Review from @eprodromou is complete. Thanks, Evan!

I've opted not to implement the changes to the form shown in the mockups in favor of more limited copy changes. Here's the comparison of before and after the changes implemented in my upcoming patch:

Change 632521 had a related patch set uploaded (by Alex Paskulin; owner: Alex Paskulin):
[mediawiki/extensions/WikimediaApiPortalOAuth@master] ui: Update copy and styles on create client form

https://gerrit.wikimedia.org/r/632521

Change 632521 merged by jenkins-bot:
[mediawiki/extensions/WikimediaApiPortalOAuth@master] ui: Update copy and styles on create client form

https://gerrit.wikimedia.org/r/632521

apaskulin moved this task from Backlog to Content on the API-Portal board.Fri, Jan 8, 12:51 AM