用作我的自定义 OIDC 提供商前端的 Angular SPA 未将会话 cookie 发送到我的后端/登录 API

问题描述 投票:0回答:1

塞纳里奥

我有两个角度应用程序,第一个是

angular_shop
,它使用
/auth
端点作为自定义node_oidc_provider来启动身份验证请求

node_oidc_provider 检查来自

angular_shop
的 PKCE 代码并重定向到第二个角度应用程序
angular_oidc_frontend
,它充当使用 node_oidc_provider

创建的自定义身份提供程序的前端

我可以看到重定向到

http:localhost:4200/signin?uid=WIkb3oodGHMOTgg4mlkyQ
已成功完成

但是现在我有两个问题

  1. 首次加载角度应用程序时,
    node_oidc_provider
    设置的会话cookie在chrome的应用程序选项卡中不可见,但如果我刷新角度应用程序页面,则可以看到。

  1. 第二个问题是,即使 cookie
    sameSite
    设置为
    None
    ,当我将登录详细信息提交到
    localhost:8081/api/v1/sigin
    端点到使用
    node_oidc_provider
    创建的 idp 服务器时,两个可见的 cookie 也不会发送到服务器

这是我在服务器上记录的

/signin
端点的请求和响应标头

    Received headers: {
  'accept-language': 'en-GB,en-US;q=0.9,en;q=0.8',
  'accept-encoding': 'gzip, deflate, br',
  referer: 'http://localhost:4200/signin?uid=PbR6zZdrqGsDauDy-Sb1X',
  'sec-fetch-dest': 'empty',
  'sec-fetch-mode': 'cors',
  'sec-fetch-site': 'same-origin',
  origin: 'http://localhost:4200',
  'sec-ch-ua-platform': '"macOS"',
  'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
  'sec-ch-ua-mobile': '?0',
  'content-type': 'application/json',
  accept: 'application/json, text/plain, */*',
  'sec-ch-ua': '"Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"',
  'content-length': '116',
  connection: 'close',
  host: 'localhost:8081'
}
Sent headers: [Object: null prototype] {
  'x-powered-by': 'Express',
  'access-control-allow-origin': 'http://localhost:4200',
  'access-control-allow-methods': 'GET, POST, OPTIONS, PUT, PATCH, DELETE',
  'access-control-allow-headers': 'X-Requested-With,content-type,Authorization,skip',
  'access-control-allow-credentials': 'true'
}

注意:最初我认为这一定是由于两个不同的来源 'http://localhost:4200

and
http://localhost:8081` 所以在 Angular cli 上使用以下设置设置代理

{
    "/temp": {
      "target": "http://localhost:8081",
      "secure": false,
      "pathRewrite": {
        "^/temp": ""
      },
      "logLevel": "debug",
      "changeOrigin":true,
      "cookieDomainRewrite":"localhost"
    }
  }

此外,角度应用程序还配置为发送

withCredentials: true 
端点。
/signin

后端其他配置如下

oidc-提供cookie配置:

const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }), withCredentials: true };

已创建自定义交互策略

cookies: { keys: ['ewdewdewdewdewdwd', 'dewdewdwedwedwedewd', 'dwedwedwdwd'], long: { signed: true, httpOnly: true, maxAge: 86400 * 1000, // 1 day in milliseconds // Add secure flag in production secure: process.env.NODE_ENV === 'production', // Add sameSite policy (strict, lax, or none) sameSite: 'none', }, short: { signed: true, httpOnly: true, // Add secure flag in production secure: process.env.NODE_ENV === 'production', // Add sameSite policy (strict, lax, or none) sameSite: 'none', }, names: { session: '_session', interaction: '_interaction', resume: '_resume', state: '_state', }, },

创建的策略已修改为重定向到正确的网址

const interactions = policy(); interactions.add(new Prompt({ name: 'signin', requestable: true, check: async (ctx) => { // Here, you check if the user is already authenticated // If not, you'll prompt for login return !ctx.oidc.session || !ctx.oidc.session.accountId; }, }), 0);

这是我在服务器上的 CROS 配置

interactions: { policy: interactions, url(ctx, interaction) {console.info('interaction',interaction) return `${process.env.IDENTITY_FRONTEND_URL}/signin?uid=${interaction.uid}`; }, },

还有我的

app.use((req, res, next) => { // Website you wish to allow to connect res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200'); // Request method you wish to allow res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); // Request headers you wish to allow res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,Authorization,skip'); // Set to true if you need the website to include cookies in the request sent // to the API (e.g. in case you use sessions) res.setHeader('Access-Control-Allow-Credentials', 'true'); // Pass to the next layer of middleware next(); }); 终点


/signin

为了可见,服务器上由于未检测到

signIn: async (req, res, next) => { try { if (!req.isAuthenticated()) { return res.status(401).send('Authentication failed'); } const interactionId = req.body.uid || req.query.uid || req.params.uid ; if (!interactionId) { return res.status(400).send('Interaction token is missing'); } //console.info('req incoming',req); const details = await oidcProvider.interactionDetails(req, res); console.log(details); assert.equal(details.interaction.uid, interactionId); const { prompt: { name }, params, session } = details; if (name === 'signin') { // Assuming you have a method or a way to get accountId from req.user const accountId = req.user._id.toString(); // Use a unique identifier for the user const result = { login: { accountId }, }; await oidcProvider.interactionFinished(req, res, result, { mergeWithLastSubmission: false }); } else { res.status(400).send('Unsupported interaction type'); } } catch (error) { console.error(error); res.status(500).send('An error occurred during authentication'); } }, 而发生错误


cookie

还在生产中,我计划使用 
{ allow_redirect: true, error: 'invalid_request', status: 400, statusCode: 400, expose: true, error_description: 'interaction session id cookie not found', error_detail: undefined }

来反向代理 angular_oidc_frontend 应用程序和 ipd nodejs api 从同一域提供服务,以解决

nginx
cookie 问题。
对长篇文章深表歉意,对应用程序之间的这种复杂流程进行简短解释有点棘手,我正在实现的是(授权代码流程)使用

sameSite

创建的自定义idp(身份服务提供商)服务器中的oidc
    

angular cookies openid-connect samesite node-oidc-provider
1个回答
0
投票
node_oidc_provider

,这意味着它只会以

/signin
开头的请求发送

Cookie path但是登录详细信息会发送到

localhost:4200/signin

,因此 cookie 将被忽略

将 cookie 路径更改为 

localhost:4200/api/v1/signin

应该可以解决问题。

    

© www.soinside.com 2019 - 2024. All rights reserved.