web-dev-qa-db-ja.com

Passport.jsによる役割と認証の確認

したがって、MongoDBで定義されているユーザーロールに基づいて異なるデータを表示するAPIでいくつかのルートを作成したいと思います。これが私が今持っているもののサンプルです、それはうまくいきます...

router.get('/test', passport.authenticate('bearer', {session: false}), function (req, res) {
    if (req.user.role == "premium") {
        return res.send('you can see this content');
    }
    else {
        return res.send('you can not see this content');
    }
})

ただし、最終的な目標は、ユーザーがログインしていないか、適切な種類の役割で認証されていない場合でも、少なくともsomethingをユーザーに提示することです。

router.get('/test', passport.authenticate('bearer', {session: false}), function (req, res) {
    if (req.user.role == "premium") {
        return res.send('this is premium content');
    }
    else {
        // could be hit by another role, or no user at all
        return res.send([some truncated version of the premium content]);
    }
})

どのように動作するかは理解できると思いますが、リクエストにAuthorizationヘッダーがないとヒットする可能性のある同じルートを指定する方法がわかりません。

これはPassport.js/Expressで可能ですか?

15
user393219

HTTPステータスコードとエラーオブジェクトを使用することをお勧めします。これは一般的なAPI規約であり、これによりAPIユーザーは何が発生していて、その理由を知ることができます。

app.get('/premium-resource', function(req, res, next) {
  passport.authenticate('bearer', function(err, user) {
    if (user){
      if (user.role === 'premium'){
        return res.send(200,{userContent:'you are a premium user'});
      }else{
        return res.send(403,{
          'status': 403,
          'code': 1, // custom code that makes sense for your application
          'message': 'You are not a premium user',
          'moreInfo': 'https://myawesomeapi.io/upgrade'
        });
      }
    }else{
      return res.send(401,{
        'status': 401,
        'code': 2, // custom code that makes sense for your application
        'message': 'You are not authenticated.',
        'moreInfo': 'https://myawesomeapi.io/docs'
      });
    }
  })(req, res, next);
});

免責事項:私は Stormpath で働いており、APIの認証と設計に多くの考慮を払っています。

https://stormpath.com/blog/designing-rest-json-apis/

9
robertjd

解決策は、ルートではなくビューのコンテンツを制限することです。

router.get('/test', authenticationMiddleware, function(req, res){
    var premiumFlag = req.user.role;
    res.send('premiumontent', {role: premiumFlag});
});

premiumContent.jade

p This content is visible to all users

- if role === "premium"
    p this content is only visible to premium users
7
takinola

私の答えに対して私が見つけた解決策は、 Passportjs.org のドキュメントの修正を使用することです。

データを返す必要があるルートでは、ユーザーがログインしているかどうかにかかわらず、次のようなものを使用できます。

// Test to check for authentication
app.get('/login', function(req, res, next) {
  passport.authenticate('bearer', function(err, user, info) {
    if (user)
        // check user's role for premium or not
        if (user.role == "premium")
            return res.send('user is premium')
        else
            return res.send('user is not premium');
    else
        // return items even if no authentication is present, instead of 401 response
            return res.send('not logged in');
  })(req, res, next);
});
1
user393219