oauth-2.0authorizationaccess-tokenclientcredential

Using OAuth client credentials to request access-token for user's resources


Our service uses OAuth to issue refresh-tokens that 3rd-party applications can later use to access users' resources without the presence of the user (server to server). We currently use Authorization Code flow and require the apps' developers to store refresh tokens per each user on their side, and use the refresh token to generate a short-lived access token that they can then use to access the user's resources. This works fine.

However, implementing this flow isn't easy for app developers. They have to implement all required redirects, and store many tokens securely on their side.

I'm trying to understand if the following approach has any security or other flaws that I miss:

  1. After the user's consent to install the app, our authorization server will store the fact that the specific permissions were granted by the user.
  2. The UI will redirect to a provided URL, so the app has a chance to ask the user to login or create an account. However, there will be no need for the app to store refresh token.
  3. The app will have to store the fact that a user's account on their side is connected to a user's account on our side.
  4. When the app wants to make a server-to-server request to our service, they will use client-credentials in order to authenticate itself, and will request a short-lived access-token scoped to the user's account resources. This is equivalent to using the refresh-token in the existing authorization code flow.
  5. The authorization server will check its records to decide if such access-token may be provided, and return it to the client.
  6. The client will call the resource server using the access-token just as it does today.

Basically this approach eliminates the need to manage refresh tokens by the clients, and the need to implement all the different redirects implied by oauth. In addition, it allows tokens revocation very easily, because all grant-consents are stored on the authorization server.

Do I miss anything? Any reason not to use this approach?

Note: This question is similar, but it asks about an internal super-powered app.


Solution

  • I would advise against this approach. There really isn't any benefit, and it's extremely risky to try and invent your own security process rather than something that's an established standard with countless people using and evaluating it.

    The motivation is completely understandable. The devs are struggling with oauth because everyone does. But things like redirects are intentionally put in place for security.

    There are several things here that will put your security at greater risk.

    There is no user in a client credentials flow. The client authenticates with the authorization server and then gets a token back.

    In step 1, you've opened up the attack vector significantly by not requiring the user to re-auth. You've essentially created an unexpiring refresh or access token (except for requiring the client to authenticate rather than just being the bearer of a token). And storing this info binds the user with the client id. If anyone else happens to use the app, there'll be no way for you to know.

    Refresh tokens are a convenience to avoid asking the user to re-auth. You've still got the same number of redirects in your approach. In step 3, you've only traded out one thing for another. They have to store this info.

    There are a few other things, but even if this did look solid without any holes, you're not getting the benefit of a large community continuously testing and updating it when any vulnerabilities are discovered. And the attack landscape is constantly evolving.