Tìm hiểu đôi chút về OAuth2: Khái niệm, Vai trò và Ứng dụng bảo mật ứng dụng hiện đại

Trong thế giới số hiện nay, bảo mật ứng dụng không còn là một lựa chọn mà đã trở thành yêu cầu bắt buộc. Mỗi ngày, chúng ta sử dụng hàng loạt ứng dụng yêu cầu truy cập vào dữ liệu cá nhân trên các nền tảng lớn như Google, Facebook hay GitHub. Vấn đề đặt ra là làm thế nào để cấp quyền cho ứng dụng một cách an toàn mà không phải chia sẻ mật khẩu của mình? Đây chính là lúc OAuth2, một giao thức ủy quyền mạnh mẽ, phát huy vai trò. OAuth2 được sinh ra để giải quyết bài toán kiểm soát truy cập và bảo vệ dữ liệu người dùng một cách hiệu quả và tiện lợi. Bài viết này sẽ cùng bạn tìm hiểu chi tiết về OAuth2, từ khái niệm cơ bản, cách hoạt động, lợi ích cho đến những ứng dụng thực tiễn.

Khái niệm cơ bản về OAuth2 và vai trò của nó trong bảo mật ứng dụng

Để hiểu rõ sức mạnh của OAuth2, trước tiên chúng ta cần làm quen với những khái niệm nền tảng và vai trò cốt lõi của nó trong việc xây dựng một hệ sinh thái ứng dụng an toàn.

OAuth2 là gì?

OAuth2, viết tắt của “Open Authorization 2.0”, là một giao thức ủy quyền tiêu chuẩn mở. Nó cho phép các ứng dụng có được quyền truy cập hạn chế vào tài khoản người dùng trên một dịch vụ HTTP. Hãy tưởng tượng bạn muốn dùng một ứng dụng chỉnh sửa ảnh trực tuyến để lấy ảnh từ Google Photos của bạn. Thay vì cung cấp tên đăng nhập và mật khẩu Google cho ứng dụng đó, OAuth2 sẽ đứng ra làm trung gian, giúp bạn cấp quyền cho ứng dụng chỉ đọc ảnh mà không lộ thông tin đăng nhập.

Giao thức này ra đời để thay thế cho OAuth 1.0, với mục tiêu đơn giản hóa quy trình cho các nhà phát triển và cung cấp các luồng ủy quyền đa dạng hơn, phù hợp với nhiều loại ứng dụng khác nhau như ứng dụng web, ứng dụng di động hay các ứng dụng chạy trên máy chủ. Mục tiêu chính của OAuth2 là tạo ra một cơ chế ủy quyền an toàn, linh hoạt và được chuẩn hóa trên toàn cầu, giúp các dịch vụ có thể tương tác với nhau một cách tin cậy.

Hình minh họa

Vai trò của OAuth2 trong bảo mật ứng dụng

Vai trò quan trọng nhất của OAuth2 là thay đổi hoàn toàn cách chúng ta chia sẻ dữ liệu giữa các ứng dụng. Trước đây, một phương pháp phổ biến nhưng cực kỳ nguy hiểm là yêu cầu người dùng nhập trực tiếp mật khẩu của họ. Cách làm này tiềm ẩn rủi ro rất lớn: nếu ứng dụng bên thứ ba bị tấn công, toàn bộ tài khoản của người dùng sẽ bị xâm phạm.

OAuth2 giải quyết triệt để vấn đề này bằng cách giới thiệu một lớp trung gian ủy quyền. Thay vì mật khẩu, ứng dụng sẽ nhận được một “Access Token” – một chuỗi ký tự đại diện cho quyền truy cập cụ thể trong một khoảng thời gian nhất định. Ví dụ, bạn chỉ cấp quyền cho ứng dụng đọc danh sách bạn bè, thì token đó chỉ có thể dùng để đọc danh sách bạn bè, không thể dùng để đăng bài hay thay đổi thông tin cá nhân. Điều này giúp hạn chế tối đa rủi ro, bảo vệ thông tin cá nhân và mang lại cho người dùng toàn quyền kiểm soát dữ liệu của mình.

Cách thức hoạt động của giao thức OAuth2

