2014-09-12 69 views
8

Passport.js是否有可選的身份驗證中間件?Passport.js可選身份驗證

比方說,我有一條路線,/api/users。我只想向公衆提供一個用戶列表,但是要認證的人員,我想添加更多的字段。

目前我只是做同樣的事情啞自定義的方法,但我不知道:

  • Passport.js已經提供了這樣的事情或
  • 我怎麼能做出這樣的部分護照,就像插件一樣。

我的方法,大概,看起來像

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(); 
    }); 
} 

然而,這似乎是愚蠢的我,也沒有在護照認證 - strategies.js或其他一些身份驗證層,我認爲它應該是。有什麼更好的方法來做到這一點?你告訴我,如果我做回401正確的事情,如果我找到一個令牌,但它是無效的

加分:)

+0

假設你有基本的工作(認證用戶),我認爲你可以使用'req.isAuthenticated()'(這是Passport定義的東西)來檢查你是否要返回額外的或不是。 – robertklep 2014-09-12 12:42:19

+0

我無法使用req.isAuthenticated,因爲我無法在此之前放置passport.authenticate()。爲什麼?因爲未經認證的用戶會被拒絕。 我沒有會話,這是一個無狀態的API,只是一個不記名的令牌。如果我把passport.authenticate()放在路由中,有些用戶會得到401,我希望他們通過,只能得到有限的信息。 – Zlatko 2014-09-14 08:26:09

回答

9

這裏有一個簡單的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); 
}); 

它的手動調用passport.authenticate」 '在/api端點中。這樣,您就可以更好地控制如何處理身份驗證錯誤(在您的情況下 - 不應將其視爲錯誤,而應視爲限制輸出的方式)。

這裏有沒有適當的認證輸出:

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

而且這裏是:

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

要作爲中間件使用:

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

謝謝。在某種程度上,我的嘗試更好,因爲它使用護照進行身份驗證。但它有點笨拙,我不能把它作爲一箇中間件放在未經驗證的路線上。但是這可能會被包裝成某種插件。我必須嘗試。 – Zlatko 2014-09-14 13:46:21

+0

@Zlatko我編輯了我的答案,提供了一個關於如何將它變成中間件的想法。 – robertklep 2014-09-15 05:25:58

+0

太棒了,就是這樣,再好不過我的插手。 – Zlatko 2014-09-15 09:16:56

6

可能是晚了,但有一個anonymous護照戰略,以準確這一點。這樣公共路線可以採取認證或不認證,但是當他們這樣做時,您仍然擁有與認證用戶相關的所有信息。看看這裏:https://github.com/jaredhanson/passport-anonymous

+0

這項工作已經晚了,但可能有助於未來的工作:) – Zlatko 2016-05-20 09:11:57