<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Mar 8, 2013 at 11:07 PM, Toshio Kuratomi <span dir="ltr">&lt;<a href="mailto:a.badger@gmail.com" target="_blank">a.badger@gmail.com</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">So in the past week a bunch of us have been talking about API Keys, OAuth,<br>
passwords, and other means of managing authn and authz in the web apps that<br>
are up and coming (specifically mentioned were copr and datagrepper).<br>
Puiterwijk has put in some time reading the OAuth specifications and on<br>
Friday he walked me through how OAuth is supposed to work.  I&#39;ll give a<br>
summary of his talkl here and then we can kick off some discussion.<br>
<br>
OAuth is a standardized method for a user to grant access to resources that<br>
they own to people and things that are not themselves.  Currently this is being<br>
used to allow a user to control the access to data and actions that may be<br>
performed on one web service by another web service.  The concepts and<br>
mechanisms can be used in any situation where the user wants to limit what the<br>
software they are using can do on their behalf.<br>
<br>
= Part I: What is OAuth? =<br><br></blockquote><div style>&lt;snip&gt; </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
== Flow of a basic request from start to finish ==<br>
<br>
* The client program needs to get access to a protected resource.<br>
* The client asks the authorization server for a client-id and tells the server<br>
  which permissions it needs<br>
* The authrization server gives a url to the client<br>
* The client program redirects the user to that url so the user can grant<br>
  permissions to the client<br>
* The authorization server authenticates the user (ie: they login to the<br>
  authorization server).<br>
* The authorization server asks the user to confirm they want to grant the<br>
  requested permissions to the client.<br>
* If the answer is no, the protocol ends.<br>
* If he answer is yes, the user is redirected to the client with an<br>
  `authorization code` in the request<br>
* The client sends the `authorization code` to the authorization server.<br>
* The authorization server generates an `access token` with the specific<br>
  permissions that the client requested, expires the `authorization code`, and<br>
  returns the `access token` to the client,<br>
* The client requests the protected resource from the resource server using the<br>
  `access token`.<br>
* The resource server verifes that the `access token` is valid.  If it is, it<br>
  allows access<br>
<br>
.. note:: the `authorization code` is only good for retrieving a single<br>
    `access token` for the particular set of permissions that the user<br>
    confirmed.<br>
<br>
.. note:: A client can request access to multiple resources at once.  Assuming<br>
    the resource owner accepted all of them, the access token the client<br>
    receives at the end will allow access to all of those.  A client typically<br>
    has one access token from an authorization server that grants it all needed<br>
    permissions on all of the resource servers that the authorization server<br>
    can give out permissions for.  It is possible for a client to have multiple<br>
    access tokens with different permissions from the same authorization server<br>
    but the client would have to keep track of which permissions were granted<br>
    by which token (and the user would have had to confirm that the client<br>
    should be granted each set of permissions).<br>
<br>
.. question:: an access token can contain permissions for multiple resource<br>
    servers.  How do we secure the token from being used maliciously by a<br>
    different resource server?  ie: I get an access token which grants some<br>
    permissions on both fas and bodhi.  I send that access token to fas to<br>
    retrieve some information.  What prevents fas from hanging onto that token<br>
    and using it to access the protected resources on bodhi that it grants<br>
    without my knowledge?<br>
<br></blockquote><div style>Every request send to auth server or resources server have to be signed </div><div style>with a consumer secret related to the token/access_token which mean that any other program than</div><div style>

