代理 Firebase 函数的跨域状态 cookie 问题 [英] Cross domain state cookie issue with proxied Firebase Functions

查看:73
本文介绍了代理 Firebase 函数的跨域状态 cookie 问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用此示例开发了 oAuth 登录.如果在浏览器中禁用第三方 cookie(现在默认情况下),遇到的第一个问题是状态 cookie 验证.正如这个答案所建议的那样,我代理了这些功能.

I developed a oAuth login using this example. The problem first problem encountered was the state cookie validation if third-party cookies are disabled in the browser (now by default). As suggested by this answer, I proxied the functions.

所以我使用托管重写来代理函数,所以你在同一个域中,第一个重定向函数设置的服务器 cookie 似乎与应用程序在同一个域中.所以这就是发生的事情

So I proxied the functions using Hosting rewrites so you are in the same domain and the server cookie that the first redirect function sets seems to be in the same domain as the app. So this is what happens

  1. 用户被重定向到设置 cookie 并将用户重定向到第三方身份验证提供商的云函数
  2. 用户登录
  3. 用户再次被重定向到应用程序,应用程序获取授权码并将用户重定向到令牌函数
  4. token 函数尝试读取状态 cookie,但根本没有 cookie

当我尝试从令牌函数中读取 cookie 时

When I try to read the cookies from the token function

[Object: null prototype] {}

这是托管重写

"hosting": {
...
"rewrites":  [
  {
    "source": "/redirect",
    "function": "redirect"
  },
  {
    "source": "/token**",
    "function": "token"
  },
  {
    "source": "**",
    "destination": "/index.html"
  }
],

这是重定向功能

exports.redirect = functions.https.onRequest((req, res) => {
  cookieParser()(req, res, () => {
    const redirect_uri = `https://${process.env.GCLOUD_PROJECT}.firebaseapp.com/auth.html`
    const state = req.cookies.state || crypto.randomBytes(20).toString('hex')
    const authorizationUri = fedidClient().authorizationCode.authorizeURL({
      redirect_uri: redirect_uri,
      scope: OAUTH_SCOPES,
      state: state,
    })
    res.cookie('state', state.toString(), {
      maxAge: 3600000,
      secure: true,
      httpOnly: true,
    })
    res.redirect(authorizationUri)
  })
})

这是令牌函数

exports.token = functions.https.onRequest((req, res) => {
  const redirect_uri = `https://${process.env.GCLOUD_PROJECT}.firebaseapp.com/auth.html`  
  try {
    return cookieParser()(req, res, async () => {
        if (!req.cookies.state) {
          throw new Error(
            'State cookie not set or expired. Maybe you took too long to authorize. Please try again.'
          )
        }
      const tokenConfig = {
        code: req.query.code,
        redirect_uri: redirect_uri,
        scope: OAUTH_SCOPES,
      }
      const result = await fedidClient().authorizationCode.getToken(tokenConfig)
      const accessToken = fedidClient().accessToken.create(result)

      let user = {}
      await getUserInfo(accessToken)
        .then((result) => result.json())
        .then((json) => (user = json))

      // Create a Firebase account and get the Custom Auth Token.
      const firebaseToken = await createFirebaseAccount(
        user.uid,
        user.displayName,
        user.mail,
        accessToken.token.access_token
      )

      res.jsonp({
        token: firebaseToken,
      })
    })
  } catch (error) {
    return res.status(500).jsonp({ error: error.toString })
  }
})    

为什么cookie没有通过第二个云函数?如果禁用重写并启用第三方 cookie,则代码可以正常工作.

Why the cookie is not passed through the second cloud function? The code works correctly if rewrites are disabled and third-party cookies are enabled.

推荐答案

您可能无意中发现了 Firebase 托管中的缓存功能,该功能会去除除 __session 之外的所有 cookie.

You've probably inadvertently discovered the caching feature in Firebase Hosting that strips all cookies except __session.

将 Firebase 托管与 Cloud Functions 或 Cloud 一起使用时运行,cookie 通常从传入的请求中剥离.这是允许有效的 CDN 缓存行为所必需的.只有允许特殊命名的 __session cookie 传递到执行您的应用.

When using Firebase Hosting together with Cloud Functions or Cloud Run, cookies are generally stripped from incoming requests. This is necessary to allow for efficient CDN cache behavior. Only the specially-named __session cookie is permitted to pass through to the execution of your app.

来源

尝试将您的 cookie 重命名为 __session,看看是否能解决问题.

Try renaming your cookie to __session and see if that fixes it.

这篇关于代理 Firebase 函数的跨域状态 cookie 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