OAuth 2.0: nó là gì và cách hoạt động của giao thức ủy quyền

Tác giả: IT Sectr Đã đăng: 2026-04-05 Thời gian đọc: 10 phút

OAuth 2.0 là một giao thức ủy quyền tiêu chuẩn công nghiệp cho phép các ứng dụng bên thứ ba truy cập hạn chế vào tài nguyên của người dùng mà không chia sẻ thông tin đăng nhập của họ. Giao thức này đã trở thành tiêu chuẩn thực tế cho ủy quyền được ủy thác trong các ứng dụng web và di động, được sử dụng bởi các nền tảng như Google, Facebook, Apple và GitHub. Theo IETF RFC 6749 (2025), OAuth 2.0 được sử dụng trong hơn 85% tất cả các tích hợp API yêu cầu truy cập dữ liệu được ủy thác.

Những điểm chính

  • OAuth 2.0 là giao thức ủy quyền được ủy thác cho phép ứng dụng truy cập tài nguyên người dùng mà không truyền mật khẩu (IETF RFC 6749)
  • Access Token là mã thông báo truy cập tạm thời do máy chủ ủy quyền cấp cho ứng dụng sau khi xác thực người dùng thành công
  • Authorization Code Flow là Grant Type an toàn nhất cho ứng dụng di động, sử dụng code challenge (PKCE) để bảo vệ khỏi bị chặn
  • Refresh Token là mã thông báo dài hạn để lấy Access Token mới mà không yêu cầu người dùng đăng nhập lại
  • AppAuth là thư viện được IETF khuyến nghị để triển khai OAuth 2.0 trong ứng dụng di động gốc trên Android và iOS

OAuth 2.0 là gì?

OAuth 2.0 là một giao thức ủy quyền được định nghĩa trong IETF RFC 6749, cho phép các ứng dụng bên thứ ba có quyền truy cập hạn chế vào tài nguyên của người dùng mà không tiết lộ tên người dùng và mật khẩu của họ. Giao thức giải quyết một vấn đề cơ bản của mô hình mật khẩu: một ứng dụng bạn tin tưởng giao mật khẩu sẽ có quyền truy cập không giới hạn vào tất cả dữ liệu tài khoản. OAuth 2.0 thay thế cách tiếp cận này bằng cách cấp một mã thông báo tạm thời với phạm vi truy cập bị giới hạn rõ ràng.

Kiến trúc của OAuth 2.0 là ủy quyền được ủy thác. Người dùng (Resource Owner) ủy quyền cho một ứng dụng (Client) truy cập dữ liệu của họ được lưu trữ trên máy chủ tài nguyên (Resource Server) thông qua một trung gian: máy chủ ủy quyền (Authorization Server). Máy chủ ủy quyền cấp Access Token: một chuỗi mật mã mà ứng dụng trình bày với máy chủ tài nguyên để truy cập dữ liệu. Một điểm khác biệt quan trọng giữa OAuth 2.0 và SAML hoặc OpenID Connect: OAuth 2.0 giải quyết nhiệm vụ ủy quyền (những gì được phép), không phải xác thực (người dùng là ai). Để xác thực, giao thức OpenID Connect (OIDC) được xây dựng trên OAuth 2.0.

Giao thức được hỗ trợ bởi tất cả các nền tảng lớn. Google sử dụng OAuth 2.0 để truy cập Google APIs (Gmail, Drive, Calendar), Facebook cho Graph API, Apple cho Sign in with Apple (ASAuthorizationAppleIDProvider) và GitHub để truy cập kho lưu trữ. Trong bối cảnh phát triển di động, OAuth 2.0 là cơ chế tiêu chuẩn để tích hợp các dịch vụ bên thứ ba: đăng nhập qua mạng xã hội, truy cập lưu trữ đám mây và xuất bản nội dung thay mặt người dùng.

Vai trò và thành phần của OAuth 2.0

Giao thức OAuth 2.0 xác định bốn vai trò mà sự tương tác của chúng tạo thành chu trình ủy quyền hoàn chỉnh. Hiểu từng vai trò là cần thiết để triển khai đúng giao thức trong ứng dụng di động.

Bốn vai trò của giao thức

Vai tròMô tảVí dụ
Resource OwnerChủ sở hữu dữ liệu: người dùng cho phép truy cập vào tài nguyên của họNgười dùng ứng dụng nhấp vào “Đăng nhập bằng Google”
ClientỨng dụng yêu cầu truy cập tài nguyên thay mặt chủ sở hữuỨng dụng di động cần truy cập Google Drive
Authorization ServerMáy chủ cấp mã thông báo sau khi xác thực và ủy quyềnaccounts.google.com: máy chủ ủy quyền của Google
Resource ServerAPI cung cấp quyền truy cập vào tài nguyên được bảo vệ thông qua mã thông báowww.googleapis.com: máy chủ tài nguyên của Google Drive API