Để hiểu tại sao OAuth2 lại an toàn và hiệu quả, chúng ta cần tìm hiểu về các bên liên quan và quy trình hoạt động của nó. Thoạt nghe có vẻ phức tạp, nhưng về cơ bản, luồng hoạt động của OAuth2 khá logic và có thể được chia thành các bước rõ ràng.

Các thành phần chính trong OAuth2

Một quy trình OAuth2 điển hình bao gồm bốn vai trò chính. Việc hiểu rõ từng vai trò sẽ giúp bạn hình dung được toàn bộ quá trình:

  • Resource Owner (Chủ sở hữu tài nguyên): Đây chính là bạn, người dùng cuối. Bạn là người sở hữu dữ liệu (ví dụ: album ảnh, danh bạ, email) và có toàn quyền quyết định ai được phép truy cập vào chúng.
  • Client (Ứng dụng yêu cầu quyền): Đây là ứng dụng của bên thứ ba muốn truy cập vào dữ liệu của bạn. Ví dụ: một ứng dụng Lịch muốn xem các sự kiện trong Google Calendar của bạn.
  • Authorization Server (Máy chủ ủy quyền): Đây là máy chủ chịu trách nhiệm xác thực danh tính của bạn và lấy sự cho phép từ bạn. Sau khi bạn đồng ý, máy chủ này sẽ cấp Access Token cho Client. Đây thường là dịch vụ mà bạn đã có tài khoản, như Google, Facebook, hoặc GitHub.
  • Resource Server (Máy chủ chứa tài nguyên): Đây là nơi lưu trữ dữ liệu của bạn. Khi Client có được Access Token, nó sẽ gửi token này đến Resource Server để yêu cầu quyền truy cập vào dữ liệu được bảo vệ. Resource Server sẽ xác thực token và trả về dữ liệu tương ứng.

Trong nhiều trường hợp, Authorization Server và Resource Server có thể là cùng một máy chủ, nhưng việc tách biệt chúng giúp mô hình trở nên linh hoạt hơn.

Hình minh họa

Quy trình ủy quyền OAuth2 cơ bản

Luồng hoạt động phổ biến nhất của OAuth2 (được gọi là “Authorization Code Grant”) diễn ra theo các bước sau. Hãy cùng xem qua ví dụ một ứng dụng tên “ABC” muốn truy cập ảnh của bạn trên “XYZ Photos”:

  1. Yêu cầu ủy quyền: Ứng dụng ABC chuyển hướng bạn đến trang đăng nhập của XYZ Photos và yêu cầu quyền truy cập vào album ảnh của bạn. Yêu cầu này chứa thông tin về các quyền cụ thể mà ứng dụng cần (ví dụ: chỉ đọc ảnh).
  2. Cấp mã ủy quyền (Authorization Grant): Tại trang của XYZ Photos, bạn sẽ đăng nhập và thấy một màn hình hỏi “Ứng dụng ABC muốn truy cập ảnh của bạn. Bạn có đồng ý không?”. Nếu bạn nhấn “Đồng ý”, Authorization Server (của XYZ Photos) sẽ tạo ra một mã ủy quyền tạm thời (Authorization Code) và gửi lại cho ứng dụng ABC thông qua trình duyệt.
  3. Trao đổi mã lấy Access Token: Ứng dụng ABC nhận được mã ủy quyền này. Nó sẽ gửi mã này cùng với thông tin xác thực của chính nó (Client ID và Client Secret) đến Authorization Server một cách bí mật. Authorization Server xác thực mã và thông tin của ứng dụng, sau đó cấp một Access Token và (tùy chọn) một Refresh Token.
  4. Sử dụng Access Token truy cập tài nguyên: Giờ đây, ứng dụng ABC đã có trong tay “chìa khóa” là Access Token. Mỗi khi cần lấy ảnh của bạn, nó sẽ gửi một yêu cầu đến Resource Server (máy chủ lưu trữ ảnh của XYZ Photos) và đính kèm Access Token này. Resource Server sẽ kiểm tra tính hợp lệ của token và phạm vi quyền, sau đó trả về dữ liệu ảnh mà ứng dụng yêu cầu.

Access Token thường có thời gian hết hạn ngắn để tăng cường bảo mật. Khi hết hạn, ứng dụng có thể sử dụng Refresh Token để lấy một Access Token mới mà không cần bạn phải đăng nhập lại.

Hình minh họa

Lợi ích và ứng dụng thực tiễn của OAuth2

