2014-11-12 6 views
11

Quindi mi piacerebbe creare alcuni percorsi in un'API che mostrerà dati diversi in base al ruolo utente, definito in MongoDB. Ecco un campionario di ciò che ho in questo momento, funziona ...Verifica dei ruoli e autenticazione con Passport.js

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

Tuttavia, l'obiettivo finale è quello di presentare almeno qualcosa per l'utente, anche se non è registrato o autenticati con il giusto tipo di ruolo.

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

Che Vorrei pensare che avrei capire come lavorare, ma non so come specificare lo stesso percorso, che forse potrebbe essere colpire senza intestazione di autorizzazione nella richiesta.

È possibile in Passport.js/Express?

+0

Dovrete costruire il proprio fork in ordoer per permettere questo credo – Vinz243

+0

Forcella il repo passaporto e aggiungere la funzionalità, è questo che vuoi dire? –

+1

Piuttosto questo penso. Se lo stai usando. https://github.com/jaredhanson/passport-http-bearer. Le linee che dovresti dare un'occhiata sono queste https://github.com/jaredhanson/passport-http-bearer/blob/master/lib/strategy.js#L89-101 – Vinz243

risposta

6

vorrei suggerire di utilizzare HTTP codici di stato e un oggetto errore, questo è un convegno API comune e consente agli utenti API per sapere cosa sta succedendo e perché:

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

Disclaimer: io lavoro a Stormpath e abbiamo messo un sacco di pensiero in autenticazione API e del design, abbiamo una veramente presentazione sul argomento:

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

+0

Buona idea! Tuttavia, chiunque non abbia effettuato l'accesso e abbia visto il contenuto premium nel proprio stream in sostanza ha ricevuto un errore nella propria console, giusto?Questa è una buona pratica generale? Soprattutto se un'app angolare è in ascolto di codici di errore e risponde con altri percorsi/modelli? –

+0

Il tuo client (un'app Angular, ecc.) Ha bisogno di leggere questi codici di stato o messaggi di errore e rispondere di conseguenza - come lo mostri all'utente del client .. questo dipende totalmente da te :) – robertjd

7

La soluzione è limitare il contenuto nella vista anziché il percorso.

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 
+0

Una buona soluzione se si utilizza la giada, di sicuro. E se non usassi Jade? Mi piacerebbe mantenere questi percorsi rigorosamente su un'API. –

+1

Se stai costruendo un'API dovresti modificare la domanda per dirlo, in questo modo possiamo offrire risposte specifiche API :) – robertjd

+0

Jade è davvero così comune presumere che sia implementato in un'app NodeJS, però? –

1

La soluzione che ho trovato per la mia risposta è quella di utilizzare un adattamento della documentazione Passportjs.org.

Nelle rotte di cui ho bisogno per restituire i dati, se un utente è connesso o non riesco a usare qualcosa come:

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