On Fri, 8 Mar 2013 14:07:28 -0800
Toshio Kuratomi <a.badger(a)gmail.com> wrote:
So in the past week a bunch of us have been talking about API Keys,
OAuth, passwords, and other means of managing authn and authz in the
web apps that are up and coming (specifically mentioned were copr and
datagrepper). Puiterwijk has put in some time reading the OAuth
specifications and on Friday he walked me through how OAuth is
supposed to work. I'll give a summary of his talkl here and then we
can kick off some discussion.
...big snip...
.. note:: A client can request access to multiple resources at once.
Assuming the resource owner accepted all of them, the access token
the client receives at the end will allow access to all of those. A
client typically has one access token from an authorization server
that grants it all needed permissions on all of the resource servers
that the authorization server can give out permissions for. It is
possible for a client to have multiple access tokens with different
permissions from the same authorization server but the client would
have to keep track of which permissions were granted by which token
(and the user would have had to confirm that the client should be
granted each set of permissions).
So, if you got a token for 'build new packages in existing copr' and
later went and got a 'make new copr' token in addition to your existing
permission, you would have two tokens? Or you could ask for one new
token with both permissions? Either would be valid?
Additionally, you could get a new token for 'change toshios full name'
and get a new token for it, or a new token with it and 'build new
packages in existing copr' in the same token?
.. question:: an access token can contain permissions for multiple
resource servers. How do we secure the token from being used
maliciously by a different resource server? ie: I get an access
token which grants some permissions on both fas and bodhi. I send
that access token to fas to retrieve some information. What prevents
fas from hanging onto that token and using it to access the protected
resources on bodhi that it grants without my knowledge?
Yeah, good question.
What does a auth token look like? Just a file with encoded data? Can
you see what a token is issued by or for based on the token?
...snip...
- Resource owner password credentials: The resource owner provides
their credentials (username and password) to the client. The client
retrieves the access token from the authorization server using the
credentials. Then it discards the credentials and only keeps the
access token for further requests.
This is nasty because the client could save the username/pass and reuse
it for other things, no?
...snip...
* Verification of the access token can take many forms.
- The authorization server could notify the resource server
whenever a new access token is issued/revoked
Not sure that gets us too much.
- The resource server could ask the authorization server to verify
the token each time it receives one
- The token could be signed by the auth server and thus be
verifiable in and of itself. The token could then contain the list
of permissions so that the resource server would just consult the
token to know what was available. This should not be preferred as it
makes revoking a token harder.
Yeah.
* The authorization server may or may not know about the range of
permissions that it can grant. The resource server needs to
interpret what the permissions the access token grants mean so if the
authorization server grants a made-up permission the application
should just ignore it.
.. question:: Is it possible for the user to grant some of the
requested permissions and deny others? Or is it all or nothing?
It might be better to reject a request entirely if you can't grant all
the permissions? Otherwise is there a clear way to note only the
permissions you actually granted? ie, "Can I build new coprs and
packages in this copr" and it rejects new coprs but grants build, the
caller could be confused when it goes to try and use the token for
something that wasn't granted.
...snip...
=== Using tokens to implement sessions ===
Is this something we want to do?
* Sessions need to be short term -- expiration would need to be low
(perhaps an hour). No possibility to refresh the token. If you need
to continue, you have to re-send your username + password (+ otp?)
* We want this specific token to represent that the user is present,
not just that the client has been delegated permissions.
* It would make sense for the token to give out all permissions that
the user has (at least, on this resource server) because the user is
present. Example token permission: "*@*" permissions token
* If possible, saving this type of session token into a
wallet/keyring would make sense as that would encrypt the on-disk
representation. However, we'd also have to account for the fact that
these services might not be present.
* Suggested to have access tokens with validity of 5 minutes.
refresh tokens of 20 minutes. This would approximate our current
cookie-based idle timeout.
.. question:: Can we also have a maximum number of refreshes or
maximum time before the user has to reenter their credentials
(username + password (+otp?))
Only by expiring the token and making them get a new one I guess?
== Some proposed best practices ==
* Oauth allows for very granular permissions. You could put a
separate permission on each resource that a client can request.
However, it doesn't require that you are granular or not because the
application interprets the meaning of the permission. A lazy
resource server could have a single permission that covered anything
that can be performed on the server but this means that a stolen
token can be used to do anything that that user could do on that
resource server. We should attempt to identify common use cases and
code separate permissions for them. ie: "building a package in a
copr" would belong in a separate permission from "creating a new
copr".
Completely agreed.
* An access token should not be taken to represent the presence of
the user. It means the user has delegated permission to perform this
action to some "client". It is possible that the client is a command
line app or an api and the user is interacting with it directly but
it cannot be assunmed that this is the case.
* Following from that, changing authentication methods, password,
yubikey, security questions, etc should never be allowed via an
access token. We want the user to be present to change these
settings.
Also completely agreed.
* Tokens and sessions should not contain information about the
authentication status. They should not contain what permissions are
held or when the session expires. These are for the resource server
and authorization server to determine.
I asked about this above. Yeah, if a token can be a anonymous looking
blob I think thats best. Of course an attacker could watch how and
where you use a token, but if they obtained that from other means than
local access they may not be able to do that.
* Also following from that -- we should write things to allow for a
session to be sufficient for allowing users to perform actions.
access tokens describe a subset of the functions that the user
themselves is allowed to perform.
I guess that's assuming we replace sessions with tokens...
* Client side -- we want to have different permissions if the user
is
running the cli from the command line vs running the cli from a cron
job. A user running from the cli could be said to have a session.
Sure. But if we kept sessions and tokens seperate we could do that
too, no?
So, what are our initial use cases for this? I guess coprs is a big
one. Any other obvious ones on the map right now?
I'd like to be carefull about this, and not just convert everything,
but have a few apps that could use it written up with use cases, etc.
kevin