2012-10-14 14 views
8

Sto sviluppando un sito Web con Node.js (utilizzando framework Express). Per utilizzare l'autenticazione di Twitter, sto utilizzando il modulo passport (http://passportjs.org) e il suo wrapper per Twitter chiamato passport-twitter.Autenticazione Twitter con middleware Passport nel nodo

Il mio script lato server è:

/** 
* Module dependencies. 
*/ 

var express = require('express') 
    , routes = require('./routes') 
    , user = require('./routes/user') 
    , http = require('http') 
    , path = require('path') 
    , passport = require('passport') 
    , keys = require('./oauth/keys') 
    , TwitterStrategy = require("passport-twitter").Strategy; 

var app = express(); 

app.configure(function(){ 
    app.set('port', process.env.PORT || 3000); 
    app.set('views', __dirname + '/views'); 
    app.set('view engine', 'jade'); 
    app.use(express.favicon()); 
    app.use(express.logger('dev')); 
    app.use(express.bodyParser()); 
    app.use(express.methodOverride()); 
    app.use(express.cookieParser('foo')); 
    app.use(express.session()); 
    // Initialize Passport! Also use passport.session() middleware, to support 
    // persistent login sessions (recommended). 
    app.use(passport.initialize()); 
    app.use(passport.session()); 
    app.use(app.router); 
    app.use(require('less-middleware')({ src: __dirname + '/public' })); 
    app.use(express.static(path.join(__dirname, 'public'))); 
}); 

app.configure('development', function(){ 
    app.use(express.errorHandler()); 
}); 

passport.serializeUser(function(user, done) { 
    done(null, user.id); 
}); 

passport.deserializeUser(function(id, done) { 
    User.findById(id, function (err, user) { 
    done(err, user); 
    }); 
}); 

passport.use(new TwitterStrategy({ 
    consumerKey: keys.twitterConsumerKey, 
    consumerSecret: keys.twitterConsumerSecret, 
    callbackURL: "http://local.host:3000/auth/twitter/callback" 
    }, 
    function(token, tokenSecret, profile, done) { 
    User.findOrCreate({ twitterId: profile.id }, function (err, user) { 
     if (err) { return done(err); } 
     else { return done(null, user); } 
    }); 
    } 
)); 

app.get('/', routes.index); 
app.get('/contacts', routes.contacts); 
app.get('/cv', routes.cv); 
app.get('/projects', routes.projects); 
app.get('/users', user.list); 

// Redirect the user to Twitter for authentication. 
// When complete, Twitter will redirect the user back to the 
// application at /auth/twitter/callback 
app.get('/auth/twitter', passport.authenticate('twitter')); 

// Twitter will redirect the user to this URL after approval. Finish the 
// authentication process by attempting to obtain an access token. If 
// access was granted, the user will be logged in. Otherwise, 
// authentication has failed. 
app.get('/auth/twitter/callback', 
    passport.authenticate('twitter', 
    { 
     successRedirect: '/', 
     failureRedirect: '/login' 
    } 
) 
); 

http.createServer(app).listen(app.get('port'), function(){ 
    console.log("Express server listening on port " + app.get('port')); 
}); 

L'URI associato il login è http://local.host:3000/auth/twitter; quando lo visito, Twitter mi mostra la forma di autenticazione per il collegamento il mio account con il mio sito web, ma, dopo questo passo, il seguente errore si è verificato:

Express 
500 ReferenceError: User is not defined 

Come posso risolvere questo problema? Cordiali saluti, Vi.

+0

var utente anziché utente var? – chovy

risposta

7

È necessario definire il tipo di utente da qualche parte. Sembra che tu ti aspetti che questa cosa sia esistente e che abbia le funzioni findOrCreate e findById, ma non l'hai mai definita da nessuna parte. Dove stai 'trovando' questi utenti? Quelli che non si trovano, dove vengono "creati"? Stai usando un database? Come ti connetti al database? Penso che tu abbia dimenticato il passaggio "Modello". Si potrebbe voler dare un'occhiata a Mongoose Auth che è come passaporto, ma si connette direttamente alla Mongoose, che connnects ad un database Mongo

+0

Mi dispiace, ho fatto un errore davvero stupido! Grazie mille per la risposta! –

+0