the one which get that access token can&#39;t get through</div><div style><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
== But wait, there&#39;s more! ==<br>
<br>
We&#39;ve now seen one authorization via oauth.  But Oauth is flexible.  There&#39;s a<br>
few different ways this can work to be aware of:<br>
<br>
* Other ways to request the access token.  The example above is what works best<br>
  for third-party web clients.  However, there&#39;s other flows that might work<br>
  better for CLI apps or &quot;trusted&quot; web clients<br>
  - Implicit: user gets the access token directly from the authorization server<br>
    rather than through a authorization code.  This sortcut is useful when the<br>
    client is entirely in the browser (no third-party server involved).  With a<br>
    third party server, the authorization code makes it so the user never sees<br>
    the actual access token, only the authorization code.  if the client is<br>
    running on the user&#39;s machine anyhow, there&#39;s no sense in that step.<br>
  - Resource owner password credentials: The resource owner provides their<br>
    credentials (username and password) to the client.  The client retrieves<br>
    the access token from the authorization server using the credentials.  Then<br>
    it discards the credentials and only keeps the access token for further<br>
    requests.<br>
  - Client credentials: Just defines that if the client is the resource server,<br>
    it can authenticate itself to access its own resources... I&#39;m a little<br>
    unclear on this but I think one use would be for a resource server to use<br>
    its externally available functions (which are protected by oauth) rather<br>
    than having to write an equivalent function that is usable internally.<br>
    puiterwijk mentions a different use: having a strict separation between<br>
    tenants in the resource server&#39;s model and then having to prove you have<br>
    permission to access the resource from a different tenant (not something<br>
    we&#39;re likely to do).<br>
* Verification of the access token can take many forms.<br>
  - The authorization server could notify the resource server whenever a new<br>
    access token is issued/revoked<br>
  - The resource server could ask the authorization server to verify the token<br>
    each time it receives one<br>
  - The token could be signed by the auth server and thus be verifiable in and<br>
    of itself.  The token could then contain the list of permissions so that<br>
    the resource server would just consult the token to know what was<br>
    available.  This should not be preferred as it makes revoking a token<br>
    harder.<br>
* The authorization server may or may not know about the range of permissions<br>
  that it can grant.  The resource server needs to interpret what the<br>
  permissions the access token grants mean so if the authorization server<br>
  grants a made-up permission the application should just ignore it.<br>
<br>
.. question:: Is it possible for the user to grant some of the requested<br>
    permissions and deny others?  Or is it all or nothing?<br></blockquote><div><br></div><div style>It&#39;s all or nothing.</div><div style>It&#39;s obvious, if you deny access to requested resources, the related token get revoked.</div>

<div style><br></div><div style>We have a case at work where we have 20 tokens for one resources server.</div><div style>it&#39;s just a matter of security level/choice.</div><div style><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<br>
== Refreshing a token and its caveats ==<br>
<br>
An access token can have an expire time.  The expire time can be coupled with a<br>
second token called a refresh token.  Usually the refresh token would expire<br>
sometime after the access token would expire.  When the access token expires,<br>
the refresh token could be used by the client to request a new access token<br>
without prompting the user.  This is indended to protect against an attacker<br>
who is sniffing packets from amassing enough ciphertext from multiple uses of a<br>
single access token to be able to brute force that token.<br>
<br>
This sort of automatic expiration and refresh **is not** meant to protect the<br>
user in case the access token is copied without their knowledge (because the<br>
refresh token can be copied at the same time).<br>
<br>
= Part II: How do we use this? =<br>
<br>
This section is less about OAuth itself but some proposals about how we can<br>
best code OAuth usage in our web applications to be secure and featureful.<br>
<br>
== Session vs token ==<br>
<br>
Currently we have a concept of a session in all of our web apps.  You login.<br>
Once you&#39;re logged in, the web app knows that future connections from your web<br>
browser/CLI/etc are being made by you.  At some point the session expires or<br>
you explicitly log out.  At that point, the session is over.  The expiration<br>
time for most of our apps is currently 20 minuts of idle time but we&#39;ve talked<br>
about increasing this in the past.  Sessions in my mind should last tens of<br>
minutes to hours.  Certainly no more than a day.  A session conceptually tells<br>
the server that the user is present and interacting with the website (by saying<br>
that the user has &quot;recently&quot; authenticated).<br>
<br>
Tokens are more akin to passwords coupled with a restricted set of permissions.<br>
They&#39;re intended to be valid for days to weeks.  Refresh tokens can (but don&#39;t<br>
necessarily) be used to keep a low amount of ciphertext in the system while<br>
still making authentication via access token transparent to the client.<br>
Conceptually, they tell the server that the **client** (not user) is the same<br>
one that was granted the permissions.<br>
<br>
=== Using tokens to implement sessions ===<br>
<br>
* Sessions need to be short term -- expiration would need to be low (perhaps an<br>
  hour).  No possibility to refresh the token.  If you need to continue, you<br>
  have to re-send your username + password (+ otp?)<br>
