护照后如何使用承诺登录。通过社会服务进行身份验证。 KeystoneJS + 护照

     2023-03-11     232

关键词:

【中文标题】护照后如何使用承诺登录。通过社会服务进行身份验证。 KeystoneJS + 护照【英文标题】:How to do sign in with promises after passport.authenticate with social services. KeystoneJS + Passport 【发布时间】:2017-04-22 18:08:43 【问题描述】:

除了my question in repository我需要在这里发布,可能有人会帮助我,我将不胜感激。

我需要在我的应用程序中解锁代码。

我有几个服务,在获取回调后将用户信息存储在会话中并重定向到名为 /auth/confirm/ 的页面。

这是 twitter auth 的示例,非常适合我。

const keystone = require('keystone');
const passport = require('passport');
const passportTwitterStrategy = require('passport-twitter').Strategy;
const User = keystone.list('User');

const credentials = 
    consumerKey: process.env.TWITTER_CONSUMER_KEY,
    consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
    callbackURL: process.env.TWITTER_CALLBACK_URL,
    includeEmail: true
;

exports.authenticateUser = function(req, res, next) 

    const redirect = '/auth/confirm';

    const twitterStrategy = new passportTwitterStrategy(credentials, function(accessToken, refreshToken, profile, done) 
        done(null, 
            accessToken: accessToken,
            refreshToken: refreshToken,
            profile: profile
        );
    );

    // Pass through authentication to passport
    passport.use(twitterStrategy);

    // Save user data once returning from Twitter
    if (req.query.hasOwnProperty('cb')) 

        passport.authenticate('twitter',  session: false , function(err, data, info) 

            if (err || !data) 
                return res.redirect('/signin');
            

            const name = data.profile && data.profile.displayName ? data.profile.displayName.split(' ') : [];

            req.session.auth = 
                type: 'twitter',

                name: 
                    first: name.length ? name[0] : '',
                    last: name.length > 1 ? name[1] : ''
                ,

                email: data.profile._json.email,

                profileId: data.profile.id,

                username: data.profile.username,

                avatar: data.profile._json.profile_image_url.replace('_normal', ''),

                accessToken: data.accessToken,
                refreshToken: data.refreshToken
            ;

            return res.redirect(redirect);

        )(req, res, next);

        // Perform initial authentication request to Twitter
     else 
        passport.authenticate('twitter')(req, res, next);
    
;

如果我们从用户那里获得访问权限,现在我们将 twitter 用户存储在 req.session.auth 中。但现在我有一个大问题。据我所知,Mongoose User 模型也可以异步工作,当我尝试通过 twitter profileID 检查现有用户时,我无法获得正确的结果,因为它首先转到 .then 回调并且不等待检查结果。我不想让这个异步但避免异步库,因为它对我来说太大了一个功能。我更喜欢使用 Node 新版本中的原生 Promises。我不确定这一切,也不知道如何以最佳性能实现它,并且非常期待有人会帮助我。无论如何-感谢您的阅读...

const keystone = require('keystone');
const User = keystone.list('User');

