Node.js/Passport推特授权returns302
Node.js/Passport Twitter authorization returns 302
我正在执行 POST 请求以通过 Passport Twitter 策略授权 Twitter。如果我使用 Postman,请求会正常进行,但如果我在我的应用程序中使用它,请求就会失败。我得到一个 302 响应,这个在浏览器控制台中
Error: Network Error
Stack trace:
createError@webpack-internal:///99:16:15
handleError@webpack-internal:///96:87:14
根据我在网上阅读的内容,我发现 302
是因为重定向调用的执行不当?也许是 twitter 在授权应用程序时所做的,而我没有正确处理它?
代码如下。客户端使用 Vuejs 和 Axios 发送请求。
Vue 模板:
<template>
<card>
<h4 slot="header" class="card-title">Edit linked accounts</h4>
<form>
<button type="submit" class="btn btn-info btn-fill" @click.prevent="authTwitter">
Link Facebook
</button>
<div class="clearfix"></div>
</form>
</card>
</template>
<script>
import Card from 'src/components/UIComponents/Cards/Card.vue'
import controller from '../../../../../src/controller/AuthController'
export default {
components: {
Card
},
data () {
return {
}
},
methods: {
authTwitter () {
let token = this.$session.get('jwt')
controller.http.post('/auth/twitter',{}, {
headers: {
Authorization: 'Bearer ' + token
}
})
.then(function(response) {
console.log(response)
})
.catch(function(error) {
console.log(error);
})
}
}
}
</script>
<style>
</style>
Axios 设置:
const axios = require('axios');
const config = require('../../config/index.js')
let http = axios.create({
baseURL: config.url,
'Content-Type' : 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin':'*'
})
module.exports = {
http
}
在我的后端,我正在执行以下操作:
护照设置:
const passport = require('passport');
const StrategyTwitter = require('passport-twitter').Strategy,
LocalStrategy = require('passport-local').Strategy;
const JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
const {
User,
UserDetails,
UserAccounts
} = require('../models');
const bcrypt = require('bcrypt-nodejs');
const jwt = require('jsonwebtoken');
const config = require('../config/config');
let session = require('express-session')
var opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = config.secretKey;
module.exports = function(app) {
// Local sign-in stragetgy
passport.use('local-signin', new LocalStrategy(
function(username, password, done) {
User.findOne({
where: {
username: username
}
}).then(function(data) {
bcrypt.compare(password, data.password, function(err, response) {
if (err) {
return done(err);
}
const token = jwt.sign({
id: data.id
}, config.secretKey, {
expiresIn: 86400 // 86400 expires in 24 hours
});
return done(null, token);
});
}).catch(function(error) {
return done(error)
});
}
));
// Local sign-up strategy
passport.use('local-signup', new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function(req, username, password, done) {
process.nextTick(function() {
User.beforeCreate(function(req) {
return encryptPass(req.password)
.then(success => {
req.password = success;
})
.catch(err => {
if (err) console.log(err);
});
});
User.create({
username: username,
password: password
}).then(function(data) {
UserDetails.create({
username: req.body.username,
name: req.body.name,
dob: req.body.dob,
phone: req.body.phone,
gender: req.body.gender,
address: req.body.address,
country: req.body.country,
}).then(function(data) {
UserAccounts.create({
username: username
}).then(function(data) {
return done(null, data);
}).catch(function(error) {
return done(error.message);
});
}).catch(function(error) {
return done(error.message);
});
}).catch(function(error) {
return done(error.message);
});
})
}
));
// Passport Jwt strategy
passport.use('jwt', new JwtStrategy(opts, function(jwt_payload, done) {
console.log('jwt', jwt_payload);
UserDetails.findOne({
where: {
id: jwt_payload.id
}
})
.then(function(user) {
return done(null, user.id);
})
.catch(function(err) {
return done(err, false);
});
}));
// Use sessions for twitterStrategy Oauth1 authorizations.
passport.serializeUser(function(user, cb) {
console.log('user', user)
cb(null, user);
});
passport.deserializeUser(function(obj, cb) {
console.log('obj', obj)
cb(null, obj);
});
// Configure the Twitter strategy for use by Passport.
//
// OAuth 1.0-based strategies require a `verify` function which receives the
// credentials (`token` and `tokenSecret`) for accessing the Twitter API on the
// user's behalf, along with the user's profile. The function must invoke `cb`
// with a user object, which will be set at `req.user` in route handlers after
// authentication.
passport.use('twitter-authz', new StrategyTwitter({
consumerKey: config.keys.twitter.consumerKey,
consumerSecret: config.keys.twitter.consumerSecret,
callbackURL: process.env.CALLBACK_URL_TWITTER || 'http://120.0.0.1:8000/#/dashboard/user'
},
function(token, tokenSecret, profile, cb) {
process.nextTick(function() {
// In this example, the user's Twitter profile is supplied as the user
// record. In a production-quality application, the Twitter profile should
// be associated with a user record in the application's database, which
// allows for account linking and authentication with other identity
// providers.
console.log(token, tokenSecret, profile);
return cb(null, profile);
})
}));
// Initialize Passport and restore authentication state, if any, from the
// session.
app.use(passport.initialize());
// Session for twitterStrategy
app.use(session({
secret: config.secretKey,
resave: false,
saveUninitialized: false
}));
}
function encryptPass(pass) {
return new Promise((resolve, reject) => {
bcrypt.hash(pass, null, null, function(err, hash) {
if (err) {
return reject(err);
};
return resolve(hash);
})
})
}
我的路由器设置:
const AuthControllerPolicy = require('./controllers/policies/AuthControllerPolicy.js')
const AuthController = require('./controllers/AuthController.js')
const passport = require('passport');
module.exports = (app) => {
app.post('/auth/twitter',
passport.authenticate('jwt', { session: false }),
passport.authorize('twitter-authz', { session: false }),
AuthController.authTwitter)
}
在此处找到答案:
看起来 Twitter 不允许 CORS 请求,只能从服务器端完成。
我正在执行 POST 请求以通过 Passport Twitter 策略授权 Twitter。如果我使用 Postman,请求会正常进行,但如果我在我的应用程序中使用它,请求就会失败。我得到一个 302 响应,这个在浏览器控制台中
Error: Network Error
Stack trace:
createError@webpack-internal:///99:16:15
handleError@webpack-internal:///96:87:14
根据我在网上阅读的内容,我发现 302
是因为重定向调用的执行不当?也许是 twitter 在授权应用程序时所做的,而我没有正确处理它?
代码如下。客户端使用 Vuejs 和 Axios 发送请求。
Vue 模板:
<template>
<card>
<h4 slot="header" class="card-title">Edit linked accounts</h4>
<form>
<button type="submit" class="btn btn-info btn-fill" @click.prevent="authTwitter">
Link Facebook
</button>
<div class="clearfix"></div>
</form>
</card>
</template>
<script>
import Card from 'src/components/UIComponents/Cards/Card.vue'
import controller from '../../../../../src/controller/AuthController'
export default {
components: {
Card
},
data () {
return {
}
},
methods: {
authTwitter () {
let token = this.$session.get('jwt')
controller.http.post('/auth/twitter',{}, {
headers: {
Authorization: 'Bearer ' + token
}
})
.then(function(response) {
console.log(response)
})
.catch(function(error) {
console.log(error);
})
}
}
}
</script>
<style>
</style>
Axios 设置:
const axios = require('axios');
const config = require('../../config/index.js')
let http = axios.create({
baseURL: config.url,
'Content-Type' : 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin':'*'
})
module.exports = {
http
}
在我的后端,我正在执行以下操作:
护照设置:
const passport = require('passport');
const StrategyTwitter = require('passport-twitter').Strategy,
LocalStrategy = require('passport-local').Strategy;
const JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
const {
User,
UserDetails,
UserAccounts
} = require('../models');
const bcrypt = require('bcrypt-nodejs');
const jwt = require('jsonwebtoken');
const config = require('../config/config');
let session = require('express-session')
var opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = config.secretKey;
module.exports = function(app) {
// Local sign-in stragetgy
passport.use('local-signin', new LocalStrategy(
function(username, password, done) {
User.findOne({
where: {
username: username
}
}).then(function(data) {
bcrypt.compare(password, data.password, function(err, response) {
if (err) {
return done(err);
}
const token = jwt.sign({
id: data.id
}, config.secretKey, {
expiresIn: 86400 // 86400 expires in 24 hours
});
return done(null, token);
});
}).catch(function(error) {
return done(error)
});
}
));
// Local sign-up strategy
passport.use('local-signup', new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function(req, username, password, done) {
process.nextTick(function() {
User.beforeCreate(function(req) {
return encryptPass(req.password)
.then(success => {
req.password = success;
})
.catch(err => {
if (err) console.log(err);
});
});
User.create({
username: username,
password: password
}).then(function(data) {
UserDetails.create({
username: req.body.username,
name: req.body.name,
dob: req.body.dob,
phone: req.body.phone,
gender: req.body.gender,
address: req.body.address,
country: req.body.country,
}).then(function(data) {
UserAccounts.create({
username: username
}).then(function(data) {
return done(null, data);
}).catch(function(error) {
return done(error.message);
});
}).catch(function(error) {
return done(error.message);
});
}).catch(function(error) {
return done(error.message);
});
})
}
));
// Passport Jwt strategy
passport.use('jwt', new JwtStrategy(opts, function(jwt_payload, done) {
console.log('jwt', jwt_payload);
UserDetails.findOne({
where: {
id: jwt_payload.id
}
})
.then(function(user) {
return done(null, user.id);
})
.catch(function(err) {
return done(err, false);
});
}));
// Use sessions for twitterStrategy Oauth1 authorizations.
passport.serializeUser(function(user, cb) {
console.log('user', user)
cb(null, user);
});
passport.deserializeUser(function(obj, cb) {
console.log('obj', obj)
cb(null, obj);
});
// Configure the Twitter strategy for use by Passport.
//
// OAuth 1.0-based strategies require a `verify` function which receives the
// credentials (`token` and `tokenSecret`) for accessing the Twitter API on the
// user's behalf, along with the user's profile. The function must invoke `cb`
// with a user object, which will be set at `req.user` in route handlers after
// authentication.
passport.use('twitter-authz', new StrategyTwitter({
consumerKey: config.keys.twitter.consumerKey,
consumerSecret: config.keys.twitter.consumerSecret,
callbackURL: process.env.CALLBACK_URL_TWITTER || 'http://120.0.0.1:8000/#/dashboard/user'
},
function(token, tokenSecret, profile, cb) {
process.nextTick(function() {
// In this example, the user's Twitter profile is supplied as the user
// record. In a production-quality application, the Twitter profile should
// be associated with a user record in the application's database, which
// allows for account linking and authentication with other identity
// providers.
console.log(token, tokenSecret, profile);
return cb(null, profile);
})
}));
// Initialize Passport and restore authentication state, if any, from the
// session.
app.use(passport.initialize());
// Session for twitterStrategy
app.use(session({
secret: config.secretKey,
resave: false,
saveUninitialized: false
}));
}
function encryptPass(pass) {
return new Promise((resolve, reject) => {
bcrypt.hash(pass, null, null, function(err, hash) {
if (err) {
return reject(err);
};
return resolve(hash);
})
})
}
我的路由器设置:
const AuthControllerPolicy = require('./controllers/policies/AuthControllerPolicy.js')
const AuthController = require('./controllers/AuthController.js')
const passport = require('passport');
module.exports = (app) => {
app.post('/auth/twitter',
passport.authenticate('jwt', { session: false }),
passport.authorize('twitter-authz', { session: false }),
AuthController.authTwitter)
}
在此处找到答案:
看起来 Twitter 不允许 CORS 请求,只能从服务器端完成。