Để cung cấp quy trình xác thực mượt mà, phù hợp với bối cảnh trên nhiều miền, các tổ chức thường nhúng trang đăng nhập vào iframe. Tuy nhiên, việc tải các bối cảnh xác thực bên trong khung hình của bên thứ ba sẽ khiến người dùng gặp phải các mối đe doạ nghiêm trọng như clickjacking (sửa đổi giao diện người dùng) và việc tạo thông tin đăng nhập trái phép. Để giảm thiểu những rủi ro này, theo mặc định, các trình duyệt sẽ tắt WebAuthn trong iframe trên nhiều nguồn gốc. Để gỡ bỏ quy định hạn chế này một cách an toàn, bạn cần có các giao thức bảo vệ chuyên sâu đang hoạt động.
Xác định các mô hình mối đe doạ
Trước khi bật khoá truy cập (WebAuthn) bên trong khung phụ, hãy tìm hiểu các trường hợp sử dụng sai mà bạn đang chống lại:
- Theo dõi bằng cách chèn iframe ẩn: Kẻ tấn công kích hoạt lời nhắc WebAuthn từ miền của chính chúng bằng cách sử dụng quảng cáo hoặc tiện ích trên một trang web đáng tin cậy, lừa người dùng uỷ quyền khoá truy cập mà không thấy ngữ cảnh. Điều này liên kết danh tính của người dùng với một tài khoản do kẻ tấn công kiểm soát để thu thập dữ liệu.
- Lớp phủ trực quan và tấn công bằng cách nhấp chuột (điều chỉnh giao diện người dùng): Một trang mẹ độc hại sẽ hiển thị iframe xác thực ở chế độ ẩn bằng cách sử dụng CSS tiêu chuẩn và phủ một phần tử giao diện người dùng giả mạo để đánh cắp một lượt nhấp kích hoạt quy trình xác thực. Điều này có thể dẫn đến việc chiếm đoạt phiên hoặc buộc thực hiện các hành động trái phép nếu người dùng vô tình hoàn tất lời nhắc.
Để đối phó với những mối đe doạ này, hãy làm theo các phương pháp hay nhất sau đây:
Đối với tài liệu cấp cao nhất (khung trên cùng):
Đối với tài liệu được nhúng (iframe):
- Bật cookie được phân vùng của bên thứ ba
- Bảo vệ điểm cuối bằng Chính sách bảo mật nội dung
- Tin tưởng nhưng xác minh phía máy chủ
Đối với cả hai tài liệu:
Bật tính năng uỷ quyền bằng Chính sách về quyền
Theo mặc định, các trình duyệt sẽ chặn quyền truy cập vào WebAuthn trong iframe trên nhiều nguồn gốc. Permissions Policy (Chính sách về quyền) là cơ chế nền tảng web hợp nhất cho phép một tài liệu cấp cao nhất uỷ quyền rõ ràng những chức năng mạnh mẽ này cho các nguồn gốc cụ thể, đáng tin cậy của bên thứ ba.
Mã thông báo tính năng
WebAuthn sử dụng 2 mã thông báo riêng biệt:
publickey-credentials-get: Cấp quyền cho quy trình đăng nhập bằng khoá truy cập (navigator.credentials.get()).publickey-credentials-create: Cấp quyền uỷ quyền cho quy trình đăng ký khoá truy cập (navigator.credentials.create()).
Điều kiện để bật
Để bật các chức năng này, bạn cần phải điều chỉnh cả phản hồi của máy chủ gốc và mã đánh dấu phía máy khách:
- Tiêu đề phản hồi HTTP theo chính sách về quyền (trang web máy chủ mẹ): Trang mẹ phải khai báo các nguồn gốc được phép trong tiêu đề phản hồi HTTP bằng cú pháp Trường có cấu trúc.
Permissions-Policy: publickey-credentials-get=(self "https://embedded-auth.example.com")
Chính sách về quyền: khả năng tương thích publickey-credentials-get:
Chính sách về quyền: khả năng tương thích publickey-credentials-create:
- Thuộc tính
allowcủa HTML: Trong mã đánh dấu HTML, phần tử<iframe>cũng phải khai báo rằng phần tử này bật tính năng.
<iframe src="https://embedded-auth.example.com?nonce=deadbeef12345678&client=https%3A%2F%2Fembedded-auth.example.com" allow="publickey-credentials-get"></iframe>
Khả năng tương thích của iframe allow="publickey-credentials-get":
Browser Support
Khả năng tương thích của iframe allow="publickey-credentials-create":
Browser Support
Bật cookie được phân vùng của bên thứ ba
Để đảm bảo quy trình xác thực đáng tin cậy, bạn phải thiết lập và duy trì một phiên trong iframe nhiều nguồn gốc được nhúng. Khi các trình duyệt hiện đại chuyển sang các quy định hạn chế nghiêm ngặt đối với cookie của bên thứ ba, các cơ chế duy trì tiêu chuẩn thường bị chặn theo mặc định và có thể yêu cầu gọi Storage Access API (API Truy cập bộ nhớ) để có quyền truy cập.
Để giảm thiểu những trở ngại này, hãy định cấu hình cookie phiên bằng các thuộc tính SameSite:
None, Secure và Partitioned. Cơ chế nền tảng hợp nhất này đảm bảo trạng thái liên tục trong iframe trong khi vẫn tuân thủ các chế độ kiểm soát quyền riêng tư ở cấp trình duyệt.
Đặt SameSite: None
SameSite:
None đánh dấu rõ ràng một cookie để truy cập trên nhiều trang web, cho phép cookie đó được gửi cùng với các yêu cầu được thực hiện từ ngữ cảnh của bên thứ ba (chẳng hạn như iframe). Thuộc tính này là điều kiện tiên quyết để cookie hoạt động trong các trường hợp trên nhiều nguồn, mặc dù bạn phải kết hợp thuộc tính này với thuộc tính Secure để được các trình duyệt hiện đại chấp nhận.
Đặt Partitioned
Thuộc tính Partitioned chọn sử dụng CHIPS (Cookie có trạng thái được phân vùng độc lập), cho phép lưu trữ cookie riêng biệt cho từng trang web cấp cao nhất. Điều này đảm bảo cookie vẫn có thể truy cập trong ngữ cảnh iframe cụ thể của bên thứ ba, cho phép trạng thái phiên liên tục mà không cần bật tính năng theo dõi trên nhiều trang web. Người dùng sẽ phải đăng nhập lại cho từng thành phần được nhúng trên một trang web khác.
Bảo vệ điểm cuối bằng Chính sách bảo mật nội dung
Trong khi Chính sách về quyền xác định xem iframe của bạn có thể chạy WebAuthn hay không, thì Chính sách bảo mật nội dung (CSP) xác định ai được phép lưu trữ iframe của bạn.
Đối với một điểm cuối xác thực, điều quan trọng là phải đảm bảo rằng chỉ các trang web đối tác được uỷ quyền hoặc các tài sản của riêng bạn mới có thể tải khung con đăng nhập, ngăn chặn các nỗ lực tấn công bằng cách nhấp chuột trái phép ngay cả trước khi chúng có thể tải giao diện người dùng.
Sử dụng frame-ancestors
Chỉ thị frame-ancestors xác định các trang mẹ hợp lệ có thể nhúng trang web của bạn. Bằng cách thêm các miền vào chỉ thị này, bạn có thể cho phép những miền được phép nhúng khung phụ đăng nhập.
Content-Security-Policy: frame-ancestors 'self' https://parent-site.example.com;
Chính sách bảo mật nội dung: khả năng tương thích của frame-ancestors:
Đặt X-Frame-Options
Tiêu đề X-Frame-Options cũ hỗ trợ khả năng tương tự, nhưng chỉ hỗ trợ các lựa chọn nhị phân (DENY hoặc SAMEORIGIN). Đặt cả frame-ancestors và X-Frame-Options: DENY CSP trong trường hợp trình duyệt không hỗ trợ CSP. CSP luôn được ưu tiên ở những nơi được hỗ trợ.
X-Frame-Options: DENY
Khả năng tương thích X-Frame-Options:
Tin tưởng nhưng xác minh phía máy chủ
Các quy trình kiểm tra phía máy khách của trình duyệt đánh giá ý định và quyền, nhưng máy chủ là bên phân xử cuối cùng về độ tin cậy. Xác minh phản hồi trên máy chủ Bên phụ thuộc (RP) để đảm bảo ngữ cảnh hợp lệ và được ký.
Tải trọng dữ liệu phía máy khách
Dữ liệu ứng dụng WebAuthn bao gồm các tham số được thiết kế riêng để giúp bạn xác minh bối cảnh của một yêu cầu được thực hiện trong iframe:
crossOrigin(boolean): Cho biết liệu WebAuthn API có được gọi trong iframe trên nhiều nguồn gốc hay không. Nếu cấu trúc của bạn dựa vào iframe, thì máy chủ của bạn phải thực thi rằng cờ này làtrue.topOrigin(chuỗi): Nguồn gốc của bối cảnh duyệt web cấp cao nhất (nội dung hiển thị trên thanh địa chỉ của trình duyệt). Máy chủ phải xác minh điều này dựa trên danh sách các nguồn gốc đã biết và được uỷ quyền của cha mẹ.
Danh sách kiểm tra xác minh
Để xác minh phản hồi của trình xác thực trên máy chủ, hãy thực hiện các bước sau:
- Phân tích cú pháp và giải mã
collectedClientDatađã ký từ phản hồi của trình xác thực. - Đảm bảo
typekhớp với quy trình (webauthn.gethoặcwebauthn.create). - Xác minh sự hiện diện và chữ ký của người dùng.
- Nếu yêu cầu được gửi từ một cấu trúc iframe:
- Thực thi
crossOrigin === true. - Thực thi rằng
topOriginkhớp với danh sách nguồn gốc mẹ được uỷ quyền của bạn.
- Thực thi
Thiết lập các phiên một cách an toàn bằng cách sử dụng postMessage()
Để thiết lập một phiên một cách đáng tin cậy, iframe phải truyền mã thông báo xác thực trở lại trang mẹ bằng cách sử dụng postMessage(), cho phép trang mẹ quản lý trạng thái phiên với tư cách là bên thứ nhất.
Quy trình làm việc an toàn
Để thiết lập một phiên an toàn, hãy làm theo quy trình sau:
- Đảm bảo URL
srccủa iframe có chứa các tham số truy vấnnoncevàorigin:- Sử dụng một giá trị ngẫu nhiên cho
nonce.nonceđóng vai trò là mã xác minh bảo mật để đảm bảo rằng mã thông báo xác thực nhận được từ một iframe khớp một cách hợp lệ với phiên cụ thể do trang mẹ khởi tạo. - Sử dụng miền khung mẹ cho
origin. Tham sốoriginchỉ định nguồn gốc của trang mẹ, cho phép iframe xác định một cách an toàn ngữ cảnh được uỷ quyền mà trong đó iframe đã được nhúng.
- Sử dụng một giá trị ngẫu nhiên cho
- iframe hoàn tất quy trình xác thực WebAuthn bằng máy chủ riêng.
Máy chủ iframe phát hành một mã thông báo (chẳng hạn như JWT) bao gồm
noncevà chuyển tiếp đến trang chính.// Extract nonce and origin from the URL params const urlParams = new URLSearchParams(window.location.search); const nonce = urlParams.get('nonce'); const origin = urlParams.get('origin'); if (!nonce || !origin) { alert('Nonce or origin is missing in the URL'); return; } // Create a JWT const response = await post('/createToken', { nonce, origin }); const token = response.token; // Post the JWT to the parent frame window.parent.postMessage({ token }, origin);Trang gốc theo dõi sự kiện
message, xác thực nguồn gốc của người gửi và xác minh mã thông báo.window.addEventListener("message", (event) => { if (event.origin !== "https://embedded-auth.example.com") return; // Verify the received JWT const result = await post('/verifyIdToken', { token: event.data.token, origin: provider.origin, }); });Trang mẹ sẽ duy trì phiên nếu JWT được xác minh thành công.
Cả người gửi và người nhận đều có trách nhiệm bảo mật:
- Người gửi (iframe): Luôn chỉ định nguồn đích nghiêm ngặt khi gửi thông báo (không bao giờ sử dụng
"*"). - Người nhận (cha mẹ): Luôn xác minh
event.originkhi nhận tin nhắn để ngăn chặn hành vi giả mạo nguồn gốc.
Kết luận
Việc sử dụng iframe an toàn phụ thuộc vào Chính sách về quyền để bật, CSP để hạn chế, cookie phân vùng của bên thứ ba để duy trì phiên, xác minh phía máy chủ về bối cảnh của ứng dụng và chuyển giao phiên theo bối cảnh bằng cách sử dụng postMessage().
Để tìm hiểu thêm về các chủ đề liên quan, hãy theo dõi blog của nhà phát triển Chrome của Google và khám phá thêm các tài nguyên tại tài liệu về Danh tính nhà phát triển Chrome.