OAuth2 không chỉ là một khái niệm lý thuyết. Nó đã trở thành xương sống cho việc ủy quyền trên khắp internet, mang lại nhiều lợi ích thiết thực và được ứng dụng rộng rãi bởi các ông lớn công nghệ.

Lợi ích nổi bật của OAuth2 trong kiểm soát truy cập và bảo vệ dữ liệu

Việc áp dụng OAuth2 mang lại nhiều ưu điểm vượt trội so với các phương pháp xác thực truyền thống:

  • Tăng cường bảo mật mà không cần chia sẻ mật khẩu: Đây là lợi ích lớn nhất. Người dùng không bao giờ phải cung cấp thông tin đăng nhập nhạy cảm của mình cho các ứng dụng bên thứ ba. Điều này loại bỏ hoàn toàn nguy cơ mật khẩu bị đánh cắp hoặc lạm dụng bởi các ứng dụng không đáng tin cậy.
  • Hạn chế quyền truy cập tối thiểu (Principle of Least Privilege): OAuth2 cho phép ứng dụng chỉ yêu cầu những quyền hạn thực sự cần thiết cho hoạt động của nó. Ví dụ, một ứng dụng phân tích trang cá nhân chỉ cần quyền đọc bài đăng công khai, không cần quyền đăng bài hay nhắn tin. Người dùng có thể xem và quyết định chính xác những gì họ cho phép, giúp kiểm soát dữ liệu tốt hơn.
  • Khả năng thu hồi quyền dễ dàng: Người dùng có toàn quyền kiểm soát. Bất cứ lúc nào, bạn cũng có thể truy cập vào trang quản lý tài khoản của mình (ví dụ: Google Account) và xem danh sách các ứng dụng đã được cấp quyền. Nếu không còn sử dụng một ứng dụng nào đó, bạn có thể dễ dàng thu hồi quyền truy cập của nó chỉ bằng một cú nhấp chuột.
  • Cải thiện trải nghiệm người dùng: Các tính năng như “Đăng nhập bằng Google” hay “Đăng nhập bằng Facebook” giúp người dùng không cần phải tạo và ghi nhớ hàng tá mật khẩu khác nhau. Quá trình đăng ký và đăng nhập trở nên nhanh chóng, liền mạch và an toàn hơn.

Hình minh họa

Ứng dụng OAuth2 trên các nền tảng phổ biến

Bạn có thể thấy OAuth2 hoạt động ở khắp mọi nơi mỗi ngày. Dưới đây là một vài ví dụ điển hình:

  • Google: Khi bạn sử dụng một ứng dụng bên thứ ba và nó yêu cầu quyền truy cập vào Google Drive, Google Calendar hay Gmail của bạn, đó chính là OAuth2. Màn hình yêu cầu sự đồng ý quen thuộc chính là bước cấp quyền trong quy trình OAuth2, đảm bảo ứng dụng chỉ có thể làm những gì bạn cho phép.
  • Facebook: Tính năng “Log in with Facebook” là một ví dụ kinh điển. Nó cho phép các trang web và ứng dụng sử dụng danh tính Facebook của bạn để xác thực mà không cần bạn tạo tài khoản mới. Các ứng dụng game cũng thường dùng OAuth2 để yêu cầu quyền đăng điểm số lên tường nhà bạn.
  • Twitter (nay là X): Khi bạn cho phép một công cụ quản lý mạng xã hội tự động đăng bài lên tài khoản Twitter của mình, bạn đang sử dụng OAuth2. Công cụ đó nhận được một token cho phép nó thực hiện hành động đăng bài thay mặt bạn.
  • GitHub: Các nhà phát triển thường sử dụng tính năng “Sign in with GitHub” để truy cập vào các dịch vụ CI/CD (Tích hợp và Triển khai liên tục) hoặc các công cụ phân tích mã nguồn. OAuth2 giúp các dịch vụ này truy cập vào kho mã nguồn một cách an toàn để thực hiện các tác vụ tự động.

Hình minh họa

So sánh OAuth2 với các giao thức ủy quyền khác

Trong lĩnh vực xác thực và ủy quyền, OAuth2 không phải là giao thức duy nhất. Để hiểu rõ hơn vị trí và ưu điểm của nó, việc so sánh với các tiêu chuẩn khác như OAuth 1.0, SAML hay OpenID Connect là rất cần thiết.

