Giải ngố API – Phần 3: API Authentication và các thể loại API data formats

Tiếp theo nội Giải ngố API – Phần 2: Web APIs hoạt động ra sao?, kỳ này tôi sẽ chuyển sang một vấn đề quan trọng là API authentication. Ngoài ra, tôi cũng sẽ bàn tiếp về một vấn đề còn tồn đọng chưa đề cập trong kỳ trước là API data format.

#1. API Authentication

Như đã giới thiệu trong nội dung Penetration Testing Step 3 – Tấn công vào Authentication mechanisms liệu có khả thi?, quá trình xác thực thông thường sẽ bao gồm các bước:

  • Client gửi credentials đến web server;
  • Web server kiểm tra và so sánh credentials client gửi đến với thông tin được lưu trữ;
  • Nếu credentials và thông tin được lưu trữ khớp thì web server sẽ tạo user sesion và cookie gửi cho client;
  • Khi kết thúc phiên làm việc, web server sẽ hủy user session và loại bỏ đám cookie liên quan đến client;
Session Management
Session Management

Nguồn: owasp.org

Lưu ý: Authentication liên quan đến việc xác nhận tuyên bố danh tính của user trong khi Authorization (tạm dịch là phân quyền) hay Access Control liên quan đến việc xác nhận và cấp quyền truy cập cho user.  

Với các đối tượng không phải “thông thường” như RESTGraphQL API, vì là dạng stateless nên mỗi khi API consumer tương tác để xác thực, server sẽ không khởi tạo session giống như quá trình nói trên. Thay vào đó, API consumer sẽ phải chứng minh “nhân thân” trong từng request gửi đến API provider.

Bàn thêm về GraphQL API, do đối tượng này không có ràng buộc cụ thể về phương án kiểm soát authenticaion/authorization nên các ông phụ trách thực thi sẽ tự do triển khai phần này luôn (tất nhiên là sẽ tự chịu trách nhiệm về phương án triển khai của mình). Về cơ bản, có 2 dạng phổ biến là In-bandOut-of-band:

Phương án In-band:

  • Việc thực thi client login, signup, role-based access controls và các kiểm soát phân quyền khác được triển khai trực tiếp trong GraphQL API. Tức là GraphQL instance sẽ vừa cung cấp application data cho client và vừa kiểm soát phần login để xác thực và phân quyền tương ứng;
  • Thường dùng query hoặc mutation operations để cho phép client gửi credentials đến API;
  • GraphQL API phụ trách xác nhận credentials và tạo token cho clients.

Phương án Out-of-band:

  • Phần logic cho phần kiểm soát truy cập và phân quyền sẽ được triển trên một hệ thống tác biệt (có thể là nội bộ hoặc bên ngoài). Khi đó, GraphQL API sẽ không chịu trách nhiệm quản lý client login, signup hay kiểm soát truy cập gì sất;
  • Lúc này GraphQL API sẽ đá trách nhiệm liên quan sang thằng khác, ví dụ như API gateway hoặc 1 ông server nào đó trong hệ thống.

Phương án In-band tiềm ẩn nhiều vấn đề (vì ôm đồm xử lý quá nhiều thứ) nên phương án chuẩn được các bậc thầy đề xuất đẩy công tác authentication qua external/third party gateway layer. Đồng thời, phần authorization logic sẽ được đá sang sang business logic layer của ứng dụng để áp dụng đồng bộ tất cả các nguyên tắc xử lý.

Nguồn: Thinking in Graphs | GraphQL

Lưu ý: Persistence layer còn được gọi là database/datastore layer.

Rồi, bây giờ tôi sẽ quay lại vấn đề chính là tóm lược các thể loại API authentication phổ biến.

#1.1 No authentication – Khỏi xác thực gì cả

Phương án đầu tiên là No authentication – “khỏi xác thực”. Vụ này nghe hơi lầy nhưng thực ra vẫn hợp lý khi cần xử lý dữ liệu không nhạy cảm. Và với kịch bản này, bạn cứ có sao chơi vậy không cần bận tâm gì tới việc xác thực cho nhọc xác.

