api authentication redefined
What we were doing for years? 
What's wrong with that?
- bulletproof cross-domain cookies are hard to implement
- you have to deal with CSRF
- awkward to use outside the web, eg. in native apps
- you have to keep state on API
alternative:
token authentication

advantages of token authentication
- CORS is a breeze
- decoupling – you can generate token anywhere
- CSRF attack does not exist
- you store session on client side
- stateless API – no login, logout or sessions
Implementation? rails side:
class AuthToken < ActiveRecord::Base
  belongs_to :user
  def self.authenticate(token)
    find_by(token: token).try(:user)
  end
  def self.fetch(user)
    return user.auth_token if user.auth_token.present?
    user.create_auth_token(token: generate_token)
  end
  def self.generate_token
    SecureRandom.hex
  end
endmodule TokenAuth
  def current_user
    authenticate_with_http_token { |token| AuthToken.authenticate(token) }
  end
end
IMPLEMENTATION? RAILS SIDE:
class SessionsController
  def create
    user = User.authenticate_with_credentials(params[:login], params[:password])
    if user
      render json: { token: AuthToken.fetch(user) }
    else
      head :forbidden
    end
  end
end
...and javascript side
getAuthorizationHeader: ->
  token = $.cookie('auth-token')
  "Token #{token}" if token
setCookie: (data) ->
  $.cookie('auth-token', data.token, { expire: 365 })
$.ajaxPrefilter (options, originalOptions, xhr) =>
   xhr.setRequestHeader('Authorization', getAuthorizationHeader())
$.post('/sessions.json', { login: 'user', password: 'secret' }).done(setCookie)
No need to:
- send request to server to sign out
- worry about remembering session, it can be done client-side
few things we should know
- we have to store tokens on client somehow
- tokens can expire like cookies
- streaming is a bit tricky – we have to send signed request
- we have to deal with XSS instead of CSRF
- we can use JSON Web Tokens
json web tokens
- draft specification for token exchanging
- encode any information like hash with user
- allows to specify expiration time of token
- have a lib for most of languages
- probably better way to issue tokens than SecureRandom
JSON WEB TOKENS
user_id = 123
claim = {
  iss: user_id,
  exp: 1.week.from_now,
  nbf: Time.now
}
jwt = JSON::JWT.new(claim).to_s
jws = JSON::JWT.new(claim).sign(key)
jws.to_s
# With signature & encryption
jwe = jws.encrypt(key, algorithm, encryption_method)
jws.to_s
questions?
sources
- http://www.sitepoint.com/using-json-web-tokens-node-js/
 
- http://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
 
- http://auth0.com/blog/2014/01/27/ten-things-you-should-know-about-tokens-and-cookies/
 
- http://tools.ietf.org/html/draft-ietf-oauth-json-web-token
 
deck
By Lucjan Suski
deck
- 348
 
   
   
  