Các thực thể chính của giao thức là Access Token, Refresh TokenAuthorization Code. Access Token là mã thông báo ngắn hạn (thường 15–60 phút) được trình bày cho máy chủ tài nguyên với mỗi yêu cầu dữ liệu. Refresh Token là mã thông báo dài hạn (ngày hoặc tuần) được sử dụng để lấy Access Token mới mà không yêu cầu người dùng đăng nhập lại. Authorization Code là mã tạm thời được cấp sau khi người dùng ủy quyền và được trao đổi lấy Access Token và Refresh Token.

Grant Types: các kịch bản ủy quyền

OAuth 2.0 xác định một số Grant Types: các kịch bản lấy mã thông báo, mỗi loại được thiết kế cho một loại máy khách và bối cảnh bảo mật cụ thể. Chọn đúng Grant Type là một quyết định kiến trúc quan trọng khi thiết kế ủy quyền trong ứng dụng di động.

Các Grant Types chính là: Authorization Code (an toàn nhất cho ứng dụng di động và web có thành phần máy chủ), Authorization Code với PKCE (Proof Key for Code Exchange: cho ứng dụng di động và SPA không có backend máy chủ), Client Credentials (cho xác thực máy chủ-máy chủ không có sự tham gia của người dùng), Resource Owner Password Credentials (không được khuyến khích: truyền trực tiếp mật khẩu). PKCE là phần mở rộng bắt buộc cho máy khách công khai (ứng dụng di động, SPA) theo khuyến nghị của OAuth Security BCP (RFC 9700).

Các Grant Types chính

  • Authorization Code + PKCE là Grant Type được khuyến nghị cho ứng dụng di động gốc. Máy khách tạo code_verifier mật mã, tính toán code_challenge (băm SHA-256) và máy chủ xác minh sự khớp khi trao đổi mã lấy mã thông báo. Điều này ngăn chặn việc chặn authorization code giữa ứng dụng và máy chủ
  • Client Credentials được sử dụng cho ủy quyền máy-máy nơi máy khách được biết và xác thực. Ứng dụng nhận mã thông báo bằng client_id và client_secret. Không yêu cầu sự tham gia của người dùng. Kịch bản điển hình: ứng dụng máy chủ gọi API để xử lý dữ liệu hàng loạt
  • Device Authorization Grant dành cho thiết bị không có trình duyệt (Smart TV, IoT). Người dùng theo liên kết trên thiết bị khác và nhập mã. Ví dụ: được sử dụng khi ủy quyền Netflix trên TV qua điện thoại thông minh
  • Resource Owner Password Credentials là Grant Type không được khuyến khích bị cấm bởi OAuth Security BCP. Mật khẩu được truyền trực tiếp đến máy khách, vi phạm nguyên tắc xác thực không kiến thức. Chỉ được sử dụng để di chuyển từ hệ thống kế thừa

Authorization Code Flow với PKCE cho ứng dụng di động

Authorization Code Flow với PKCE là cấu hình OAuth 2.0 được khuyến nghị cho ứng dụng di động gốc. PKCE (Proof Key for Code Exchange) thêm một lớp bảo vệ bổ sung ngăn chặn các cuộc tấn công chặn authorization code. Giao thức được mô tả trong IETF RFC 7636.

Trình tự từng bước của PKCE

Trình tự các bước: (1) máy khách tạo code_verifier ngẫu nhiên (chuỗi 43–128 ký tự chỉ sử dụng ký tự không dành riêng), (2) máy khách tính toán code_challenge = SHA-256(code_verifier), (3) máy khách mở trình duyệt để người dùng ủy quyền trên Authorization Server, truyền code_challenge, (4) sau khi ủy quyền thành công, máy chủ trả authorization code cho ứng dụng qua lược đồ URI tùy chỉnh (liên kết sâu ứng dụng), (5) máy khách gửi authorization code + code_verifier đến máy chủ, (6) máy chủ xác minh SHA-256(code_verifier) === code_challenge và cấp Access Token + Refresh Token.

Lợi thế của PKCE: ngay cả khi kẻ tấn công chặn được authorization code trong lược đồ URI, chúng không thể trao đổi nó lấy mã thông báo nếu không có code_verifier, chỉ có máy khách hợp pháp mới biết. Trong ứng dụng di động, để mở trình duyệt nên sử dụng Chrome Custom Tabs (Android) hoặc ASWebAuthenticationSession (iOS); điều này đảm bảo trình duyệt hệ thống không thể truy cập code_verifier từ bộ nhớ của ứng dụng.

