7 phương pháp hay nhất để bảo mật REST API: Xác thực và ủy quyền
Hầu hết các ứng dụng sử dụng web framework hiện đại sẽ có một hoặc nhiều REST API, đây là một cách đơn giản và linh hoạt để cấu trúc một API web. FUNiX sẽ giới thiệu 7 phương pháp hay nhất để bảo mật REST API: Xác thực và ủy quyền (Authentication và authorization) ở bài viết dưới đây.
Table of Contents
>> Đơn giản hóa và bảo mật thông tin đăng nhập trực tuyến với YubiKey
>> 7 Bí kíp bảo mật điện thoại cần thực hiện ngay bây giờ
Rest – Representational State Transfer – là một dạng chuyển đổi cấu trúc, thường sử dụng phương thức HTTP để tạo ra giao tiếp giữa các máy.
API – Application Programming Interface – tập hợp bao gồm những cơ chế và quy tắc tạo ra sự tương tác giữa một ứng dụng hoặc một thành phần nào đó với một ứng dụng hoặc một số thành phần khác.
Hầu hết các ứng dụng sử dụng web framework hiện đại sẽ có một hoặc nhiều REST API, đây là một cách đơn giản và linh hoạt để cấu trúc một API web. Nó không phải là một tiêu chuẩn hay giao thức, mà là một tập hợp các ràng buộc về kiến trúc.
Bất kỳ API nào cũng đều có thể bị lạm dụng bởi các tác nhân độc hại, do đó cần có chính sách để bảo mật nó.
Luôn sử dụng TLS
Mọi API web nên sử dụng TLS (Transport Layer Security – Bảo mật lớp truyền tải). TLS bảo vệ thông tin mà API gửi đi và nhận từ người dùng bằng cách mã hóa các tin nhắn khi chúng được chuyển tiếp. Tiền thân của TLS có tên là SSL (Secure Sockets Layer – Lớp socket bảo mật). Chúng ta nhận biết một trang web đã bật TLS khi URL của nó bắt đầu bằng https:// thay vì http://.
Nếu không có TLS, bên thứ ba có thể chặn và đọc thông tin nhạy cảm khi chuyển tiếp, như thông tin đăng nhập REST API và dữ liệu cá nhân. Điều này sẽ làm suy yếu bất kỳ biện pháp xác thực nào của chúng ta.
TLS yêu cầu một chứng chỉ có hiệu lực, để cho người dùng biết rằng API này là hợp pháp và được bảo vệ. Hầu hết các nhà cung cấp điện toán đám mây và dịch vụ lưu trữ sẽ quản lý chứng chỉ và bật TLS cho chúng ta.
Nếu chúng ta lưu trữ một trang web trên Heroku thì việc bật TLS chỉ cần nhấp vào một nút. Lưu trữ trên AWS (Amazon Web Services – là nền tảng web service cung cấp giải pháp cho tính toán, lưu trữ và mạng) thì trình quản lý chứng chỉ AWS kết hợp với AWS Cloudfront (dịch vụ phân phối nội dung toàn cầu) sẽ phụ trách. Nếu có thể thì hãy để máy chủ quản lý chứng chỉ, điều này giúp mọi thứ đều đơn giản và mọi lệnh gọi REST API sẽ được bảo mật tự động.
Nếu bạn đang chạy máy chủ web của riêng mình mà không có bất kỳ dịch vụ bên thứ ba nào thì bạn sẽ phải quản lý chứng chỉ của riêng mình. Và cách dễ nhất là với Let’s Encrypt – một tổ chức phát hành chứng chỉ tự động.
Sử dụng OAuth2 để đăng nhập một lần (SSO) với OpenID Connect
OAuth2 – viết tắt của Open with Authentication or Authorization – là một phương thức chứng thực, được ra đời để giúp các ứng dụng có thể chia sẻ tài nguyên với nhau mà không cần chia sẻ tên người dùng và mật khẩu.
SSO – Single Sign-On – là cơ chế để cho phép người dùng có thể truy cập nhiều trang web, ứng dụng mà chỉ cần đăng nhập một lần.
OpenID Connect là một framework được sử dụng cho công việc xác thực, đây là một lớp xác thực trên nền tảng OAuth2.
Gần như mọi ứng dụng sẽ cần liên kết một số dữ liệu riêng tư của một người, được gọi là tài khoản người dùng và sẽ có đăng nhập, đăng xuất. Trước đây chúng ta có thể đã tự viết mã đăng nhập, nhưng có một cách đơn giản hơn đó là sử dụng OAuth2 để tích hợp với các nhà cung cấp dịch vụ đăng nhập một lần – được gọi là “SSO”.
SSO cho phép người dùng tự xác minh với bên thứ ba đáng tin cậy (như Google, Microsoft Azure hoặc AWS) bằng cách trao đổi mã thông báo để có quyền truy cập vào resource. Chẳng hạn, họ sẽ đăng nhập vào tài khoản Google của họ và được cấp quyền truy cập vào REST API.
Sử dụng SSO có nghĩa là:
- Ứng dụng không cần phải tự quản lý mật khẩu. Nên dữ liệu cần lưu trữ sẽ giảm xuống và khi có trường hợp vi phạm dữ liệu thì sẽ có ít dữ liệu của người dùng bị lộ.
- Vừa tránh thực hiện đăng nhập, đăng xuất, còn tránh được việc thực hiện xác thực đa yếu tố.
- Người dùng không cần tạo tài khoản và mật khẩu mới vì họ đã có tài khoản với nhà cung cấp SSO như Google. Giảm xung đột khi đăng ký nghĩa là sẽ có nhiều người dùng hơn.
OAuth2 là một tiêu chuẩn mô tả cách một ứng dụng của bên thứ ba có thể truy cập dữ liệu từ ứng dụng thay mặt cho người dùng. OAuth2 không trực tiếp xử lý xác thực mà là một framework chung được xây dựng chủ yếu với mục đích ủy quyền.
Ví dụ: một người dùng có thể cấp cho một ứng dụng quyền truy cập để xem lịch của họ nhằm lên kế hoạch cho một cuộc họp. Điều này sẽ liên quan đến tương tác OAuth2 giữa người dùng, nhà cung cấp lịch và ứng dụng lập kế hoạch.
Trong ví dụ trên, OAuth2 đang cung cấp cơ chế phối hợp giữa ba bên. Ứng dụng lập kế hoạch muốn lấy mã thông báo truy cập để có thể tìm nạp dữ liệu lịch từ nhà cung cấp, thì sẽ thực hiện bằng cách gửi người dùng đến nhà cung cấp lịch tại một URL cụ thể với các tham số yêu cầu đã được mã hóa. Nhà cung cấp lịch sẽ yêu cầu người dùng đồng ý với quyền truy cập này, sau đó chuyển hướng người dùng quay lại ứng dụng lập kế hoạch bằng mã ủy quyền. Mã này có thể được đổi lấy mã thông báo truy cập.
Chúng ta có thể triển khai xác thực trên OAuth2 bằng cách tìm nạp thông tin nhận dạng người dùng duy nhất như địa chỉ email. Tuy nhiên nên sử dụng OpenID Connect, được xây dựng trên OAuth2 và cung cấp một giao thức để xác thực người dùng.
Dù vậy không phải nhà cung cấp nào cũng hỗ trợ OpenID Connect. Ví dụ: GitHub không cho phép sử dụng OpenID Connect. Trong trường hợp này chúng ta sẽ phải tự xử lý OAuth2. Nhưng may mắn là có một thư viện OAuth2 cho ngôn ngữ lập trình và có nhiều tài liệu hay để lựa chọn.
Sử dụng các API key để cấp quyền truy cập cho người dùng
API Key là các khoá để cấp quyền cho các phần mềm/ứng dụng nhận diện và làm việc với nhau.
Mặc dù các điểm cuối REST API có thể phục vụ trang web riêng của bạn, nhưng một lợi thế lớn là REST cung cấp một cách tiêu chuẩn để các chương trình khác tương tác với dịch vụ của bạn. Đừng bắt người dùng thực hiện OAuth2 cục bộ hoặc bắt họ cung cấp một tổ hợp tên người dùng / mật khẩu, mà thay vào đó, hãy đơn giản hóa mọi thứ bằng việc phát hành các API key. Đây là cách thực hiện:
- Khi một người dùng đăng ký quyền truy cập vào API, hãy tạo API key:
var token = crypto.randomBytes(32).toString(‘hex’); - Lưu trữ khóa này trong cơ sở dữ liệu được liên kết với người dùng.
- Cẩn thận chia sẻ API key với người dùng, đảm bảo rằng nó ẩn càng nhiều càng tốt. Ví dụ: bạn có thể muốn hiển thị nó một lần trước khi tạo lại nó.
- Yêu cầu người dùng cung cấp API key của họ dưới dạng tiêu đề, như:
curl -H “Authorization: apikey MY_APP_API_KEY” https://myapp.example.com - Tra cứu API key của người dùng trong cơ sở dữ liệu để xác thực yêu cầu của họ.
Khi người dùng tạo một API key, hãy để họ đặt nhãn hoặc tên cho khóa đó trong bản ghi, điều này giúp chúng ta có thể xóa hoặc tạo lại các khóa, từ đó khôi phục tài khoản người dùng từ thông tin đăng nhập bị xâm phạm.
Sử dụng phương pháp quản lý bí mật tốt nhất cho các API key
Người dùng được khuyến khích nên làm theo các phương pháp quản lý bí mật hay nhất bằng cách viết mã mẫu tốt. Hãy hiển thị các ví dụ REST API sử dụng các biến môi trường, chẳng hạn như ENV[“MY_APP_API_KEY”].
from requests.auth import HTTPBasicAuth
import requests
import os
api_key = os.environ.get(“MY_APP_API_KEY”)
auth = HTTPBasicAuth(‘apikey’, api_key)
req = requests.get(“<https://myapp.example.com>,
headers={‘Accept’: ‘application/json’},
auth=auth)
Chọn thời điểm thực thi ủy quyền với cấp độ yêu cầu ủy quyền
Việc ủy quyền REST API được nói đến như thể nó sẽ áp dụng cho mọi yêu cầu, nhưng không nhất thiết phải như vậy. Chúng ta có thể muốn thêm cấp độ yêu cầu ủy quyền: xem xét một yêu cầu để quyết định xem người dùng có quyền truy cập vào resource hay không.
Cách này cho phép mọi người xem resources trong /public/ hoặc chọn một số loại chứa những yêu cầu nhất định mà người dùng cần được xác thực để thực hiện.
Cách tốt nhất để làm điều này là dùng phần mềm trung gian yêu cầu.
API key khác nhau được định cấu hình các quyền khác nhau
Người dùng được cấp quyền truy cập API có lập trình vì nhiều lý do khác nhau. Một số điểm cuối REST API có thể dành cho quyền truy cập tập lệnh, một số khác dành cho trang tổng quan,… và không phải mọi điểm cuối đều cần quyền truy cập tài khoản đầy đủ của người dùng. Một số API key khác nhau sẽ được quy định các cấp độ quyền khác nhau.
Để thực hiện việc này cần lưu trữ các quyền trong cơ sở dữ liệu cùng với các API key dưới dạng danh sách các chuỗi. Đơn giản hóa ngay từ đầu bằng “read” và “write”. Sau đó, thêm một phần mềm trung gian để yêu cầu tìm nạp người dùng, và đối với REST API, hãy tìm các quyền cho API key và kiểm tra quyền của mã thông báo.
Phần còn lại của ủy quyền trong các ứng dụng/logic kinh doanh
Khi đã bắt đầu thêm ủy quyền vào REST API, có thể thêm ngày càng nhiều logic hơn để xử lý nhiều lần kiểm tra hơn. Chúng ta có thể kết thúc với các câu lệnh If lồng nhau cho từng resource và cấp độ quyền. Vấn đề là việc này có thể kết thúc trùng lặp logic ứng dụng. Và chúng ta phải tìm nạp các bản ghi cơ sở dữ liệu trong phần mềm trung gian, và đây không phải là một ý hay.
Thay vào đó, hãy để mức logic ủy quyền đó cho mã ứng dụng. Mọi kiểm tra ủy quyền trên resource sẽ thực hiện trong ứng dụng, không phải trong phần mềm trung gian. Nếu cần xử lý logic ủy quyền phức tạp trong ứng dụng thì hãy sử dụng Oso, một công cụ cho phép giảm chính sách ủy quyền thành một vài quy tắc đơn giản.
Luôn có nhiều điều để thảo luận xung quanh việc xác thực và ủy quyền. FUNiX hy vọng những mẹo này sẽ giúp bạn thiết kế các điểm cuối REST API hữu ích và an toàn nhất.
Hiện nay, FUNiX đang có chương trình tài trợ học phí trị giá 30 triệu đồng của 44 Doanh nghiệp cam kết việc làm sau khóa học.
Xem thêm các chủ đề hữu ích:
- 5 Điểm đáng chú ý tại khóa học lập trình trực tuyến FPT – FUNiX
- Từ A-Z chương trình học FUNiX – Mô hình đào tạo lập trình trực tuyến số 1 Việt Nam
- Lý do phổ biến khiến học viên nước ngoài chọn FUNiX
- Lưu ý để học blockchain trực tuyến hiệu quả cao tại FUNiX
- Lý do nữ giới nên chọn FUNiX để học chuyển nghề IT
- FUNiX trở thành đối tác của Liên minh Blockchain Việt Nam
- 3 lý do bạn trẻ nên học blockchain trực tuyến ở FUNiX
Phạm Thị Thanh Ngọc (theo Stack Overflow)
Bình luận (0
)