module.exports = (req, res, next) => 

    const locals = res.locals;

    locals.authUser = req.session.auth;

    // Set existing user if already logged in
    locals.existingUser = req.user || false;

    // Reject request if no auth data is stored in session
    if (!locals.authUser) 
        console.log('[auth.confirm] - No auth data detected, redirecting to signin.');
        console.log('------------------------------------------------------------');
        return res.redirect('/');
    

    const authenticateUser = new Promise((resolve, reject) => 
        if (locals.existingUser) resolve(true);
        console.log('[auth.confirm] - Searching for existing users via [' + locals.authUser.type + '] profile id...');
        console.log('------------------------------------------------------------');
        User.model.findOne()
            .where('services.' + locals.authUser.type + '.profileId', locals.authUser.profileId)
            .exec((err, user) => 
                if (err) 
                    console.log('[auth.confirm] - Error finding existing user via profile id.', err);
                    console.log('------------------------------------------------------------');
                    reject(err);
                
                if (user) 
                    console.log('[auth.confirm] - Found existing user via [' + locals.authUser.type + '] profile id...');
                    console.log('------------------------------------------------------------');
                    locals.existingUser = user;
                    resolve(true);
                
                resolve(false);
            );
    );

    authenticateUser
        .then(result => 
            if (result) return result;
            User.model.findOne()
                .where('email', locals.authUser.email)
                .exec((err, user) => 
                    if (err) 
                        throw err;
                    
                    if (user) 
                        locals.existingUser = user;
                    
                    return false;
                );
        )
        .then(result => 
            if (result) return result;

            if (locals.existingUser) 
                const userData = 
                    email: locals.authUser.email,
                    services: locals.existingUser.services || 
                ;

                userData.services[locals.authUser.type] = 
                    isConfigured: true,
                    profileId: locals.authUser.profileId,
                    username: locals.authUser.username,
                    avatar: locals.authUser.avatar,
                    accessToken: locals.authUser.accessToken,
                    refreshToken: locals.authUser.refreshToken
                ;

                locals.existingUser.set(userData);

                locals.existingUser.save(err => 
                    if (err) throw err;
                    return true;
                );

             else 

                const userData = 
                    name: 
                        first: locals.authUser.name.first,
                        last: locals.authUser.name.last
                    ,
                    email: locals.authUser.email,
                    password: Math.random().toString(36).slice(-8),
                    services: 
                ;

                userData.services[locals.authUser.type] = 
                    isConfigured: true,
                    profileId: locals.authUser.profileId,
                    username: locals.authUser.username,
                    avatar: locals.authUser.avatar,
                    accessToken: locals.authUser.accessToken,
                    refreshToken: locals.authUser.refreshToken
                ;

                locals.existingUser = new User.model(userData);
                locals.existingUser.save(err => 
                    if (err) throw err;
                    return true;
                );
            
        )
        .then(result => 
            console.log('[auth.confirm] - Signing in user...');
            console.log('------------------------------------------------------------');

            const onSuccess = user => 
                console.log('[auth.confirm] - Successfully signed in.');
                console.log('------------------------------------------------------------');
                return res.redirect(req.cookies.target || '/keystone');
            ;

            const onFail = err => 
                console.log('[auth.confirm] - Failed signing in.', err);
                console.log('------------------------------------------------------------');
                if (err) throw err;
                return res.redirect('/');
            ;

            keystone.session.signin(String(locals.existingUser._id), req, res, onSuccess, onFail);
        );

    return authenticateUser;
;

【问题讨论】:

【参考方案1】:

此时我的代码如下。它工作正常且异步,但无论如何我都会很高兴得到某人的评论。

const keystone = require('keystone');
const User = keystone.list('User');

module.exports = (req, res, next) => 

    const authUser = req.session.auth;

    // Reject request if no auth data is stored in session
    if (!authUser) 
        return res.redirect('/');
    

    // Set existing user if already logged in
    if (req.user) return doSignIn(req.user);

    User.model.findOne()
        .where('services.' + authUser.type + '.profileId', authUser.profileId)
        .exec()
        .then(user => 
            if (user) return doSignIn(user);
            User.model.findOne()
                .where('email', authUser.email)
                .exec()
                .then(user => 
                    return createOrUpdateUser(user);
                , err => 
                    if (err) 
                        throw err;
                    
                );
        , err => 
            throw err;
        );


    function doSignIn(user) 

        const onSuccess = user => 
            return res.redirect(req.cookies.target || '/keystone');
        ;

        const onFail = err => 
            if (err) throw err;
            return res.redirect('/');
        ;

        keystone.session.signin(String(user._id), req, res, onSuccess, onFail);
    

    function createOrUpdateUser(user) 
        if (user) 

            const userData = 
                email: authUser.email,
                services: user.services || 
            ;

            userData.services[authUser.type] = 
                isConfigured: true,
                profileId: authUser.profileId,
                username: authUser.username,
                avatar: authUser.avatar,
                accessToken: authUser.accessToken,
                refreshToken: authUser.refreshToken
            ;

            user.set(userData);

            user.save((err, user) => 
                if (err) throw err;
                return doSignIn(user);
            );

         else 

            const userData = 
                name: 
                    first: authUser.name.first,
                    last: authUser.name.last
                ,
                email: authUser.email,
                password: Math.random().toString(36).slice(-8),
                services: 
            ;

            userData.services[authUser.type] = 
                isConfigured: true,
                profileId: authUser.profileId,
                username: authUser.username,
                avatar: authUser.avatar,
                accessToken: authUser.accessToken,
                refreshToken: authUser.refreshToken
            ;

            const newUser = new User.model(userData);

            newUser.save((err, user) => 
                if (err) throw err;
                return doSignIn(user);
            );
        
    
