Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Security on Single Page Application (JakartaJS Apr 2014)

Security on Single Page Application (JakartaJS Apr 2014)

Giovanni Sakti

April 30, 2014
Tweet

More Decks by Giovanni Sakti

Other Decks in Programming

Transcript

  1. 1. SPA Characteristic 2. SPA and API Server 3. Securing

    Client-Side Codes 4. Authentication 5. Authorization 6. Determine Your Needs
  2. Http Request Http Request Client API Server Have to be

    secured Have to be secured Have to be secured
  3. …function(){app.service(“Session”,["sessionStore","UserSession",function(a,b) {return this.signedIn=!!window.sessionStorage.getItem(a),this.signedOut=! this.signedIn,this.signedIn? (this.currentUser=JSON.parse(window.sessionStorage.getItem(a)).data,this.user Session=new b({login:this.currentUser.username,password:"",remember_me:! 1,auth_token:this.currentUser.authentication_token})): (this.currentUser=null,this.userSession=new b({login:"",password:"",remember_me:!

    1,auth_token:""})),this.putSessionData=function(c){return window.sessionStorage.setItem(a,JSON.stringify(c)),this.signedIn=! 0,this.signedOut=!this.signedIn,this.currentUser=c.data,this.userSession=new b({login:c.data.username,password:"",remember_me:! 1,auth_token:c.data.authentication_token}) },this.removeSessionData=function(){return window.sessionStorage.removeItem(a),this.signedIn=!1,this.signedOut=! this.signedIn,this.currentUser=null,this.userSession=new b({login:””,password:”",remember_me:! 1,auth_token:""})},this}])}.call(this),function(){app.constant("apiHost"... https://github.com/mishoo/UglifyJS
  4. ‘Normal’ web app Send login & password Track States Track

    session, return cookies Http request, put cookie in request header Return HTML
  5. SPA Track States Http request, send login & password Return

    JSON Http request, send login & password Return JSON
  6. SPA Track States Http request, send login & password Return

    JSON Http request, send login & password Return JSON wow much bad
  7. SPA Track States Send login & password Return expirable auth

    code Http request, send expirable auth code Return JSON Variant 1
  8. cookies ! always get sent on every request for same

    domain Have maximum size of 4096K Usually gets deleted when the browser is closed or when expiration date is set ! document.cookie  =  “auth_key=12345678;  expires=….”
  9. HTML5 sessionStorage ! Do not get sent with request Have

    maximum size of around ~5mb Gets deleted when the tab/window is closed ! sessionStorage.setItem(‘auth_key’,’12345678’)
  10. HTML5 localStorage ! Do not get sent with request Have

    maximum size of around ~5mb Can be stored forever as long as you don’t uninstall your browser ! localStorage.setItem(‘auth_key’,’12345678’)
  11.    UserSession::$save  =  -­‐>          $http.post  apiHost

     +  "users/sign_in",              data:                  login:  @login                  password:  @password                  remember_me:  (if  @remember_me  then  1  else  0)
  12.    def  create          #  Find  the

     login  on  the  db          resource  =  resource_class.find_for_database_authentication(login:   params[:data][:login])          raise  "Invalid  login  or  password"  if  resource.nil?   !        #  If  login  is  found,  continue  with  password  verification          password_valid  =  resource.valid_password?(params[:data][:password])          raise  "Invalid  login  or  password"  unless  password_valid   !        #  Create  authentication  information          create_authentication!(resource)   !        #  Render  the  response          render  json:  resource,                serializer:  Api::SessionSerializer,              status:  201  #  created      end
  13.    #  Function  for  storing  session  data      @putSessionData

     =  (sessionData)  -­‐>          window.sessionStorage.setItem(sessionStore,   JSON.stringify(sessionData))   !        @signedIn  =  true          @signedOut  =  not  @signedIn          @currentUser  =  sessionData.data          @userSession  =  new  UserSession(              login:  sessionData.data.username              password:  ""              remember_me:  false              auth_token:  sessionData.data.authentication_token          )
  14.    #  Wrap  an  action  in  a  resource  with  auth_token

         #  Treat  each  kind  of  action  accordingly      tokenWrapper  =  (resource,  action)  -­‐>          resource['_'  +  action]  =  resource[action]   !        if  action  in  ['save',  'update']              resource[action]  =  (params,  data,  success,  error)  -­‐>                  resource['_'  +  action]  angular.extend({},  params  or  {},                      username:  authTokenHandler.getUsername()                      auth_token:  authTokenHandler.getAuthToken()                  ),  data,  success,  error          else              resource[action]  =  (params,  success,  error)  -­‐>                  resource["_"  +  action]  angular.extend({},  params  or  {},                      username:  authTokenHandler.getUsername()                      auth_token:  authTokenHandler.getAuthToken()                  ),  success,  error
  15. Track States Send login & password Return expirable auth code

    Http request, send expirable auth code & permanent identifier Return JSON Variant 2 Return permanent identifier Expirable auth code can be stored on sessionStorage ! Permanent identifier can be stored on localStorage
  16. id: 1, name: giovanni id: 2, name: john id: 3,

    name: robert id: 4, name: sean id: 5, name: roger id: 1, name: giovanni id: 3, name: robert id: 5, name: roger Logged  in  as  John,   John  is  staff
  17. id: 1, name: giovanni id: 2, name: john id: 3,

    name: robert id: 4, name: sean id: 5, name: roger id: 1, name: giovanni id: 2, name: john id: 3, name: robert id: 4, name: sean id: 5, name: roger Logged  in  as  Giovanni,   John  is  admin
  18. id: 1, name: giovanni id: 2, name: john id: 3,

    name: robert id: 4, name: sean id: 5, name: roger 403 forbidden Not  logged  in
  19. Selective View Access ! This can happens only on the

    client or both the client and the API server
  20. If you chose to do it only on the client..

    Http Request send everything + { access: [‘viewDashboard’, ‘viewUsers’] }
  21. If you chose to do it both on the server

    and client (more secure) Http Request send only necessary templates Can i access dashboard? send dashboard-related templates
  22. 1. Can guests see all views? - Concern => send

    ping to server 1st - Not a concern => store authorization on client ! 2. Are many of your users access your app from public/shared pc? - Quick Session timeout - Disable ‘remember me’ feature …
  23. … 3. Are your applications utilize very sensitive information ?

    (e.g. credit cards, etc) - Do not store it on client. ever. - https for transaction is a must! - 3rd party payment tools ! 4. Are your applications have separate admin area to control the whole application? - Use separate domain for the admin area. Or better yet, different server too - Obsfucate the url. http://app.com/xyzabc rather than http:// app.com/admin …