perché dovresti aver bisogno di un database quando accedi agli utenti? non è un "must". Non uso alcun database nella mia app, non ho nulla da salvare .. – vsync

+0

vsync sei corretto, non hai bisogno di avere un database. Solo se si desidera mantenere le informazioni utente da una richiesta all'altra è necessario un qualche tipo di database (possono essere file, in memoria o un database appropriato). – Max

3

Questo è quello che ho fatto quando ho affrontato lo stesso errore che dice User non è definito:

passport.use(new TwitterStrategy({ 
    consumerKey: keys.twitterConsumerKey, 
    consumerSecret: keys.twitterConsumerSecret, 
    callbackURL: "http://local.host:3000/auth/twitter/callback" 
    }, 
    function(token, tokenSecret, profile, done) { 
    done(null, profile); 
    } 
)); 
+2

Si prega di non farlo, non è sicuro. Hai una singola istanza 'User', che è condivisa tra tutti i visitatori del tuo sito. Ciò causerà molti problemi di sicurezza e controllo degli accessi. –

+0

ma la mia app dice che l'utente non è definito. Devo definirlo manualmente. Ho aggiornato la mia risposta dal modo in cui – vsync

+0

Giusto, l'utente è qualcosa che è necessario implementare. Di solito è una classe o un modello fornito da un ORM come Mongoose. L'importante è che ci sia un'istanza unica per ogni utente dell'applicazione. –

0

Ho riscontrato lo stesso problema durante l'integrazione della strategia OAuth2 BeatsMusic per Passport in Kraken. Sembra che gli esempi delle varie strategie di integrazione Kraken Passport utilizzino la stessa semplice documentazione di esempio che non ha esplicitamente discusso l'oggetto User (comprensibile).

Ho scoperto (dallo scavo attraverso gli esempi di strategia del passaporto trovati @https://github.com/krakenjs/kraken-examples/tree/master/with.passport) che l'Utente è destinato a essere un modello basato sullo schema del modello Mongoose e che è anche configurato con il plug-in https://github.com/drudge/mongoose-findorcreate.

Dopo aver incluso lo User = require('../PATH_TO/user') e aggiunto questo plug-in al modello Utente, voilà! niente più errori :)

Sembra che tu non abbia bisogno della funzionalità DB, quindi probabilmente stai bene rimuovendo il controllo dell'autorizzazione.

Spero che questo aiuti chiunque abbia problemi simili.

0

Penso che l'API non sia pronta per i casi che non necessitano di integrazione db dell'utente. La mia soluzione è stata ignorare la funzione done() e fare un reindirizzamento alla pagina di successo.

passport.use(new TwitterStrategy({ 
    consumerKey: keys.twitterConsumerKey, 
    consumerSecret: keys.twitterConsumerSecret, 
    callbackURL: "http://local.host:3000/auth/twitter/callback" 
    }, 
    function(token, tokenSecret, profile, done) { 
    //done(null, profile); 
    this.redirect('/auth/success'); 
    } 
)); 
0

Per spiegare ulteriormente sulla risposta di Max: "È necessario creare User te stesso"

Read Here

TL: DR - In pratica è necessario disporre di un userschema che si utilizza per impostare gli utenti e verificare utenti, ha bisogno di un backend db mangusta, che è in realtà semplice da configurare.

essenzialmente creando questo middleware:

var mongoose = require('mongoose'); 
var bcrypt = require('bcrypt-nodejs'); 

// define the schema for our user model 
var userSchema = mongoose.Schema({ 

    local   : { 
     email  : String, 
     password  : String, 
     group  : String, 
    }, 
    facebook   : { 
     id   : String, 
     token  : String, 
     email  : String, 
     name   : String 
    }, 
    twitter   : { 
     id   : String, 
     token  : String, 
     displayName : String, 
     username  : String 
    }, 
    google   : { 
     id   : String, 
     token  : String, 
     email  : String, 
     name   : String 
    } 

}); 

// methods ====================== 
// generating a hash 
userSchema.methods.generateHash = function(password) { 
    return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null); 
}; 

// checking if password is valid 
userSchema.methods.validPassword = function(password) { 
    return bcrypt.compareSync(password, this.local.password); 
}; 

// create the model for users and expose it to our app 
module.exports = mongoose.model('User', userSchema); 
Problemi correlati