#1.2 HTTP Basic authentication

Ở phương án HTTP Basic authenticion, quy trình sẽ hơi phức tạp hơn một ít. Lúc này, API consumer sẽ gửi kèm username và password trong phần header hoặc body của request đi. Một khi nhận được, API sẽ chuyển username và password cho provider dạng plaintext hoặc encode credentials (ví dụ kiểu base64): Authorization: Basic <base64_encoded_credential> .

Thông thường HTTP Basic authentication sẽ chỉ yêu cầu API consumer cung cấp credential trong request đầu tiên, sau đó API provider sẽ tạo API key hoặc token để gửi kèm trong các request tiếp theo.

Nguồn: What Is API Authentication? Benefits, Methods & Best Practices | Postman

Lưu ý: Bạn có thể xem thêm thông tin ở trang Information on RFC 7617 » RFC Editor (rfc-editor.org), nếu cần.

Dạng Base64-encoded thường gặp trong môi trường testing hoặc staging (tức là chỗ môi trường để mấy ông developer tung tóe chứ không môi trường production cho người dùng sử dụng) với các điểm yếu:

  • Thiếu phương án bảo vệ khi truyền tải credentials đến server qua HTTP nên có thể chết với man-in-the-middle attack (có thể dùng phương án giảm thiểu ví dụ như sử dụng TLS);
  • Thiếu hỗ trợ tính năng logout nhằm vô hiệu hóa crenditals đã bị rò rỉ (lúc này ông admin sẽ phải thò tay vào thay đổi crenditals);

 

#1.3 API Keys

API key là chuỗi ký tự đặc biệt không trùng lặp mà API provider phọt ra để cung cấp cho API consumer (tất nhiên là với API consumer đã đăng ký xác nhận chính chủ) sử dụng cho quyền truy cập theo mức độ phân quyền tương ứng.

Một khi nhận được API key, API consumer sẽ đính kèm cái key này trong các request mỗi khi được API provider yêu cầu. Thông thường, hàng sẽ được gửi đi theo kiểu:

  • Nằm trong query string parameters: /api/users?apikey= kjfashf978khfask;
  • Nằm trong request headers: “API-Secret”:”fasfdsf-gaerg54-fsde”;
  • Nằm trong body data hoặc cookie: Cookie: API-Key=fsdf54f8aw.
API key authentication
API key authentication

Nguồn: What Is API Authentication? Benefits, Methods & Best Practices | Postman

Lưu ý: Bạn có thể xem thêm thông tin ở trang API Keys (swagger.io), nếu cần.

API key nhìn chung sẽ bảo mật hơn so với basic authentication vì:

  • Khó brute-force hơn;
  • Có thể thiết lập expiraton dates để cho nó tự hẹo sau một khoảng thời gian nhất định.

Tuy nhiên phương án này cũng có các vấn đề bao gồm:

  • Vẫn cần TLS để bảo vệ API key tương tự như phương án basic authentication;
  • API key khi được tạo dựa trên user data sẽ có thể bị đoán mò hoặc giả mạo dựa trên thông tin liên quan của API consumer;
  • Có thể bị vô tình rò rỉ trên không gian mạng khi vẫn còn hiệu lực sử dụng.

#1.4 HMAC

Hash-based message authentication code  – HMAC là phương thức xác thực API cơ bản của AWS. Quy trình cụ thể như sau:

  • API provider tạo secret key và gửi đến API consumer;
  • Mỗi khi cần tương tác với API, API consumer sẽ gọi HMAC hash function để xử lý đám API request datasecret key nói trên;
  • Hashed result (message digest) sẽ được bổ sung vào request và gửi đến API provider;
  • API provider tính toán HMAC tương tự như cách API consumer xử lý và so sánh kết quả với cái hashed result API consumer gửi đến.

Bạn có thể xem ví dụ minh họa sau cho dễ hình dung.

HMAC
HMAC

Nguồn: HMAC – Wikipedia

