I'm currently experimenting with OAuth2 to develop a fully JavaScript mobile application that speaks with the CakePHP API. Take a look at the following code to see how my application currently looks (note that this is an experiment, therefore, messy code and lack of structure in areas, etc.)
var access_token, refresh_token; var App = { init: function() { $(document).ready(function(){ Users.checkAuthenticated(); }); }(), splash: function() { var contentLogin = '<input id="Username" type="text"> <input id="Password" type="password"> <button id="login">Log in</button>'; $('#app').html(contentLogin); }, home: function() { var contentHome = '<h1>Welcome</h1> <a id="logout">Log out</a>'; $('#app').html(contentHome); } }; var Users = { init: function(){ $(document).ready(function() { $('#login').live('click', function(e){ e.preventDefault(); Users.login(); }); $('#logout').live('click', function(e){ e.preventDefault(); Users.logout(); }); }); }(), checkAuthenticated: function() { access_token = window.localStorage.getItem('access_token'); if( access_token == null ) { App.splash(); } else { Users.checkTokenValid(access_token); } }, checkTokenValid: function(access_token){ $.ajax({ type: 'GET', url: 'http://domain.com/api/oauth/userinfo', data: { access_token: access_token }, dataType: 'jsonp', success: function(data) { console.log('success'); if( data.error ) { refresh_token = window.localStorage.getItem('refresh_token'); if( refresh_token == null ) { App.splash(); } else { Users.refreshToken(refresh_token); } } else { App.home(); } }, error: function(a,b,c) { console.log('error'); console.log(a,b,c); refresh_token = window.localStorage.getItem('refresh_token'); if( refresh_token == null ) { App.splash(); } else { Users.refreshToken(refresh_token); } } }); }, refreshToken: function(refreshToken){ $.ajax({ type: 'GET', url: 'http://domain.com/api/oauth/token', data: { grant_type: 'refresh_token', refresh_token: refreshToken, client_id: 'NTEzN2FjNzZlYzU4ZGM2' }, dataType: 'jsonp', success: function(data) { if( data.error ) { alert(data.error); } else { window.localStorage.setItem('access_token', data.access_token); window.localStorage.setItem('refresh_token', data.refresh_token); access_token = window.localStorage.getItem('access_token'); refresh_token = window.localStorage.getItem('refresh_token'); App.home(); } }, error: function(a,b,c) { console.log(a,b,c); } }); }, login: function() { $.ajax({ type: 'GET', url: 'http://domain.com/api/oauth/token', data: { grant_type: 'password', username: $('#Username').val(), password: $('#Password').val(), client_id: 'NTEzN2FjNzZlYzU4ZGM2' }, dataType: 'jsonp', success: function(data) { if( data.error ) { alert(data.error); } else { window.localStorage.setItem('access_token', data.access_token); window.localStorage.setItem('refresh_token', data.refresh_token); access_token = window.localStorage.getItem('access_token'); refresh_token = window.localStorage.getItem('refresh_token'); App.home(); } }, error: function(a,b,c) { console.log(a,b,c); } }); }, logout: function() { localStorage.removeItem('access_token'); localStorage.removeItem('refresh_token'); access_token = window.localStorage.getItem('access_token'); refresh_token = window.localStorage.getItem('refresh_token'); App.splash(); } };
I have a number of questions related to my OAuth implementation:
1.) Apparently, storing access_token in localStorage is bad practice and I should use cookies instead. Can anyone explain why? Since this is not more secure or less secure, as far as I can tell, since the cookie data will not be encrypted.
UPDATE: In accordance with this question: Local storage and cookies storing data in localStorage is ONLY available on the client side and does not make any HTTP request, unlike cookies, it seems to me more secure, or at least for me that's no problem at all!
2.) Regarding question 1, using a cookie for the expiration will be equally meaningless to me, as if you looked at the code, the application will start asking for information about the user, which will return an error if it expired on the server and requires refresh_token . Therefore, Iโm not sure about the benefits of expiration time on the BOTH client and server when the server really matters.
3.) How do I get the update token, without A, storing it with the original access_token for later use, and B) also storing the client_id? I was told that this is a security issue, but how can I use them later, but protect them in a JS application? Review the above code again to find out how I have done so far.