OAuth2 vs OAuth1

OAuth 2.0 ra đời như một sự kế thừa, khắc phục những nhược điểm và sự phức tạp của phiên bản tiền nhiệm, OAuth 1.0 (chính xác hơn là 1.0a). Sự khác biệt chính nằm ở cơ chế bảo mật và tính đơn giản hóa:

  • Cơ chế ký yêu cầu (Request Signing): OAuth 1.0 yêu cầu mọi yêu cầu API từ Client đến Server đều phải được ký bằng các thuật toán mã hóa phức tạp (thường là HMAC-SHA1). Việc này khá nặng nề và khó triển khai, đặc biệt là trên các ứng dụng di động hoặc ứng dụng JavaScript phía client.
  • Sự đơn giản hóa của OAuth2: OAuth2 loại bỏ yêu cầu ký phức tạp này. Thay vào đó, nó dựa hoàn toàn vào giao thức HTTPS (TLS/SSL) để đảm bảo tính toàn vẹn và bảo mật cho dữ liệu truyền đi. Điều này làm cho việc triển khai OAuth2 trở nên đơn giản và nhanh chóng hơn rất nhiều. OAuth2 cũng tách biệt vai trò của Authorization Server và Resource Server, mang lại sự linh hoạt cao hơn.
  • Access Token: Trong OAuth2, Access Token được gọi là “Bearer Token”, nghĩa là bất kỳ ai nắm giữ token này đều có quyền truy cập. Đây là lý do tại sao việc truyền token qua HTTPS là cực kỳ quan trọng. OAuth 1.0 thì phức tạp hơn, token phải được sử dụng cùng với một quy trình ký.

Nhìn chung, OAuth2 thân thiện hơn với nhà phát triển, linh hoạt hơn và phù hợp hơn với kiến trúc ứng dụng hiện đại.

Hình minh họa

OAuth2 so với các phương thức khác (SAML, OpenID Connect)

Mặc dù đôi khi được sử dụng trong cùng một bối cảnh, các giao thức này phục vụ những mục đích khác nhau:

  • OAuth2 vs SAML (Security Assertion Markup Language):
    • Mục đích: OAuth2 tập trung vào ủy quyền (Authorization) – tức là cho phép ứng dụng A thực hiện hành động thay mặt người dùng trên ứng dụng B. SAML chủ yếu dùng cho xác thực (Authentication) và thường được triển khai trong môi trường doanh nghiệp cho các giải pháp Single Sign-On (SSO). Với SAML, bạn đăng nhập một lần vào hệ thống trung tâm (Identity Provider) và có thể truy cập nhiều ứng dụng khác nhau mà không cần đăng nhập lại.
    • Định dạng: OAuth2 thường sử dụng định dạng JSON, nhẹ và dễ xử lý bởi các ứng dụng web hiện đại. SAML sử dụng định dạng XML, cồng kềnh hơn.
    • Trường hợp sử dụng: OAuth2 lý tưởng cho các API công khai, ứng dụng di động và web. SAML vẫn là lựa chọn hàng đầu cho các giải pháp SSO trong nội bộ doanh nghiệp.
  • OAuth2 vs OpenID Connect (OIDC):
    • Mối quan hệ: Đây không hẳn là một sự so sánh “đối đầu”. OpenID Connect thực chất là một lớp (layer) được xây dựng trên nền tảng của OAuth2.
    • Mục đích: OAuth2 chỉ giải quyết bài toán ủy quyền. Nó cho ứng dụng biết ứng dụng có thể làm gì nhưng không cho biết người dùng là ai. OIDC bổ sung thêm phần xác thực vào quy trình OAuth2. Nó cung cấp một cách chuẩn hóa để Client có thể xác minh danh tính của người dùng dựa trên quá trình xác thực được thực hiện bởi Authorization Server.
    • Cách hoạt động: Khi sử dụng OIDC, ngoài Access Token, Authorization Server còn trả về một “ID Token”. ID Token này là một JWT (JSON Web Token) chứa các thông tin cơ bản về người dùng (như ID, tên, email) đã được ký điện tử, giúp Client xác thực người dùng một cách an toàn.
    • Kết luận: Nếu bạn chỉ cần cấp quyền truy cập API, hãy dùng OAuth2. Nếu bạn cần xây dựng tính năng “Đăng nhập bằng…”, bạn đang thực sự cần OpenID Connect.

