我有一臺遠程 Ubuntu 機器運行帶有 next.js 的節點服務器并使用 next-auth 進行身份驗證。在本地使用 HTTP 一切正常。
配置
這是在 HTTPS 上運行節點服務器并使用 next.js 的代碼。
const https = require('https');
const fs = require('fs');
const next = require('next')
const port = 3000;
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev, dir: __dirname })
const handle = app.getRequestHandler()
const { parse } = require('url');
const options = {
key: fs.readFileSync('./path/to/private-key'),
cert: fs.readFileSync('./path/to/csr'),
ca: [fs.readFileSync('./path/to/gdroot-g2')]
};
app.prepare().then(() => {
https.createServer(options, (req, res) => {
const parsedUrl = parse(req.url, true);
handle(req, res, parsedUrl);
}).listen(port, err => {
if (err) throw err
console.log(`> Ready on localhost:${port}`)
})
})
服務器在 3000 埠上運行,所以我曾經sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 3000
將請求重定向到 443。
我購買了注冊的豪華 SSL 證書example.com
,還購買了域名,其中有一條 A 記錄指向服務器的 ip。
這是服務器的/etc/hosts
檔案(不包括 IPv6 主機)。
127.0.0.1 localhost
192.XXX.XXX.XX server.example.com server
在我的.env
中,我設定NEXTAUTH_URL=https://example.com:3000
了為了讓它在那里發送它的請求。
問題
在生產版本中,當 next-auth 嘗試獲取用戶的會話時,它會使用域名(例如:)從服務器向自身發送一個 HTTPS 請求example.com
。然后服務器出錯request to https://mDomain.com:3000/api/auth/session failed, reason: unable to verify the first certificate
。
如果我更改NEXTAUTH_URL=https://example.com
(沒有埠),節點會改為錯誤request to https://example.com/api/auth/session failed, reason: connect ECONNREFUSED 192.XXX.XXX.XX:443
。
同樣,如果我使用 curl ( curl https://example.com:3000/api/auth/session
),curl 會回應,curl: (60) SSL certificate problem: unable to get local issuer certificate
并且節點甚至不會收到請求(因此節點永遠不會出錯)。
請注意,如果我從我自己的機器上使用 curl,它會發送請求并且節點接收它但會立即拋出request failed, unable to verify...
錯誤(我相信這是因為證書從我的機器到服務器有效,但是從服務器到服務器的后續請求導致錯誤)。
我嘗試設定NEXTAUTH_URL_INTERNAL但錯誤是相同的(我嘗試將其設定為域名、IP 地址和本地主機)。但是,我認為這不是問題的真正根源。
看來問題的根源是當服務器收到自己的HTTPS請求時,域名不匹配example.com
(可能來自127.0.0.1:3000
或它的IP地址),因此無法驗證它。當發件人是另一臺機器時,所有 HTTPS 請求都有效。
我能想到的唯一解決方案是在服務器上為 localhost 創建一個自簽名證書(然后我可以指向 next-auth 在內部使用 localhost)。這將要求服務器使用 2 個 SSL 證書,這也可能是不可能的。然而,根據 next-auth,一切都應該在 HTTPS 上正常作業,所以希望我剛剛做了一個可修復的錯誤配置。
感謝您的幫助,如果您對解決方案有任何想法,請告訴我。
更新
我對 NEXTAUTH_URL_INTERNAL 進行了更多實驗,發現如果我在埠 3000 上啟動 HTTPS 服務器并在埠 3001 上啟動 HTTP 服務器并設定NEXTAUTH_URL_INTERNAL=http://127.0.0.1:3001
它確實有效。
但是,在 3001 埠上擁有一個 HTTP 服務器(用戶仍然可以連接到該埠)并允許 next-auth 在內部使用 HTTP,這不是一個安全漏洞嗎?是否可以NEXTAUTH_URL_INTERNAL=https://127.0.0.1:3000
為 localhost 擁有并自簽名證書?或者這也是一個漏洞?
請注意,目前,如果沒有 localhost 的自簽名證書,如果我設定NEXTAUTH_URL_INTERNAL=https://127.0.0.1:3000
然后節點錯誤為request to https://127.0.0.1:3000/api/auth/session failed, reason: Hostname/IP does not match certificate's altnames: IP: 127.0.0.1 is not in the cert's list:
. 也許我可以將 localhost 添加到 altnames 中?或者甚至是服務器的IP?
uj5u.com熱心網友回復:
我最終通過在一個單獨的埠上運行另一個 HTTPS 服務器(用于下一個相同的應用程式)來修復它,并為 localhost 提供自簽名證書。然后我設定NEXTAUTH_URL_INTERNAL
在該埠上查詢本地主機。我還必須使用mkcert創建自己的 CA。默認情況下,節點的 fetch 無法識別我的自定義 CA,所以我添加NODE_EXTRA_CA_CERTS="/path/to/rootCA.pem
到/etc/environment
.
所有這些都允許 next-auth 通過 HTTPS 查詢 localhost 并驗證證書(即使它是自簽名的)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/468964.html