2014-09-12 13 views
8

Czy istnieje opcjonalne oprogramowanie pośredniczące do uwierzytelniania ze strony Passport.js?Opcjonalne uwierzytelnianie Passport.js

Załóżmy, że mam trasę, /api/users. Chcę podać tylko listę użytkowników do wiadomości publicznej, ale do uwierzytelnionych osób, chcę dodać więcej pól.

Obecnie mam tylko głupi sposób niestandardowy, który robi to samo, ale zastanawiam się, czy:

  • Passport.js przewiduje już taką rzecz lub
  • jak mogę zrobić to część od paszport, jak wtyczka lub coś podobnego.

Moja metoda, z grubsza wygląda

function optionalAuth(req, res, next) { 

    var authHeader = req.headers.authorization; 
    var token = parseToken(authHeader); // just getting the OAuth token here 
    if(!token) { 

     return next(); 
    } 
    User.findOne({ 
     token: token 
    }, function(err, user) { 

     if(err) { 
      return res.json(401, {message: 'auth expired'}); 
     }; 
     if(user) { 
      req.user = user; 
     } 
     next(); 
    }); 
} 

to jednak wydaje mi się głupie, a także nie w paszporcie-auth-strategies.js lub jakaś inna warstwa auth gdzie myślę, że powinien być. Jaki jest lepszy sposób na zrobienie tego?

Dodatkowe punkty za poinformowanie mnie, czy robię właściwą rzecz powracającego 401 jeśli znajdę token, ale to nieważne :)

+0

Zakładając, że masz podstawowe funkcje (uwierzytelnianie użytkowników), myślę, że możesz użyć 'req.isAuthenticated()' (który jest zdefiniowany przez Passport), aby sprawdzić, czy chcesz zwrócić dodatkowe pola lub nie. – robertklep

+0

Nie można użyć polecenia req.isAuthenticated, ponieważ nie mogę przedtem podać pliku passport.authenticate(). Czemu? Ponieważ nieuwierzytelnieni użytkownicy zostaną odrzuceni. Nie mam sesji, to bezpaństwowy interfejs API, tylko token na okaziciela. Jeśli umieściłbym passport.authenticate() na trasie, niektórzy użytkownicy otrzymaliby 401. Chcę, żeby je przekazali, a otrzymają tylko ograniczone informacje. – Zlatko

Odpowiedz

9

Oto prosty PoC:

var express  = require('express'); 
var app   = express(); 
var server  = app.listen(3012); 
var passport  = require('passport'); 
var LocalStrategy = require('passport-local').Strategy; 

app.use(passport.initialize()); 

passport.use(new LocalStrategy(function(username, password, done) { 
    if (username === 'foo' && password === 'bar') { 
    return done(null, { username : 'foo' }); 
    } 
    return done(null, false); 
})); 

app.get('/api', function(req, res, next) { 
    passport.authenticate('local', function(err, user, info) { 
    var data = { hello : 'world' }; 
    // Only if the user authenticated properly do we include secret data. 
    if (user) { 
     data.secret = '3133753CR37'; 
    } 
    return res.send(data); 
    })(req, res, next); 
}); 

on dzwoni passport.authenticate „ręcznie "w punkcie końcowym /api. W ten sposób uzyskasz większą kontrolę nad tym, jak radzić sobie z błędem uwierzytelniania (który - w Twojej sytuacji - nie powinien być traktowany jako błąd, ale jako sposób ograniczenia wydajności).

Oto wyjście bez odpowiedniej autoryzacji:

$ curl 'localhost:3012/api?username=foo&password=wrong' 
{"hello":"world"} 

A oto z:

$ curl 'localhost:3012/api?username=foo&password=bar' 
{"hello":"world","secret":"3133753CR37"} 

użyć jako middleware:

var middleware = function(req, res, next) { 
    passport.authenticate('local', function(err, user, info) { 
    req.authenticated = !! user; 
    next(); 
    })(req, res, next); 
}; 

app.get('/api', middleware, function(req, res, next) { 
    var data = { hello : 'world' }; 
    if (req.authenticated) { 
    data.secret = '3133753CR37'; 
    } 
    return res.send(data); 
}); 
+0

Dzięki. W pewnym sensie jest to lepsze niż moja próba, ponieważ używa paszportu dla auth. Ale jest trochę bardziej niezgrabny, nie mogę po prostu umieścić go jako oprogramowania pośredniego na nieuwierzytelnionych trasach. Ale to może być wrapable do jakiejś wtyczki. Będę musiał spróbować. – Zlatko

+0

@Zlatko Edytowałem swoją odpowiedź, aby dać wyobrażenie o tym, jak można ją przekształcić w oprogramowanie pośrednie. – robertklep

+0

Niesamowite, to wszystko, lepsze niż moje wtrącanie się. – Zlatko

6

może być późno, ale nie anonymous Strategia paszportowa umożliwiająca to. W ten sposób publiczne trasy mogą albo wymagać uwierzytelnienia, albo nie, ale kiedy to zrobią, nadal będziesz mieć wszystkie informacje związane z uwierzytelnionym użytkownikiem. Sprawdź to tutaj: https://github.com/jaredhanson/passport-anonymous

+0

Jest za późno na tę pracę, ale może pomóc w przyszłości :) – Zlatko