* We want this specific token to represent that the user is present, not just<br>
  that the client has been delegated permissions.<br>
* It would make sense for the token to give out all permissions that the user<br>
  has (at least, on this resource server) because the user is present. Example<br>
  token permission: &quot;*@*&quot; permissions token<br>
* If possible, saving this type of session token into a wallet/keyring would<br>
  make sense as that would encrypt the on-disk representation.  However, we&#39;d<br>
  also have to account for the fact that these services might not be present.<br>
* Suggested to have access tokens with validity of 5 minutes.  refresh tokens<br>
  of 20 minutes.  This would approximate our current cookie-based idle timeout.<br>
<br>
.. question:: Can we also have a maximum number of refreshes or maximum time<br>
    before the user has to reenter their credentials (username + password<br>
    (+otp?))<br>
<br>
== Some proposed best practices ==<br>
<br>
* Oauth allows for very granular permissions.  You could put a separate<br>
  permission on each resource that a client can request.  However, it doesn&#39;t<br>
  require that you are granular or not because the application interprets the<br>
  meaning of the permission.  A lazy resource server could have a single<br>
  permission that covered anything that can be performed on the server but this<br>
  means that a stolen token can be used to do anything that that user could do<br>
  on that resource server.  We should attempt to identify common use cases and<br>
  code separate permissions for them.  ie: &quot;building a package in a copr&quot; would<br>
  belong in a separate permission from &quot;creating a new copr&quot;.<br></blockquote><div><br></div><div style>I&#39;m definitively +1 on this one.</div><div style> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<br>
* An access token should not be taken to represent the presence of the user.<br>
  It means the user has delegated permission to perform this action to some<br>
  &quot;client&quot;.  It is possible that the client is a command line app or an api and<br>
  the user is interacting with it directly but it cannot be assunmed that this<br>
  is the case.<br></blockquote><div><br></div><div style>+1 Also, all allowed access should be revoke-able by the user at any time.</div><div style> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<br>
* Following from that, changing authentication methods, password, yubikey,<br>
  security questions, etc should never be allowed via an access token.  We want<br>
  the user to be present to change these settings.<br>
<br></blockquote><div style>+1</div><div style><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
* Tokens and sessions should not contain information about the authentication<br>
  status.  They should not contain what permissions are held or when the<br>
  session expires.  These are for the resource server and authorization server<br>
  to determine.<br></blockquote><div> </div><div style>Yeah, that&#39;s the resource sever which actually defines what third-parties are allowed to</div><div style>to get from it even if token is granted.</div><div style>

<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
* Also following from that -- we should write things to allow for a session to<br>
  be sufficient for allowing users to perform actions.  access tokens describe<br>
  a subset of the functions that the user themselves is allowed to perform.<br>
<br>
* Client side -- we want to have different permissions if the user is running<br>
  the cli from the command line vs running the cli from a cron job.  A user<br>
  running from the cli could be said to have a session.<br>
<br></blockquote><div style>Hmm... I&#39;m not sure we can really prevent user from running the exact same cmd-line from a terminal</div><div style>to a cron tab.</div><div style>Unless having strong policies on user/admin&#39;s operation. SOP!</div>

<div style><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
IRC log (since this is all paraphrased and I could have misunderstood what puiterwijk meant):<br>
<br>
<a href="http://toshio.fedorapeople.org/puiterwijk-oauth.html" target="_blank">http://toshio.fedorapeople.org/puiterwijk-oauth.html</a><br>
<span class="HOEnZb"><font color="#888888"><br></font></span></blockquote></div><br clear="all"><div><br></div>-- <br>Xavier <br><br><br></div></div>