2

I have a REST api that accepts what are essentially anonymous survey responses, i.e., from non-authenticated users. My organization wants to allow a few (maybe 12) partners to develop client apps to collect the responses and send them to the api. I want the api to authenticate these clients, i.e., validate that the client is one of the 12 that we've authorized. I was planning to use the OAuth 2 "client credentials" flow, providing each of these clients with a unique client_id and client_secret. The client would request a token using their client_id and client_secret, and then use that token in subsequent api calls. The clients would be required to be https server-based apps that can keep the client_secret hidden -- i.e., "confidential clients" for the purposes of the OAuth2 spec (https://www.rfc-editor.org/rfc/rfc6749#page-14).

But can the client_secret really be confidential in the client credentials flow? As I understand it, the recommended way to pass the client_id and client_secret is as a base64-encoded value in the HTTP Basic auth header. If an attacker browses to that client app to submit a suryvey response, can't he just use the browser dev tool to see the base64-encoded client_id:client_secret value, decode it, and build his own app using that same client_id and client_secret?

I know I can use CORS to restrict browser-based requests to those from the 12 authorized domains. So I guess I'm really asking about non-browser attacks that try to impersonate one of the authorized clients.

So my questions:

  1. Am I right that this visible base-64 encoded version of the client_id:client_secret presents a vulnerability in a vanilla OAUth2 2-legged client credentials flow (i.e., no end-user to authorize the client)?
  2. Instead of client credentials, I'm thinking we could use a signed-token approach (probably JWT), similar to what's described here, where:
    • the client server and api server have a shared private key.
    • the client generates a token, signing it with a hash of the private key plus a timestamp. The client sends that token in the api request, along with the "request timestamp" used for the hash.
    • the api server validates the token, using the private key and the "request timestamp" to verify the hash. The server accepts only recent timestamps (e.g., within the last 2 seconds) to prevent replay attacks.
    • Does that sound like a reasonable approach?
  3. Can anyone think of another way to restrict the api to only authorized clients?
Community
  • 1
  • 1
Drewd
  • 21
  • 2
  • As far as the in transit of the HTTP Basic auth header is "protected" in HTTPS transmissions. You May be could use https://tools.ietf.org/html/draft-ietf-oauth-jwsreq-16 – jwilleke Apr 16 '18 at 12:13

0 Answers0