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

Login con Angular + NodeJS

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →

Login con Angular + NodeJS

Cómo implementar login con JSON Web Tokens usando Express y cómo consumirlo en Angular.

Repasa las formas de hacer login.

Avatar for Jeduan Cornejo

Jeduan Cornejo

August 30, 2014

More Decks by Jeduan Cornejo

Other Decks in Technology

Transcript

  1. HTTP Basic • ! Parte del protocolo HTTP. • !

    Usado en APIs modernas (Stripe).
  2. HTTP Basic • ! Parte del protocolo HTTP. • !

    Usado en APIs modernas (Stripe). • " Se envia el usuario y password en cada petición.
  3. HTTP Basic GET /api/channel/favorites HTTP/1.1 Host: localhost:3000 Connection: close User-Agent:

    curl/7.9.8 (i686-pc-linux-gnu) libcurl 7.9.8 (OpenSSL 0.9.6b) (ipv6 enabled) Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
  4. Cookies • ! Existe de años y es ampliamente soportado.

    • ! Los riesgos de seguridad son bien conocidos.
  5. Cookies • ! Existe de años y es ampliamente soportado.

    • ! Los riesgos de seguridad son bien conocidos. • " Hay muchos problemas con mobileweb • " El server se encarga de guardar las sesiones
  6. Cookies GET /api/channel/favorites HTTP/1.1 Cookie: connect.sid=12345 Host: localhost:3000 Connection: close

    User-Agent: curl/7.9.8 (i686-pc-linux-gnu) libcurl 7.9.8 (OpenSSL 0.9.6b) (ipv6 enabled)
  7. Cookies GET /api/channel/favorites HTTP/1.1 Cookie: connect.sid=12345 Host: localhost:3000 Connection: close

    User-Agent: curl/7.9.8 (i686-pc-linux-gnu) libcurl 7.9.8 (OpenSSL 0.9.6b) (ipv6 enabled)
  8. OAuth + Tokens • ! Facebook, Twitter, Foursquare, Github, Pinterest

    • ! Granular • ! Móviles + Web • " Confuso (¿hice login con Facebook o con la app?) • " El estandar menos estandar • " Varios pasos para autentificarse • " Para este caso no se necesitan muchas de sus funcionalidades
  9. OAuth + Tokens GET /api/channel/favorites HTTP/1.1 Host: localhost:3000 Connection: close

    User-Agent: curl/7.9.8 (i686-pc-linux-gnu) libcurl 7.9.8 (OpenSSL 0.9.6b) (ipv6 enabled) Authorization: OAuth realm="example", oauth_consumer_key="9djdj82h48djs9d2", oauth_token="kkk9d7dh3k39sjv7", oauth_signature_method="HMAC-SHA1", oauth_timestamp="137131201", oauth_nonce="7d8f3e4a", oauth_signature="bYT5CMsGcbgUdFHObYMEfcx6bsw%3D"
  10. JSON Web Tokens • ! En estandarización • ! Soportado

    en móviles y web • ! El token puede expirar por tiempo o dar acceso solo a ciertas partes
  11. JSON Web Tokens • ! En estandarización • ! Soportado

    en móviles y web • ! El token puede expirar por tiempo o dar acceso solo a ciertas partes • " Relativamente nuevo
  12. GET /api/channel/favorites HTTP/1.1 Host: localhost:3000 Connection: close User-Agent: curl/7.9.8 (i686-pc-linux-gnu)

    libcurl 7.9.8 (OpenSSL 0.9.6b) (ipv6 enabled) Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dWlkIjoiYjNmM2RmMDEtOTY2My00YmY5LTljNjYtYTcwOGVhOTYyOTg0IiwiaWF0IjoxNDA5MzAzNjIyLCJleHAiOjE0MDkzMDcyMjJ9.ttk55eIjwU2gzlS5DwifZpJN_NDdCVjBKhMEpTCkjfw
  13. Node: • promesas (bluebird) • express • passport • passport-local

    • passport-http-bearer • bookshelf • mysql • jwt-simple
  14. /api/token : El usuario cambia un usuario y contraseña por

    un token o un horroroso 401 router.route('/') .post(function(req, res, next) { passport.authenticate('local', function(err, account, info) { if (err) return next(err) if (!account) { return res.status(401).end() } var token = jwt.encode({id: account.id, exp: Date.now() + (60 * 24 * 15}) res.send({user: account, token: token}) })(req, res, next) })
  15. passport-config passport.use(new LocalStrategy(function (username, password, done) { return Account.where({username: username})

    .fetch({require: true}) .then(function(account) { return account.checkPassword(password) .then(function(isMatch) { if (!isMatch) { throw new UnauthorizedError() } else { return done(null, account) } }) }).catch(function(err) { if (err instanceof UnauthorizedError || err.message === 'EmptyResponse') { return done(null, false) } else { return done(err) } }) }))
  16. passport.use(new BearerStrategy(function (token, done){ return jwt.verifyAsync(token, process.env.SECRET) .then(function(payload) { return

    Account.where({id: payload.id}).fetch({require: true}) }).then(function(account){ done(null, account) }).catch(function(err) { if (err.message === 'invalid signature') { console.error('[users] Invalid token used') return done(null, false) } return done(err) }) }))
  17. server.js router.route('/api/token').get(function(req, res) {...}) router.route('/api/countries').get(function(req, res) {...}) router.use(passport.authenticate('bearer', {session: false}))

    router.route('/api/profile').get(function(req, res) {...}) router.route('/api/favorites').get(function(req, res) {...}) router.route('/api/channels').get(function(req, res) {...}) router.use(function(req, res, next) { if (!req.user.get('isAdmin')) res.send(403).end() next() }) router.route('/api/create').post(function(req, res) {...})
  18. .controller('LoginController', function($scope, authService, $http, $window) { $scope.login = function(credentials) {

    var self = this return $http.post('/api/token', credentials, { ignoreAuthModule: true }) .success(function(user) { authService.loginConfirmed(user) $window.localStorage.token = user.token }) } })
  19. .service('userService', function($rootScope){ var currentUser = null $rootScope.$on('event:auth-loginConfirmed', function(user) { currentUser

    = user }) $rootScope.$on('event:auth-loginCancelled', function(user) { currentUser = null delete $window.localStorage.token }) return { getCurrentUser: function() { return currentUser }, fetch() { if (!currentUser && localStorage.token) { return $http.get('/api/user') } } } })
  20. .config(function($httpProvider) { $httpProvider.interceptors.push(function ($window) { return { request: function(config) {

    config.headers = config.headers || {} if ($window.localStorage.token) { config.headers.Authorization = 'Bearer ' + $window.localStorage.token } return config }, } }) })