#1.5 JSON Web Tokens

JSON Web Tokens – JWTAPI token-based authentication.

Quy trình xử lý với JWT có thể tóm lược như sau:

  • API consumer sẽ bắt đầu quá trình xác thực với API provider bằng cách gửi username và password;
  • API provider tạo JWT và gửi về cho API consumer;
  • API consumer bổ sung JWT vào Authorization header trong các API request tiếp theo.
JSON Web Tokens authentication
JSON Web Tokens authentication

Nguồn: What Is API Authentication? Benefits, Methods & Best Practices | Postman

Lưu ý: Bạn có thể xem thêm thông tin ở trang API Keys (swagger.io), nếu cần.

Để dễ hình dung, bạn có thể xem hình dạng cụ thể của 1 cái JWT như sau:

JWT example
JWT example

Nguồn: JSON Web Tokens – jwt.io

Như trên, bạn có thể thấy cái JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c sẽ bao gồm 3 phần đã được chuyển đổi với base64-encoded và phân tách bằng dấu chấm “.“. 3 phần này tương ứng với:

  • Header: Thông tin thuật toán được dùng để ký payload tạo Signature;
  • Payload: Data ví dụ như username, timestampissuer;
  • Signature: Thông tin được chuyển đổi và mã hóa dùng để xác định token.

Phần Header sẽ bao gồm 2 yếu tố quan trọng là alg key và typ key. typ key sẽ cho biết thông tin về loại token (JWT trong trường hợp này) và alg key sẽ cho biết thông tin về thuật toán sử dụng (HS256 trong trường hợp này). alg key thường bao gồm các dạng:

  • none: Không sử dụng Signature;
  • HS256: HMAC với SHA-256;
  • HS384: HMAC với SHA-384;
  • RS256: RSA với SHA-256;
  • RS384: RSA với SHA-384.

Tiếp theo, phần PAYLOAD sẽ chứa claims – thường là các thông tin liên quan đến việc xác định user (và một số thứ râu ria khác), Ví dụ:

  • sub: tương ứng với subject, thường được dùng như unique identifier để nhận diện user;
  • name: tương ứng với tên của user;
  • iat: thời điểm khởi tạo token.

Cuối cùng, phần signature được tạo bằng cách:

  • Chạy encryption function (HMACSHA256() tương ứng “alg”: “HS256” trong ví dụ trên) để mã hóa cái base64-encoded headerpayload trước khi base64-encoded cái kết quả encryption ở trên.

Quá trình ký tá này sẽ yêu cầu một thông tin quan trọng là secret để bảo đảm có được cái signature chuẩn mực. Và nhờ vào nó, mưu đồ tự tạo JWT giả danh cán bộ (ví dụ đút vô payload cái claim “admin”: true) của các bựa nhân sẽ bị bóp chết từ trong trứng nước.

Đọc đến đây chắc bạn cũng sẽ phọt ra thắc mắc giống tôi kiểu như “Ủa vậy điên hay sao mà chơi alg key – none hả mấy ông?”. Ở đây tôi nghĩ có thể có một lý do hợp lí là sử dụng alg key – none phục vụ việc kiểm tra thử nghiệm token validation process của mấy ông developer.

Ghi chú: Thiết lập alg sang none là một dạng tấn công phổ biến vào ứng dụng sử dụng JWT. Tấn công ứng dụng sử dụng JWT là một chủ đề thú vị và phức tạp nên chắc tôi sẽ sắp xếp giới thiệu riêng.

#1.6 OAuth 2.0

Open AuthoizationOAuth nói chung (hay cụ thể là OAuth 2.0) là authorization framework cho phép bên thứ 3 có được quyền truy cập tạm thời HTTP service (ví dụ như GraphQL API) dưới danh nghĩa của người dùng. Các ứng dụng sử dụng OAuth 2.0 framework có thể dùng token theo định dạng của JSON Web Token – JWT.

