# Cross-Origin, Cross-Site, and Cookie ## Same Origin and Same Site 區分 `https://site.com/myblog` Origin: `https://site.com`,定義:`scheme`, `host`, `port` 的部分 Site: `site.com`,定義: eTLD Length(.com) + 1 的區域 | Same Site? | Same Origin? | Domain A | Domain B | | -------------------------------------------------------------- | ----------- | ----------------------------- | --------------------- | | X | X | http://daniel840829.github.io | http://github.io | | X | X | http://google.com | http://google.io | | O(如果 chrome://flags/#schemeful-same-site 設定是開啟的則是 X) | X | https://site.com | http://site.com | | 同上 | X | http://site.com:80 | http://site.com:433 | | O | X | http://www.web.dev | http://static.web.dev | ## Access-Control-Allow-Credentials 與 Request.withCredentials 先來看ㄧ下 credential 的定義: > Credentials are actually cookies, authorization headers or TLS(Transport Layer Security) client certificates. 也就是說若不符合規範的 `cookie` 和帶了`Access-Control-*` 的 request 會被擋下 Access-Control-Allow-Credentials 定義: > The Access-Control-Allow-Credentials header is used to tell the browsers to expose the response to front-end JavaScript code when the request’s credentials mode Request.credentials is “include”. request.withCredentials: 1. js 發送 request 時帶入的參數 1. false 會將 response 回傳的 credential 忽略,request 也不帶入 credential,也因此 cookie 和 Access-Control-* 會失效 ### 情況整理 | 情況 | withCredential | Allow Credential | Allow Origin | | ------------------------------------------------------------ | -------------- | ---------------- | ------------ | | request 不會帶入 credential 的資訊,不過可以正常發送 request | false | - | | | 會被 chrome 擋下,因為 Allow Credential = false 代表不支援 | true | false | | | Chrome 會擋下,不能是 wildcard | true | true | `*` | ### Cookie 的 attributes 也會影響 browser 是否阻擋此 Cookie withCredential 是 true 且 request 沒有被阻擋的情況下 Cookie 用以下特性可以被傳送到 browser Chrome 未來會, | Samesite | Secure | Method | HTTP Only | | -------- | ------ | ------------------------------------------------- | --------- | | None | Must be true | - | - | | Lax | - | Must Top level navigation(GET 或 img 等 html tag) | - | | strict | - | 必須符合samesite 定義,否則一律阻擋 | - | ### 踩雷經驗 使用 Chrome ver. 80 時發生的,80 版沒有設定會被當成 SameSite=Lax,後來因為疫情而延期救了我一命 :tongue: 使用金流等第三方服務會有問題的案例: 總是在付完款之後就被登出了,以下還原案發現場: 1. 用戶已登入,瀏覽器上有 session cookie = 1 1. 用戶按下付款,導入金流服務頁面付款 1. 金流服務的前端頁面使用 POST Method 來將用戶已付款的訊息通知 Server ( cross-site 所以不帶入 cookie ) 1. server 將你導回付款完成的頁面,因為不知道你是誰所以回傳一個全新的 session cookie = 2 1. 恭喜登出 :laughing: 趕快在 Cov-19 的帶領之下,好好檢視自己的 Cookie 設定XD ## 最後 若需要架設 github.io 個人頁又需要串接自己的服務,肯定 cros-origin 跟 cros-site 都會遇到, 這邊整理一下: 若是 Cookie 沒出現需要先分清楚什麼是後端該設定的和前端該設定的,與是 request 還是 cookie 被阻擋,Cookie 是被阻擋還是因為設定了 `HttpOnly`而前端沒拿到 後端: 1. header in response `Access-Control-Allow-Credentials` 1. Cookie attibutes SameSite and Secure 前端:`withCredentials: true` 而如果是 Cross Orgin request 的問題,則會牽涉到 browser 是否發送 prefilght 驗證,之後有時間會再整理 --- 參考: https://www.geeksforgeeks.org/http-headers-access-control-allow-credentials/ https://developer.mozilla.org/zh-TW/docs/Web/API/XMLHttpRequest/withCredentials https://web.dev/same-site-same-origin/