Triển khai OAuth 2.0 trên Android qua AppAuth

AppAuth là triển khai tham chiếu của OAuth 2.0 và OpenID Connect cho ứng dụng gốc, được IETF khuyến nghị. Thư viện hỗ trợ PKCE, Chrome Custom Tabs, lược đồ URI tùy chỉnh để trả authorization code và tự động làm mới mã thông báo. AppAuth cho Android có sẵn qua phụ thuộc `net.openid:appauth:0.11.1`.

kotlin
val serviceConfig = AuthorizationServiceConfiguration.fromUrl(
    Uri.parse("https://accounts.google.com/.well-known/openid-configuration")
)

val request = AuthorizationRequest.Builder(
    serviceConfig,
    "CLIENT_ID.apps.googleusercontent.com",
    ResponseTypeValues.CODE,
    Uri.parse("com.example.app:/oauth2callback")
)
.setScope("openid profile email")
.setCodeVerifier(
    CodeVerifierUtil.generateRandomCodeVerifier()
)
.build()

val authService = AuthorizationService(context)
val intent = authService.getAuthorizationRequestIntent(request)

// Khởi chạy Chrome Custom Tab để ủy quyền
startActivityForResult(intent, REQUEST_CODE_AUTH)

Sau khi nhận authorization code (onActivityResult), ứng dụng trao đổi nó lấy Access Token và Refresh Token qua TokenRequest. Các mã thông báo được lưu trong SharedPreferences với mã hóa qua EncryptedSharedPreferences (Android Security Crypto). Refresh Token nên được lưu trữ trong KeyStore: kho khóa dựa trên phần cứng không thể truy cập được bởi các ứng dụng khác. Mỗi khi Access Token hết hạn, ứng dụng sử dụng Refresh Token để lấy mã mới: người dùng không cần xác thực lại.

kotlin
// Trao đổi authorization code lấy mã thông báo
val data = intent?.data ?: return
val resp = AuthorizationResponse.fromIntent(data)
val exchangeReq = resp?.createTokenExchangeRequest()
    ?: return

authService.performTokenRequest(
    exchangeReq,
    ClientAuthentication.none()
) { tokenResp, ex ->
    if (tokenResp != null) {
        // Đã nhận Access Token và Refresh Token
        val accessToken = tokenResp.accessToken
        val refreshToken = tokenResp.refreshToken
        // Lưu vào EncryptedSharedPreferences
        saveTokens(accessToken, refreshToken)
    }
}

Đoạn mã trên minh họa luồng OAuth 2.0 hoàn chỉnh với PKCE: tạo cấu hình máy chủ qua OpenID Connect Discovery, tạo yêu cầu ủy quyền với code_verifier, khởi chạy Chrome Custom Tab, nhận authorization code qua lược đồ URI tùy chỉnh và trao đổi mã lấy mã thông báo qua Token Request. Điều quan trọng là xử lý hết hạn Access Token: khi nhận phản hồi HTTP 401 từ Resource Server, ứng dụng nên sử dụng Refresh Token để lấy Access Token mới và thực thi lại yêu cầu.

Bảo mật OAuth 2.0: các cuộc tấn công điển hình và bảo vệ

OAuth 2.0 là một giao thức phức tạp với nhiều vectơ tấn công. IETF Security BCP (RFC 9700) mô tả hơn 20 lớp lỗ hổng OAuth 2.0. Đối với ứng dụng di động, quan trọng nhất là: chặn authorization code qua lược đồ URI tùy chỉnh, tấn công CSRF vào điểm cuối callback, đánh cắp Refresh Token từ bộ nhớ không an toàn và giả mạo máy khách qua chặn intent.

Bảo vệ chống lại các cuộc tấn công này bao gồm các biện pháp bắt buộc: (1) PKCE với code_challenge S256: ngăn chặn chặn authorization code ngay cả khi lược đồ URI bị chặn; (2) sử dụng tham số nonce hoặc state để ngăn CSRF: máy chủ xác minh authorization code khớp với yêu cầu gốc; (3) lưu trữ Refresh Token chỉ trong KeyStore (Android) hoặc Keychain (iOS): không bao giờ trong SharedPreferences hoặc UserDefaults; (4) sử dụng TLS với Certificate Pinning để bảo vệ chống MITM ở lớp truyền tải; (5) xác thực redirect_uri: máy chủ ủy quyền phải xác thực nghiêm ngặt sự khớp với URI đã đăng ký.

