5

I am trying to implement a system for third-party apps to access data that a user stores on a provider. We have a robust access control system, with separate read/write/etc. levels for each "stream" of data published by a user. Inside our website, these access levels are already enforced depending on which user is trying to do which action with another user's stream.

Now comes time to allow third-party apps to do the same, in an oAuth2-compatible way. We currently represent third-party apps inside the provider app database as regular users with a user id, canonical url, etc. So this user id would be the client_id of the app.

My question is, why does oAuth have tokens at all, which are essentially opaque strings that map to (user_id, client_id) records that have (scope, etc)?

Can't the app simply identify itself with the client_id as its api key and sign its requests with a symmetric secret, for server-to-server requests? These signed requests and responses can be relayed through a user agent if need be, if there is an additional requirement that a user be online when the request is granted.

The provider already stores the access records for the (user_id, client_id) so it knows whether to approve or deny a request from the client app. Why does the client app need to store and spit back extra tokens?

The only thing I have come up with so far is maybe this is to increase the security in case someone gets unauthorized access to the client app's symmetric secret. And this way the attack would be limited to whatever tokens they would be able to get (since the tokens are required as an additional credential). Seems that on the server side, if someone gets the symmetric secret, they probably also get the database credentials as well. So this isn't much of a plus.

Is there any other reason? Or was it just security theater?

1 Answers1

6

maybe this is to increase the security in case someone gets unauthorized access to the client app's symmetric secret.

That's one valid reason, yes. Sending around short-lived access tokens instead of long-lived shared secrets reduces the attack surface.

Is there any other reason?

OAuth defines several roles. Often a resource doesn't reside on the same server that handles authentication and/or authorization. An access token can be generated by one service and be consumed by another that doesn't actually know anything about who has authorization to what. A resource server might not know which users have access to what resources, but being given a valid access token by an authorization server, it can make a decision about granting access.

Think about access control in a building (or at the border of a country) - the guard at the entrance might not have a list of every person allowed inside and might never have seen you before; but if you show him a valid access card for the restricted area (or passport in the country example), he'll know he's supposed to let you in.

This has a few downsides as well. If access is revoked, but you can retain your access card, chances are you'll still get inside even if you aren't supposed to anymore. This can be countered by putting an expiration date on the access card, and this is why access tokens are usually short-lived, so that even if they're stolen, they can't be used for very long.

Out of Band
  • 9,150
  • 1
  • 21
  • 30
  • A followup question, though: how would the resource server know, from an opaque access token, whether a certain client_id is authorized to access some resource owned by some user -- unless it performa a lookup! So that lookip needs to be performed anyway for each request. In most implementations the access token isn't a data structure that contains the resource id and the permission, signed with an hmac. It's just an opaque token. – Gregory Magarshak Jun 11 '17 at 19:41
  • 1
    Hmmm. With id tokens, the tokens aren't actually opaque; you can look inside them to get information about the user it was issued for if you want to (or you can call an endpoint to do it for you). If your access token actually *is* just a random string, then you'll have to do an extra lookup just like you say. But I was under the impression that while OAuth access tokens are opaque to the client, they're not necessarily opaque to the resource server. So the design of OAuth (using tokens) would allow systems to be designed that don't need that extra lookup. – Out of Band Jun 11 '17 at 19:58
  • So what would you say the oAuth token contains, if it's not opaque to the server? The ids of all the approved resources, the client_id and cryptographic signature? So anyone who forges this signature can access the resources. – Gregory Magarshak Jun 11 '17 at 21:50
  • 1
    At the very least, a scope defining the extend of allowed access, an identifier which identifies the subject of the scope (e.g. the URL of the resource server), and an expiration time, and possibly a nonce, all of it digitally signed using asymmetric cryptography. Yes, anyone who forges the signature can get access, but forging a signature would involve knowing the private key of the service which minted the access token. – Out of Band Jun 12 '17 at 16:52
  • I just researched some more and it turns out access tokens lead to a lot of security vulnerabilities for the users, who can't be sure of what the providers are doing. For example these two, which could easily be avoided if we just stuck to API keys to identify clients and the server did the permission lookups with that client id for the resources it is requesting: http://homakov.blogspot.com/2012/08/oauth2-one-accesstoken-to-rule-them-all.html – Gregory Magarshak Jun 23 '17 at 22:42
  • And even the oAuth 2 spec says so: https://tools.ietf.org/html/rfc6749#section-10.16 – Gregory Magarshak Jun 24 '17 at 00:39
  • You're pointing out an authentication problem. OAuth isn't really designed for authentication. This is what Open ID Connect is there to solve (by adding additional security measures - translating to several more fields in the involved tokens and a somewhat more complicated flow (IMO)) – Out of Band Jun 24 '17 at 07:02