Đây là dạng có độ tin cậy cao nhất của API authorization nhưng cũng sẽ có thể làm gia tăng attack surface tùy thuộc theo phương án thực thi OAuth của API provider.

OAuth authentication
OAuth authentication

Nguồn: What Is API Authentication? Benefits, Methods & Best Practices | Postman

Lưu ý: Bạn có thể xem thêm thông tin ở trang Web Authorization Protocol (oauth) (ietf.org), nếu cần.

OAuth 2.0 có nhiều dạng grant types (tạm hiểu là kiểu cấp quyền), trong đó 2 ông phổ biến nhất là Authorization CodeImplicit (hiện đã được thay thế bằng Proof Key for Code Exchange – PKCE).

Ví dụ với Authorization Code, quy trình xử lý sẽ có dạng như sau:

Authorization Code flow
Authorization Code flow

Cũng như phần JWT, nội dung chi tiết liên quan đến OAuth 2.0 khá hay ho và phức tạp. Do vậy, tôi xin phép tách nội dung này ra một chủ đề riêng và giới thiệu sau (nếu tôi lỡ quên vụ này thì bạn nhớ comment chửi bới để nhắc tôi!).

#2. Các thể loại API data formats

Trước khi kết thúc nội dung kỳ này tôi xin dành ít phút để giới thiệu nốt về một vấn đề cũng khá quan trọng là API data formats.

API data formats đại khái là các kiểu định dạng dữ liệu được API consumerAPI provider sử dụng để “nói chuyện” với nhau.Về cơ bản API data formats sẽ sử dụng các định dạng phổ biến sau.

#2.1 JSON

Đây là định dạng phổ biến nhất thể hiện các đối tượng ở dạng key/value pair nằm bên trong curly brackets “{}” và phân cách bằng dấu phẩy “,”.

Dạng này sẽ không cho phép bạn triển inline comment (tức là kiểu thích comment dòng nào thì quất vào dòng đó) mà sẽ sử dụng comment cũng theo kiểu key/value ví dụ như comment” : “this is a comment. Để dễ hình dung, bạn có thể xem ví dụng minh hoạ cái REST API POST sử dụng JSON format như bên dưới.

REST API POST with JSON
REST API POST with JSON

Nguồn: How do I post JSON to a REST API endpoint? (reqbin.com)

#2.2 XML

Dạng Extensible Markup Language – XML thường hay la liếm với ông SOAP API (tôi có đề cập trong các kỳ trước, nếu cần thì bạn de lại đấy xem). Dạng này sử dụng descriptive tags (ví dụ như <id>[data]</id>) tương ứng cho các dạng dữ liệu.

Extensible Markup Language - XML
Extensible Markup Language – XML

Nguồn: SOAP XML Request and Response Headers  |  Ad Manager API  |  Google for Developers 

#2.3 YAML

Dạng thứ 3 được đề cập là YAML Ain’t Markup Language – YAML (cái tên hơi dị???) cũng bao gồm key/value pair giống JSON. Tuy nhiên, YAML được cho là “thân thiện” với người dùng hơn với một số điểm khác biệt bao gồm:

  • Báo hiệu bắt đầu với “” và kết thúc với ““;
  • Không bắt buộc sử dụng quotes cho strings, thích cho đẹp thì dùng, không dùng cũng chả sao;
  • Sử dụng indentation (tức là kiểu thụt đầu dòng) thay vì curly brackets “{}” để thể hiện nesting (đại khái là các kiểu phân cấp dữ liệu) và cho phép comment với “#”.

Bạn có thể xem ví dụ minh họa sau đây để dễ hình dung.

YAML
YAML

Nguồn: YAML – Wikipedia

Nếu đặc biệt hứng thú với thằng này, bạn có thể bơi vào Web Site chính thức của nó để xem thêm: The Official YAML Web Site.

Rồi thôi, bài kỳ này chữ hơi nhiều rồi nên tôi xin tạm nghỉ ở đây. Hẹn gặp lại bạn trong các chủ đề tiếp theo của con hàng API.

Leave a Reply

Your email address will not be published. Required fields are marked *