;

【讨论】:

如何获得快速路线通过护照进行身份验证

】如何获得快速路线通过护照进行身份验证【英文标题】:Howtogetexpressroutetogothroughpassportforauthentification【发布时间】:2019-01-0119:27:30【问题描述】:我最近将在es6中制作的样板更改为稍旧的es5版本。我不得不重新创建导出,需... 查看详情

使用护照进行身份验证后,如何在 React FROM express 中重定向到用户仪表板

】使用护照进行身份验证后,如何在ReactFROMexpress中重定向到用户仪表板【英文标题】:HowdoIredirecttouserdashboardinReactFROMexpressafterauthenticatingwithpassport【发布时间】:2021-05-0912:08:30【问题描述】:我正在使用MERN堆栈构建一个应用程... 查看详情

如何修复阻止注册用户登录的护照本地身份验证错误

】如何修复阻止注册用户登录的护照本地身份验证错误【英文标题】:Howtofixpassportlocalauthenticationerrorthatpreventsregisteredusersfromloggingin【发布时间】:2021-01-1516:04:23【问题描述】:我花了一些时间来弄清楚为什么我的护照本地身份... 查看详情

Laravel 通过生成的令牌进行身份验证,无需护照和 jwt

】Laravel通过生成的令牌进行身份验证,无需护照和jwt【英文标题】:Laravelauthbygeneratedtokenwithoutpassportandjwt【发布时间】:2018-05-2810:12:09【问题描述】:我正在尝试通过在laravel5.5中使用md5加密方法从登录用户的用户名中检查生成... 查看详情

快速护照检查用户是不是已通过身份验证

】快速护照检查用户是不是已通过身份验证【英文标题】:expresspassportcheckifuserisauthenticated快速护照检查用户是否已通过身份验证【发布时间】:2018-12-2117:08:46【问题描述】:我正在使用护照登录并显示“/home”。登录有效并重... 查看详情

带有请求承诺的 NodeJS 发布请求以进行 Twitch 身份验证

...对用户进行身份验证。我似乎无法正确获得request.post()(使用请求承诺)。我尝试了许多不同的变体,并且通常在服务器日志中收到“未处理 查看详情

如何使用 oauth2 通过 REST Web 服务进行身份验证

】如何使用oauth2通过RESTWeb服务进行身份验证【英文标题】:Howtoauthenticatewithrestwebserviceusingoauth2【发布时间】:2016-01-2720:20:51【问题描述】:您好,我有一个实现oauth2.0的休息网络服务。现在我的Web应用程序有一个登录名,目前... 查看详情

节点护照错误:未知身份验证策略“本地登录”

】节点护照错误:未知身份验证策略“本地登录”【英文标题】:nodespassportError:Unknownauthenticationstrategy"local-login"【发布时间】:2016-03-1117:47:07【问题描述】:我一直在尝试使用nodejs上的护照进行本地身份验证工作,据我... 查看详情