Hình minh họa

Common Issues/Troubleshooting

Mặc dù OAuth2 rất mạnh mẽ, việc triển khai nó không phải lúc nào cũng suôn sẻ. Các nhà phát triển có thể gặp phải một số lỗi phổ biến nếu không cẩn thận, dẫn đến các lỗ hổng bảo mật không đáng có.

Lỗi phổ biến khi triển khai OAuth2

Một trong những sai lầm nghiêm trọng và phổ biến nhất là việc quản lý Access Token không đúng cách. Access Token giống như một chiếc chìa khóa tạm thời có quyền lực lớn. Nếu bị rò rỉ, kẻ tấn công có thể mạo danh ứng dụng của bạn để truy cập tài nguyên của người dùng.

  • Lưu trữ Access Token không an toàn: Một số nhà phát triển lưu Access Token trong localStorage hoặc sessionStorage của trình duyệt. Đây là một thực hành nguy hiểm vì chúng có thể bị đánh cắp thông qua các cuộc tấn công kịch bản chéo trang (Social engineering). Kẻ tấn công có thể chèn một đoạn mã độc vào trang web của bạn để đọc và gửi token về máy chủ của chúng.
  • Truyền token qua các kênh không mã hóa: Mọi giao tiếp liên quan đến OAuth2 (bao gồm cả việc gửi token) phải được thực hiện qua HTTPS. Nếu bạn gửi token qua HTTP, nó có thể bị nghe lén và chiếm đoạt một cách dễ dàng.
  • Không xử lý Refresh Token đúng cách: Refresh Token thậm chí còn nhạy cảm hơn Access Token vì chúng có thể được dùng để tạo ra nhiều Access Token mới. Chúng phải được lưu trữ ở một nơi cực kỳ an toàn phía máy chủ, không bao giờ được để lộ ra phía client.

Hình minh họa

Vấn đề liên quan đến quyền hạn không phù hợp

Một sai lầm khác đến từ việc yêu cầu quyền hạn quá rộng, đi ngược lại nguyên tắc “đặc quyền tối thiểu”.

  • Cấp quyền quá rộng làm tăng nguy cơ rò rỉ dữ liệu: Nhiều ứng dụng, vì muốn đơn giản hóa, đã yêu cầu quyền truy cập đầy đủ vào tài khoản của người dùng (ví dụ: full_access vào Google Drive) trong khi chỉ cần đọc một loại tệp cụ thể. Điều này rất nguy hiểm. Nếu ứng dụng hoặc token bị xâm phạm, kẻ tấn công sẽ có toàn quyền truy cập vào dữ liệu của người dùng, gây ra hậu quả nghiêm trọng.
  • Làm người dùng mất lòng tin: Khi người dùng thấy một ứng dụng yêu cầu quá nhiều quyền hạn không liên quan đến chức năng của nó, họ sẽ trở nên nghi ngờ và có thể từ chối cấp quyền. Ví dụ, một ứng dụng đèn pin không có lý do gì để yêu cầu truy cập vào danh bạ của bạn. Việc yêu cầu quyền một cách minh bạch và hợp lý sẽ giúp xây dựng lòng tin với người dùng. Luôn yêu cầu phạm vi (scope) hẹp nhất có thể để ứng dụng hoạt động.

Để khắc phục, hãy luôn kiểm tra kỹ lưỡng các phạm vi quyền mà bạn yêu cầu và đảm bảo chúng thực sự cần thiết cho từng tính năng của ứng dụng.

Best Practices

