cakephp – Using Access Tokens with JavaScript in OAuth2

cakephp – Using Access Tokens with JavaScript in OAuth2

1. How to keep your users from having to log in on every request

Nobody forces you to issue refresh tokens, or to expire access tokens on every request. If you issue an access token that is valid for an hour or two, that should be enough time for a user to use the website without allowing the sort of endless refresh chain refresh tokens offer (as typically using a refresh token will result in both a new access and refresh token being issued). Choose an expiration period that will allow for the typical user action period, allow some extra, and you can avoid issuing refresh tokens altogether.

Of course, there is some risk that a user will exceed that time span and be forced to log in again. I think usually if that happens, if it is explained to them that it happens for security reasons and what happened in easy, non-technical terms, they will be okay with that. In the end, its always a trade-off between best security and best usability: better usability would be using refresh tokens, obviously – your users will never be forced to re-login while theyre using the page – but if you do, you have to live with there being a risk of them becoming compromised.

Local storage is protected by a same origin policy, so its about as secure as anything the browser has to offer for storing things. Personally, I like the idea of using a session cookie for storing the tokens – it works across browser tabs, gets cleared when the browser is closed and when the user manually clears their cookies, they get the expected behavior of being forgotten by your page (which they wont with browser local/session storage). If you do this, make sure to use a secure only cookie. Setting the cookie path to a non-existent value will keep it from being transmitted on every request, although this is purely a message size consideration, as it will get transmitted on every request anyways (in the Authorization header). Whatever storage type you use, you are always susceptible to XSS attacks, so make very sure to guard well against it.

My point in a nutshell: Youre not required to issue refresh tokens or expire access tokens on every request. If you want to avoid using refresh tokens, make your access tokens live longer – but youll have to live with there being a chance that users will have to re-authenticate while using your website.

2. Use of the Implicit flow over the Resource Owner Password Credentials flow

The reason that youre discouraged from using the Resource Owner Password Credentials flow normally is because it forces the user to expose their credentials for another identity provider that youre using to authenticate them. I.e. if youre allowing your users to sign in using their Google/Facebook, you shouldnt use that flow because the user would have to give their username and password to your app/website, and you could do all kinds of shenanigans with them.

Since you on the other hand, from how I understand your question, have your own OAuth2 server up and running, youre your own identity provider – you already have access to the users credentials (user name and hashed password), so avoiding the resource owner flow has no additional security benefits. RFC 6749 actually does not specify a client id and secret be used for this flow (and it would not make much sense, either), hence, no need to protect what you dont have to supply.

My point in a nutshell: Because you are your own identity provider using the Resource Owner Password Credentials flow is okay. You dont need a client id and/or secret for this. The Autorization Grant flow and Implicit flow are meant for when you authenticate against a different identity provider (such as Google or Facebook)

3. To keep or not to keep token based authentication

The probably most commonly used authentication mechanism is still session based, i.e. the server, when you have logged in, issues you a session id by which it keeps track of the fact that youve successfully authenticated. Typically this session id gets stored as a cookie. The beauty is that you have pretty much no implementation concerns – set the cookie, and the browser will handle pretty much all the nitty gritty details for you. On the server, all you have to do is check that the session is valid. However, this mechanism is still susceptible to XSS attacks, and, worse, to XSRF (cross-site request forgery). While not impossible to guard against, it is a bit of a pain to detect and prevent this from happening. With a token based authentication system, you get XSRF protection built-in.

My point in a nutshell: Since you already have an OAuth2 server up and running, I would stick with it. If you go with the Resource Owner Password Credentials flow, there is no need for client id and secret to be used.

  1. Refresh tokens are optional for the flow type you are using. You can use the password flow when required to obtain another acesss token and dispense with refresh tokens.
  2. The resource owner grant type is the right flow type for your case since it is your client using your oauth server. The use of client ids is not required or meaningful since your client is a browser based client. To get a feel for it, Imagine you were instead using a third party oauth server, it would be their browser client code asking for the password or checking some cookie or localstorage state. The dirty work of asking the user to authorise the action and provide their username and password has to be done somewhere and since in your case its not a third party, its your oauth server and web client doing the asking its unavoidable and must be done.
  3. Stick with the resource owner grant type which yields an access token. Its up to you if you want to actually store this in localStorage, it wont be as user friendly and will require a relogin every time a hard page refresh is done but it is more secure if you are concerned about tokens being accessible on the client. Although an attacker with that level of access to the client can mount many other attacks so keep it in perspective.

cakephp – Using Access Tokens with JavaScript in OAuth2

In order to get a refresh token you need to use the code flow, not the implicit grant flow.

You cannot securely refresh a token in the implicit flow.

Obviously you can implement the authorization code flow in the client (i.e – as if it were a server), but that causes 2 problems:

1) If your IDP (Identity Provider) is in another domain than your client, your browser will prevent you from making HTTP calls to generate tokens from the user generated code (or using the refresh_token).

2) Your client secret will be available from inside the client – a security flaw. The refresh token will also be available – another security flaw.

In a nutshell – there cannot be a seamless refresh experience when using the implicit oAuth flow.

Leave a Reply

Your email address will not be published. Required fields are marked *