使用护照 jwt 进行身份验证

】使用护照jwt进行身份验证【英文标题】:authenticationusingpassportjwt【发布时间】:2016-10-0218:06:34【问题描述】:我是基于令牌的身份验证的新手。我想将用户限制在我网站上的特定页面(检查他的身份验证),并看到jwt是实现它... 查看详情

如何使用 graphql 和护照设置身份验证但仍使用 Playground

】如何使用graphql和护照设置身份验证但仍使用Playground【英文标题】:Howtosetupauthenticationwithgraphql,andpassportbutstillusePlayground【发布时间】:2020-12-0813:21:20【问题描述】:向我们的后端Graphql服务器添加身份验证后,“Schema”和“Docs... 查看详情

使用 JWT 进行护照身份验证:如何将护照的默认未经授权响应更改为我的自定义响应?

】使用JWT进行护照身份验证:如何将护照的默认未经授权响应更改为我的自定义响应?【英文标题】:PassportauthenticationwithJWT:HowcanIchangepassport\'sdefaultunauthorizedresponsetomycustomresponse?【发布时间】:2019-05-3020:08:26【问题描述】:我... 查看详情

如何使用护照发送成功重定向的用户个人资料数据?

】如何使用护照发送成功重定向的用户个人资料数据?【英文标题】:howtosenduserprofiledataonsuccessredirectwithpassport?【发布时间】:2018-03-1610:31:51【问题描述】:我对Node.js还是很陌生,我正在学习使用护照进行身份验证,在我的节... 查看详情

新用户注册后立即进行护照认证

】新用户注册后立即进行护照认证【英文标题】:PassportAuthenticationimmediatelyafterNewUserRegistration【发布时间】:2013-07-3105:27:03【问题描述】:我正在尝试在/register表单上提交POST后立即对用户进行身份验证和登录。理想情况下,我... 查看详情

我们如何通过自定义登录屏幕绕过 Salesforce 登录屏幕进行身份验证?

】我们如何通过自定义登录屏幕绕过Salesforce登录屏幕进行身份验证?【英文标题】:Howcanwebypasssalesforceloginscreenforauthenticationbycustomloginscreen?【发布时间】:2021-02-0108:04:16【问题描述】:我们需要身份验证功能而不使用Salesforce登... 查看详情

如何在通过 Redux 操作进行身份验证后重定向用户?

】如何在通过Redux操作进行身份验证后重定向用户?【英文标题】:HowtoredirectuserafterauthenticationfromReduxaction?【发布时间】:2019-06-0614:47:22【问题描述】:我在Redux文件中使用firebase来验证我的用户。但是如何将他从登录页面重定... 查看详情

通过 nodejs 上的 express 服务器通过护照登录,使用 mongoose 连接 mongoDB

】通过nodejs上的express服务器通过护照登录,使用mongoose连接mongoDB【英文标题】:logginginviapassportbyanexpressserverontopofnodejs,usingmongoosetoconnectwithmongoDB【发布时间】:2021-07-1610:03:08【问题描述】:我对身份验证和授权很陌生,我正在... 查看详情

如何使用 Firebase 进行“使用 Spotify 登录”身份验证系统?

】如何使用Firebase进行“使用Spotify登录”身份验证系统?【英文标题】:Howtomakea\'loginwithSpotify\'authenticationsystemusingFirebase?【发布时间】:2016-08-2814:29:19【问题描述】:我有一个网页,我想让它仅在用户使用他们的Spotify帐户登录... 查看详情

在与 Scrapy 进行身份验证的登录会话后使用 Selenium

】在与Scrapy进行身份验证的登录会话后使用Selenium【英文标题】:UsingSeleniumafterauthenticatedloginsessionwithScrapy【发布时间】:2016-11-1801:22:31【问题描述】:环顾四周,似乎如果您通过Scrapy登录网站,如果您尝试在蜘蛛中使用Selenium,... 查看详情