1

I am implementing an OAuth2-like flow using webhooks between two webservices (no browser/user-agent involved). The authentication server will grant access based on the URL of the webhook to which the result should be returned.

It is (currently) based on the "implicit" flow - same parameters, just passed using POST request bodies instead of queries/fragments and redirects.

So the question is: which (if any) security concerns for the "implicit" OAuth flow (particularly compared to other flows) would still apply to this setup?

                                             +----------------+
                                             | Resource owner |
                                             +----------------+
                                                    ^
                                                    |
                                             (B) Approves access/scope
                                                    |
                                                    v
+--------+                                  +----------------------+
|        +----(A) Authorization Request --->|                      |
| Client |                                  | Authorization server |
|        +<---(C) Access Token Response ----|                      |
+--------+                                  +----------------------+

Steps A and C are webhooks - POST requests responded to immediately (probably with status 202 Accepted).

The parameters are taken from sections 4.2.1 and 4.2.2 of RFC 6749, except that redirect_uri is replaced by webhook_uri, and the response_type is changed from "token" to "webhook".


Here's an example request by the server at https://bar.com/ looking to obtain a token from https://foo.com/, asking for the response to be sent to https://bar.com/webhook:

POST /auth HTTP/1.1
Host: foo.com
Content-Type: application/x-www-form-urlencoded

response_type=webhook&webhook_uri=https%3A%2F%2Fbar.com%2Fwebhook
&client_id=https%3A%2F%2Fbar.com%2F&state=b2dZnjdZQdmxwvMbibS6vQ

Once approved, the response is given:

POST /webhook HTTP/1.1
Host: bar.com
Content-Type: application/x-www-form-urlencoded

access_token=...&token_type=bearer&expires_in=86400
&state=b2dZnjdZQdmxwvMbibS6vQ

(Errors are handled similarly, using parameters from section 4.2.2.1)


Notes:

  • The obvious alternative is to implement something more similar to the "authorization code" flow, where the webhook response contains an auth code which is then exchanged for an access token.
    • Assuming proper use of the state parameter (particularly that it contains a non-guessable value as per section 10.12), are there any advantages to this?
  • One of the reasons the "implicit" flow is considered less secure is that the access token is carried by the user's browser (in the fragment), and may be leaked via the browser's history, or other unexpected behaviour. Since here the token is sent server-to-server, I don't think this applies.
  • Another reason the "implicit" flow is considered problematic is that web-apps often (falsely) assume that if they end up with a valid access token for a user on a third-party site, then that they can treat that user as "logged in" on the web-app. However, if an attacker obtains an access token for a user (even one with trivial permissions, by getting the user to "log in" to the attacker's site) they can use this token to impersonate the user to the web-app.
    • Firstly, I don't think there's a way for an attacker to provide their own access tokens like that in the webhook setup. Without knowledge of state, the attacker cannot make it look as if their access token came from the authorization server. (In contrast, the browser-redirect allows the attacker to tamper with parameters/token mid-redirect, because their browser is the conduit for all the information)
    • Secondly, this weakness happens when http://bar.com/ is relying on http://foo.com/ to identify the user - instead, in the webhook model, http://bar.com/ already knows the user's identity, and is looking to use that identity on http://foo.com/'s API.
  • In other flows, the state parameter helps prevent CSRF attacks, and here it performs a similar role - allowing the client to match up outgoing requests to incoming tokens, and therefore making sure that it is not using an access token for a different user on http://foo.com/ (into which it might place sensitive information).
  • It's an interesting idea but one wonders problem this dance solves that can't be solved more simply? From a security perspective, it's probably best not to think of this in the context of OAuth2, despite this being an authorization flow modeled after the interaction. Having a client induce a server to initiate outbound requests to and process responses from potentially untrusted or compromised hosts is a completely different thing from what OAuth does. Webhook security requirements are going to be a better guide. – Jonah Benton Aug 9 '16 at 3:04
  • It's one request in each direction, and I'm not sure it can be done "more simply" - I actually didn't start with OAuth2, but my design looked very similar to above, and I realised it could precisely re-use the parameter names from OAuth2. There are also other advantages to using OAuth2, most notably that the standard continues to develop (e.g. this MAC tokens proposal). – cloudfeet Aug 9 '16 at 11:34
  • When it comes to "untrusted" hosts, it seems to me: (1) OAuth always process responses from a third-party hosts, with various degrees of trust depending on configuration, just as in this situation. Some of these requests don't even happen directly (using the user's browser as a carrier), so I don't see how this is worse. (2) whatever the authorization flow, the client server is going to end up using the provider's API afterwards - are there concerns with processing requests/responses specific to the authorization step? – cloudfeet Aug 9 '16 at 12:52
  • Sure- this is not intended as criticism, just reflection. By "simpler" I'm referring to the workflow, configuration and error handling required for an async/webhook interaction as opposed to a synchronous interaction. For instance- when calling code authenticates, it wants to do so in order to perform an authorization-required action. Instead of being able to just do that directly following a response from authentication, now it has to queue up that action to be performed following the receipt of the return call, and it has to set a timer with some kind of retry. – Jonah Benton Aug 9 '16 at 22:47
  • 1
    In terms of security, an authentication service is the trust boundary in a web ecosystem, the mechanism through which untrusted callers become trusted. If a malicious calling service issues an attempt that fails to authenticate, what is the obligation for the authentication service to inform the caller of its failure, and what additional risks does the authentication service take upon itself in connecting to the malicious caller? – Jonah Benton Aug 9 '16 at 22:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.