Để triển khai OAuth2 một cách an toàn và hiệu quả, việc tuân thủ các thực hành tốt nhất là vô cùng quan trọng. Những nguyên tắc này không chỉ giúp bảo vệ dữ liệu người dùng mà còn xây dựng nên một ứng dụng đáng tin cậy.

  • Luôn xác thực HTTPS khi xử lý OAuth2: Đây là quy tắc vàng không thể bỏ qua. Toàn bộ chu trình OAuth2, từ việc chuyển hướng người dùng đến trao đổi mã ủy quyền và gửi Access Token, phải được thực hiện trên một kết nối được mã hóa bằng TLS/SSL (TLS/SSL). Điều này ngăn chặn các cuộc tấn công xen giữa (Man-in-the-Middle), đảm bảo rằng mã ủy quyền và token không bị nghe lén trên đường truyền.
  • Chỉ cấp quyền tối thiểu cần thiết cho ứng dụng (Principle of Least Privilege): Trước khi yêu cầu quyền, hãy tự hỏi: “Ứng dụng của tôi thực sự cần quyền gì để hoạt động?”. Đừng yêu cầu quyền truy cập toàn bộ tài khoản nếu bạn chỉ cần đọc thông tin hồ sơ cơ bản. Hãy xác định các phạm vi (scopes) hẹp nhất có thể. Điều này không chỉ giảm thiểu rủi ro bảo mật mà còn tăng tỷ lệ người dùng đồng ý cấp quyền.
  • Lưu trữ Access Token an toàn và thiết lập thời gian hết hạn:
    • Lưu trữ: Đối với các ứng dụng web (Single Page Applications), nên lưu trữ token trong bộ nhớ (in-memory) thay vì localStorage. Đối với các ứng dụng phía máy chủ, hãy lưu chúng trong một cơ sở dữ liệu an toàn. Refresh Token phải được bảo vệ cẩn mật hơn nữa, ví dụ như mã hóa chúng trước khi lưu.
    • Thời gian hết hạn: Access Token nên có vòng đời ngắn (vài phút đến vài giờ). Điều này giới hạn khoảng thời gian mà một token bị đánh cắp có thể bị lạm dụng. Sử dụng Refresh Token để lấy Access Token mới khi cần thiết, giúp duy trì phiên đăng nhập mà không cần người dùng phải xác thực lại liên tục.
  • Thường xuyên rà soát và thu hồi quyền không cần thiết: Cung cấp cho người dùng một giao diện rõ ràng để họ có thể xem lại các ứng dụng đã được cấp quyền và dễ dàng thu hồi chúng. Về phía nhà phát triển, nếu một tính năng không còn được sử dụng, hãy cân nhắc việc loại bỏ các quyền liên quan đến nó trong các phiên bản cập nhật của ứng dụng.
  • Sử dụng tham số state để chống lại tấn công CSRF: Khi bắt đầu luồng OAuth2, ứng dụng Client nên tạo một chuỗi ngẫu nhiên, khó đoán (tham số state) và gửi nó cùng với yêu cầu ủy quyền. Khi Authorization Server gọi lại, nó sẽ trả về tham số state này. Client phải xác minh rằng tham số state trả về khớp với giá trị ban đầu để đảm bảo yêu cầu là hợp lệ và không bị giả mạo.

Hình minh họa

Conclusion

Qua những phân tích chi tiết, có thể thấy OAuth2 không chỉ là một giao thức kỹ thuật mà còn là một trụ cột thiết yếu trong kiến trúc bảo mật của thế giới internet hiện đại. Nó đã giải quyết thành công bài toán nan giải về việc ủy quyền truy cập giữa các ứng dụng một cách an toàn, linh hoạt mà không làm lộ thông tin nhạy cảm của người dùng. Bằng cách thay thế việc chia sẻ mật khẩu bằng cơ chế Access Token với phạm vi quyền hạn chế, OAuth2 đã tạo ra một môi trường tương tác đáng tin cậy, thúc đẩy sự phát triển của hệ sinh thái ứng dụng đa dạng như ngày nay.

Đối với các nhà phát triển, việc hiểu và áp dụng OAuth2 đúng cách là một kỹ năng quan trọng. Nó không chỉ giúp bảo vệ người dùng mà còn nâng cao uy tín và trải nghiệm cho sản phẩm của bạn. Với sự hỗ trợ từ các nền tảng lớn và cộng đồng, việc triển khai OAuth2 đã trở nên dễ dàng hơn bao giờ hết. Do đó, hãy bắt đầu tìm hiểu sâu hơn và tích hợp giao thức mạnh mẽ này vào các dự án của mình để xây dựng những ứng dụng an toàn và đáng tin cậy hơn.

Đánh giá
Tác giả

Mạnh Đức

Có cao nhân từng nói rằng: "Kiến thức trên thế giới này đầy rẫy trên internet. Tôi chỉ là người lao công cần mẫn đem nó tới cho người cần mà thôi !"

Chia sẻ
Bài viết liên quan