Khuyến nghị bổ sung từ IETF: ứng dụng di động nên sử dụng AppAuth hoặc các thư viện tương tự đã qua kiểm tra bảo mật; không dựa vào WebView cho OAuth (WebView không cách ly dữ liệu khỏi ứng dụng chính); triển khai xoay vòng Refresh Token tự động (mỗi Refresh Token chỉ có thể sử dụng một lần); thêm Certificate Pinning qua TrustManager cho Android và URLSession cho iOS. OpenID Connect Discovery (điểm cuối well-known) giúp tự động xác định các điểm cuối chính xác của máy chủ ủy quyền và tránh chuyển hướng đến các trang lừa đảo.

Câu hỏi thường gặp

Sự khác biệt giữa OAuth 2.0 và OpenID Connect là gì?

OAuth 2.0 là giao thức ủy quyền (được phép làm gì?), trong khi OpenID Connect (OIDC) là giao thức xác thực (người dùng là ai?). OIDC được xây dựng trên OAuth 2.0 và thêm ID Token: mã thông báo JWT chứa thông tin về danh tính người dùng. OAuth 2.0 cung cấp Access Token, OIDC bổ sung ID Token và điểm cuối UserInfo để lấy hồ sơ người dùng.

Bearer Token là gì và tại sao nó nguy hiểm?

Bearer Token là Access Token được trình bày trong tiêu đề HTTP Authorization: Bearer. Sự nguy hiểm của nó nằm ở chỗ bất kỳ ai sở hữu mã thông báo đều có thể truy cập tài nguyên: mã thông báo không gắn với máy khách. Do đó, Bearer Token chỉ được truyền qua TLS (HTTPS), có thời gian sống ngắn (15–60 phút) và không bao giờ được lưu trữ trong nhật ký hoặc tham số URL.

Tại sao PKCE bắt buộc cho ứng dụng di động?

Ứng dụng di động là máy khách công khai không có client_secret (bí mật không thể bảo vệ trong APK/IPA). Không có PKCE, kẻ tấn công có thể chặn authorization code qua lược đồ URI tùy chỉnh (ví dụ: malformed://callback?code=ABC) và trao đổi nó lấy mã thông báo. PKCE thêm code_verifier chỉ ứng dụng biết, làm cho mã bị chặn trở nên vô dụng.

Bao lâu nên làm mới Access Token?

Access Token điển hình có thời gian sống 15–60 phút (có thể cấu hình trên máy chủ ủy quyền). Với mỗi yêu cầu HTTP đến Resource Server, phản hồi được kiểm tra: nếu mã là 401, ứng dụng kích hoạt Refresh Token Flow để lấy Access Token mới. Refresh Token sống từ 24 giờ đến vài tháng, tùy thuộc vào chính sách bảo mật của nhà cung cấp. Khi Refresh Token thay đổi, mã cũ bị vô hiệu hóa.

Có thể sử dụng WebView cho OAuth 2.0 không?

Không: IETF Security BCP (RFC 9700) cấm WebView cho OAuth 2.0 trong ứng dụng di động. WebView không cách ly cookie và dữ liệu khỏi ứng dụng chính, cho phép ứng dụng chặn thông tin đăng nhập của người dùng. Thay vì WebView, hãy sử dụng Chrome Custom Tabs (Android) hoặc ASWebAuthenticationSession (iOS): các thành phần trình duyệt hệ thống được cách ly khỏi ứng dụng.

Tóm tắt

  • OAuth 2.0 là giao thức ủy quyền được ủy thác (IETF RFC 6749) thay thế truyền mật khẩu bằng mã thông báo tạm thời với phạm vi truy cập hạn chế
  • Authorization Code + PKCE là Grant Type bắt buộc cho ứng dụng di động bảo vệ khỏi chặn authorization code qua lược đồ URI
  • Access Token là mã thông báo ngắn hạn (15–60 phút) được trình bày cho Resource Server với mỗi yêu cầu dữ liệu
  • Refresh Token là mã thông báo dài hạn để làm mới Access Token liền mạch mà không yêu cầu người dùng đăng nhập lại
  • AppAuth là thư viện OAuth 2.0 tham chiếu cho Android và iOS với hỗ trợ PKCE, Custom Tabs và KeyStore
  • WebView bị cấm: OAuth 2.0 phải được thực hiện qua trình duyệt hệ thống (Custom Tabs / ASWebAuthenticationSession) theo IETF RFC 9700
  • OpenID Connect là giao thức xác thực trên OAuth 2.0 thêm ID Token (JWT) để nhận dạng người dùng

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm