【问题标题】:Why passport authentication seems to work only in local?为什么护照认证似乎只在本地有效?
【发布时间】:2021-01-08 17:33:24
【问题描述】:

我有一个 Node.js 后端服务和一个 React 前端。它一直工作到今天,当我再次遇到与 CORS 相关的问题时。它在我的本地环境中运行良好,但是当我将它部署到 App Engine 时,CORS 问题仍然存在。这里缺少什么?

这是我的代码:

Node.JS 后端服务:

const app = express();

/* MIDDLEWARE USER: set up cors to allow us to accept requests from our client */
app.use(
    cors({
      origin: process.env.CLIENT_URL || 'http://localhost:3001', // allow to server to accept request from different origin
      methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
      credentials: true, // allow session cookie from browser to pass through
    }),
);

我正在使用护照从 Google 获取凭据并传递到服务器

/* MIDDLEWARE USE: use Session Middleware */
const MAX_AGE = process.env.MAX_AGE || 60 * 60 * 1000;
const SECRET = process.env.SECRET || 'Our Secret';
const DEFAULT_ENV = process.env.NODE_ENV || 'development';
app.use(session({
  cookie: {
    maxAge: MAX_AGE,
    secure: DEFAULT_ENV === 'production',
    // secure: true,
    httpOnly: true,
  },
  secret: SECRET,
  resave: false,
  saveUninitialized: false,
  // store: new FileStore(fileStoreOptions),
  store: new FirestoreStore({
    dataset: new Firestore({
      kind: 'express-sessions',
    }),
  }),
}));

/* MIDDLEWARE USE: use Passport Middleware */
app.use(passport.initialize());
app.use(passport.session());

然后我在前端使用 react 和 redux,这里的代码从我的端点获取凭据。

/* RETRIEVE INFO FROM OAUTH AS SOON USER CLICK ON LOGIN WITH GOOGLE */
export const loginWithGoogle = () => {
  return (dispatch) => {
    dispatch({type: FETCH_START});
    axios.post('/auth/login/oauth/success').then(({data}) => {
      // console.log('userSignInFromGoogle: ', data);
      if (data) {
        const {originalMaxAge} = data.session.cookie;
        const expireDate = (new Date()).getTime() + originalMaxAge;

        localStorage.setItem('token', JSON.stringify(data.result.accessToken));
        localStorage.setItem('token_expires_in', JSON.stringify(expireDate));

        axios.defaults.headers.common['Authorization'] = 'Bearer ' +
            data.result.accessToken;

        dispatch({type: FETCH_SUCCESS});
        // dispatch({type: USER_DATA, payload: data.result});
        dispatch({type: USER_TOKEN_SET, payload: data.result.accessToken});
      } else {
        dispatch({type: FETCH_ERROR, payload: data.error});
      }
    }).catch(function(error) {
      dispatch({type: FETCH_ERROR, payload: error.message});
      // console.log('Error****:', error.message);
    });
  };
};

/* FUNCTION TO FETCH DATA FROM THE AUTHENTICATED USER */
export const getAuthenticatedUser = () => {
  return (dispatch) => {
    dispatch({type: FETCH_START});
    isTokenExpired();
    axios.post('auth/me',
    ).then(({data}) => {
      // console.log('userSignIn: ', data);
      if (data.result) {
        dispatch({type: FETCH_SUCCESS});
        dispatch({type: USER_DATA, payload: data.result});
      } else {
        dispatch({type: FETCH_ERROR, payload: data.error});
      }
    }).catch(function(error) {
      dispatch({type: FETCH_ERROR, payload: error.message});
      // console.log('Error****:', error.message);
      if (error) {
        dispatch({type: SIGNOUT_USER_SUCCESS});
        localStorage.removeItem('token');
        localStorage.removeItem('token_expires_in');
      }
    });
  };
};

在这里我定义了 axios 的端点:

import axios from 'axios';
/* TODO: Change In production with this */
export default axios.create({
  withCredentials: true,
  baseURL: `backend-url`,//YOUR_API_URL HERE
  headers: {
    'Content-Type': 'application/json',
  },
});

【问题讨论】:

  • 你得到什么错误信息?
  • 我在向后端服务进行身份验证时收到 401 错误。
  • 401 表示您不是在处理 CORS 错误,而是在处理身份验证问题。
  • 是的,401是登录函数抛出的错误。由于 Chrome 的新限制,问题在于在没有“sameSite”属性的情况下存储 cookie。如果您有兴趣,我在下面发布了答案,我会修复问题标题。

标签: node.js reactjs cors passport.js


【解决方案1】:

经过一些测试以找出问题所在,我终于在各种浏览器上测试了这段代码,然后只有 Chrome 显示这个问题,没有将令牌从后端服务器传递到另一台服务器。最后我修改了与会话存储相关的代码sn-p,将“sameSite”属性添加到cookie中。 Chrome 在最新版本中要求指定此属性,否则它会阻止从服务器到服务器的 cookie。

/* MIDDLEWARE USE: use Session Middleware */
const MAX_AGE = process.env.MAX_AGE || 60 * 60 * 1000;
const SECRET = process.env.SECRET || 'Our Secret';
const DEFAULT_ENV = process.env.NODE_ENV || 'development';
app.use(session({
  cookie: {
    maxAge: MAX_AGE,
    secure: DEFAULT_ENV === 'production',
    httpOnly: true,
    /*TODO: Fix for chrome*/
    sameSite: 'none',
  },
  secret: SECRET,
  resave: false,
  saveUninitialized: false,
  // store: new FileStore(fileStoreOptions),
  store: new FirestoreStore({
    dataset: new Firestore({
      kind: 'express-sessions',
    }),
  }),
}));

【讨论】:

    猜你喜欢
    • 2016-10-12
    • 2015-09-23
    • 1970-01-01
    • 2018-04-20
    • 1970-01-01
    • 1970-01-01
    • 2022-08-05
    • 2016-12-28
    • 2016-10-19
    相关资源
    最近更新 更多