Tổng quan
Vào ngày 16 tháng 2 năm 2022, chúng tôi đã thông báo về kế hoạch tăng cường bảo mật cho các hoạt động tương tác bằng OAuth của Google bằng cách sử dụng các quy trình OAuth an toàn hơn. Hướng dẫn này giúp bạn hiểu những thay đổi và bước cần thiết để di chuyển thành công từ luồng OAuth ngoài băng thông (OOB) sang các giải pháp thay thế được hỗ trợ.
Đây là biện pháp bảo vệ chống lại các cuộc tấn công giả mạo và lừa đảo ứng dụng trong quá trình tương tác với các điểm cuối uỷ quyền OAuth 2.0 của Google.
OOB là gì?
OAuth ngoài phạm vi (OOB), còn gọi là tuỳ chọn sao chép/dán thủ công, là một quy trình cũ được phát triển để hỗ trợ các ứng dụng gốc không có URI chuyển hướng để chấp nhận thông tin xác thực sau khi người dùng phê duyệt yêu cầu đồng ý OAuth. Quy trình OOB gây ra rủi ro lừa đảo từ xa và ứng dụng phải di chuyển sang một phương thức thay thế để bảo vệ khỏi lỗ hổng này.Quy trình OOB không còn được dùng nữa cho tất cả các loại ứng dụng, tức là ứng dụng web, Android, iOS, Nền tảng Windows phổ biến (UWP), ứng dụng Chrome, TV và thiết bị có khả năng nhập hạn chế, Ứng dụng dành cho máy tính.
Các mốc thời gian quan trọng về việc tuân thủ
- Ngày 28 tháng 2 năm 2022 – chặn hoạt động sử dụng OAuth mới cho quy trình OOB
- Ngày 5 tháng 9 năm 2022 – thông báo cảnh báo dành cho người dùng có thể được hiển thị cho các yêu cầu OAuth không tuân thủ
- Ngày 3 tháng 10 năm 2022 – quy trình OOB không còn được dùng nữa đối với ứng dụng OAuth được tạo trước ngày 28 tháng 2 năm 2022
- Ngày 31 tháng 1 năm 2023 – tất cả ứng dụng hiện có sẽ bị chặn (bao gồm cả ứng dụng được miễn trừ)
Thông báo lỗi dành cho người dùng sẽ xuất hiện đối với các yêu cầu không tuân thủ. Thông báo này sẽ cho người dùng biết rằng ứng dụng bị chặn trong khi hiển thị email hỗ trợ mà bạn đã đăng ký trong màn hình xin phép bằng OAuth trong Google API Console.
- Xác định xem bạn có bị ảnh hưởng hay không.
- Hãy chuyển sang một giải pháp thay thế an toàn hơn nếu bạn bị ảnh hưởng.
Xác định xem bạn có bị ảnh hưởng hay không
Việc ngừng sử dụng này chỉ áp dụng cho các ứng dụng phát hành chính thức (tức là các ứng dụng có trạng thái phát hành được đặt thành Đang phát hành chính thức). Luồng này sẽ tiếp tục hoạt động đối với các ứng dụng có trạng thái phát hành thử nghiệm.
Xem trạng thái phát hành trong OAuth của và chuyển sang bước tiếp theo nếu bạn đang sử dụng luồng OOB trong một dự án có trạng thái phát hành là "Đang phát hành".
Cách xác định xem ứng dụng của bạn có đang sử dụng luồng OOB hay không
Kiểm tra mã ứng dụng hoặc lệnh gọi mạng đi (trong trường hợp ứng dụng của bạn đang sử dụng thư viện OAuth) để xác định xem yêu cầu uỷ quyền OAuth của Google mà ứng dụng của bạn đang thực hiện có sử dụng giá trị URI chuyển hướng OOB hay không.
Kiểm tra mã ứng dụng
redirect_uri
có bất kỳ giá trị nào trong số
các giá trị sau đây hay không:
redirect_uri=urn:ietf:wg:oauth:2.0:oob
redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
redirect_uri=oob
https://accounts.google.com/o/oauth2/v2/auth? response_type=code& scope=<SCOPES>& state=<STATE>& redirect_uri=urn:ietf:wg:oauth:2.0:oob& client_id=<CLIENT_ID>
Kiểm tra lệnh gọi mạng đi
- Ứng dụng web – kiểm tra hoạt động mạng trên Chrome
- Android – kiểm tra lưu lượng truy cập mạng bằng Công cụ kiểm tra mạng
-
Ứng dụng Chrome
- Chuyển đến trang Tiện ích Chrome
- Đánh dấu vào hộp đánh dấu Chế độ nhà phát triển ở góc trên cùng bên phải của trang tiện ích
- Chọn tiện ích mà bạn muốn theo dõi
- Nhấp vào đường liên kết trang nền trong phần Kiểm tra chế độ xem trên trang phần mở rộng
- Một cửa sổ bật lên Công cụ cho nhà phát triển sẽ mở ra để bạn có thể giám sát lưu lượng truy cập mạng trong thẻ Mạng
- iOS – Phân tích lưu lượng truy cập HTTP bằng Instruments
- Universal Windows Platform (UWP) – Kiểm tra lưu lượng truy cập mạng trong Visual Studio
- Ứng dụng dành cho máy tính – sử dụng công cụ ghi lại mạng có sẵn cho hệ điều hành mà ứng dụng được phát triển
redirect_uri
có bất kỳ giá trị nào sau đây hay không:
redirect_uri=urn:ietf:wg:oauth:2.0:oob
redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
redirect_uri=oob
https://accounts.google.com/o/oauth2/v2/auth? response_type=code& scope=<SCOPES>& state=<STATE>& redirect_uri=urn:ietf:wg:oauth:2.0:oob& client_id=<CLIENT_ID>
Di chuyển sang một phương án thay thế an toàn
Ứng dụng di động (Android / iOS)
Nếu xác định rằng ứng dụng của bạn đang sử dụng quy trình OOB với loại ứng dụng OAuth Android hoặc iOS, bạn nên chuyển sang sử dụng các SDK được đề xuất (Android, iOS).
SDK này giúp bạn dễ dàng truy cập vào các API của Google và xử lý tất cả các lệnh gọi đến điểm cuối uỷ quyền OAuth 2.0 của Google.
Các đường liên kết đến tài liệu bên dưới cung cấp thông tin về cách sử dụng các SDK được đề xuất để truy cập vào API của Google mà không cần sử dụng URI chuyển hướng OOB.
Truy cập vào API của Google trên Android
Quyền truy cập phía máy khách
Ví dụ sau đây cho biết cách truy cập vào các API của Google ở phía ứng dụng trên Android bằng cách sử dụng Thư viện Android Dịch vụ nhận dạng của Google được đề xuất.
ListrequestedScopes = Arrays.asList(DriveScopes.DRIVE_APPDATA); AuthorizationRequest authorizationRequest = AuthorizationRequest.builder().setRequestedScopes(requestedScopes).build(); Identity.getAuthorizationClient(activity) .authorize(authorizationRequest) .addOnSuccessListener( authorizationResult -> { if (authorizationResult.hasResolution()) { // Access needs to be granted by the user PendingIntent pendingIntent = authorizationResult.getPendingIntent(); try { startIntentSenderForResult(pendingIntent.getIntentSender(), REQUEST_AUTHORIZE, null, 0, 0, 0, null); } catch (IntentSender.SendIntentException e) { Log.e(TAG, "Couldn't start Authorization UI: " + e.getLocalizedMessage()); } } else { // Access already granted, continue with user action saveToDriveAppFolder(authorizationResult); } }) .addOnFailureListener(e -> Log.e(TAG, "Failed to authorize", e));
Truyền authorizationResult
vào phương thức đã xác định để lưu nội dung vào thư mục ổ của người dùng. authorizationResult
có phương thức
getAccessToken()
trả về mã thông báo truy cập.
Quyền truy cập phía máy chủ (khi không có mạng)
Ví dụ sau đây cho thấy cách truy cập vào các API của Google ở phía máy chủ trên Android.ListrequestedScopes = Arrays.asList(DriveScopes.DRIVE_APPDATA); AuthorizationRequest authorizationRequest = AuthorizationRequest.builder() .requestOfflineAccess(webClientId) .setRequestedScopes(requestedScopes) .build(); Identity.getAuthorizationClient(activity) .authorize(authorizationRequest) .addOnSuccessListener( authorizationResult -> { if (authorizationResult.hasResolution()) { // Access needs to be granted by the user PendingIntent pendingIntent = authorizationResult.getPendingIntent(); try { startIntentSenderForResult(pendingIntent.getIntentSender(), REQUEST_AUTHORIZE, null, 0, 0, 0, null); } catch (IntentSender.SendIntentException e) { Log.e(TAG, "Couldn't start Authorization UI: " + e.getLocalizedMessage()); } } else { String authCode = authorizationResult.getServerAuthCode(); } }) .addOnFailureListener(e -> Log.e(TAG, "Failed to authorize", e));
authorizationResult
có phương thức
getServerAuthCode()
trả về mã uỷ quyền mà bạn có thể gửi đến phần phụ trợ để lấy mã truy cập và làm mới.
Truy cập vào API của Google trong ứng dụng iOS
Quyền truy cập phía máy khách
Ví dụ bên dưới cho thấy cách truy cập vào các API của Google ở phía máy khách trên iOS.
user.authentication.do { authentication, error in guard error == nil else { return } guard let authentication = authentication else { return } // Get the access token to attach it to a REST or gRPC request. let accessToken = authentication.accessToken // Or, get an object that conforms to GTMFetcherAuthorizationProtocol for // use with GTMAppAuth and the Google APIs client library. let authorizer = authentication.fetcherAuthorizer() }
Sử dụng mã truy cập để gọi API bằng cách đưa mã truy cập vào tiêu đề của yêu cầu REST hoặc gRPC (Authorization: Bearer ACCESS_TOKEN
) hoặc bằng cách sử dụng trình uỷ quyền trình tìm nạp (GTMFetcherAuthorizationProtocol
) với
thư viện ứng dụng API của Google cho Objective-C cho REST.
Xem lại hướng dẫn truy cập phía máy khách về cách truy cập vào các API của Google ở phía máy khách. về cách truy cập vào các API của Google ở phía máy khách.
Quyền truy cập phía máy chủ (khi không có mạng)
Ví dụ bên dưới cho thấy cách truy cập vào các API của Google ở phía máy chủ để hỗ trợ ứng dụng iOS.GIDSignIn.sharedInstance.signIn(with: signInConfig, presenting: self) { user, error in guard error == nil else { return } guard let user = user else { return } // request a one-time authorization code that your server exchanges for // an access token and refresh token let authCode = user.serverAuthCode }
Xem lại hướng dẫn truy cập phía máy chủ về cách truy cập vào API của Google từ phía máy chủ.
Ứng dụng Chrome
Nếu xác định rằng ứng dụng của bạn đang sử dụng luồng OOB trên ứng dụng Chrome, bạn nên chuyển sang sử dụng API nhận dạng Chrome.
Ví dụ bên dưới cho thấy cách lấy tất cả danh bạ của người dùng mà không cần sử dụng URI chuyển hướng OOB.
window.onload = function() { document.querySelector('button').addEventListener('click', function() { // retrieve access token chrome.identity.getAuthToken({interactive: true}, function(token) { // .......... // the example below shows how to use a retrieved access token with an appropriate scope // to call the Google People API contactGroups.get endpoint fetch( 'https://people.googleapis.com/v1/contactGroups/all?maxMembers=20&key=API_KEY', init) .then((response) => response.json()) .then(function(data) { console.log(data) }); }); }); };
Xem lại hướng dẫn về Chrome Identity API để biết thêm thông tin về cách truy cập để xác thực người dùng và gọi các điểm cuối của Google bằng Chrome Identity API.
Ứng dụng web
Nếu xác định rằng ứng dụng của bạn đang sử dụng luồng OOB cho một ứng dụng web, bạn nên chuyển sang sử dụng một trong các thư viện ứng dụng Google API của chúng tôi. Thư viện ứng dụng cho nhiều ngôn ngữ lập trình được liệt kê tại đây.
Các thư viện này giúp bạn dễ dàng truy cập vào API của Google và xử lý tất cả các lệnh gọi đến điểm cuối của Google.
Quyền truy cập phía máy chủ (khi không có mạng)
- Thiết lập máy chủ và xác định một điểm cuối có thể truy cập công khai (URI chuyển hướng) để nhận mã uỷ quyền.
- Định cấu hình URI chuyển hướng trong của
Đoạn mã dưới đây cho thấy ví dụ về NodeJS về cách sử dụng API Google Drive để liệt kê các tệp Google Drive của người dùng ở phía máy chủ mà không cần sử dụng URI chuyển hướng OOB.
async function main() { const server = http.createServer(async function (req, res) { if (req.url.startsWith('/oauth2callback')) { let q = url.parse(req.url, true).query; if (q.error) { console.log('Error:' + q.error); } else { // Get access and refresh tokens (if access_type is offline) let { tokens } = await oauth2Client.getToken(q.code); oauth2Client.setCredentials(tokens); // Example of using Google Drive API to list filenames in user's Drive. const drive = google.drive('v3'); drive.files.list({ auth: oauth2Client, pageSize: 10, fields: 'nextPageToken, files(id, name)', }, (err1, res1) => { // TODO(developer): Handle response / error. }); } } }
Xem lại hướng dẫn về ứng dụng web phía máy chủ về cách truy cập vào API của Google từ phía máy chủ.
Quyền truy cập phía máy khách
Đoạn mã dưới đây (bằng JavaScript) cho thấy ví dụ về cách sử dụng API Google để truy cập vào các sự kiện trên lịch của người dùng ở phía máy khách.
// initTokenClient() initializes a new token client with your // web app's client ID and the scope you need access to const client = google.accounts.oauth2.initTokenClient({ client_id: 'YOUR_GOOGLE_CLIENT_ID', scope: 'https://www.googleapis.com/auth/calendar.readonly', // callback function to handle the token response callback: (tokenResponse) => { if (tokenResponse && tokenResponse.access_token) { gapi.client.setApiKey('YOUR_API_KEY'); gapi.client.load('calendar', 'v3', listUpcomingEvents); } }, }); function listUpcomingEvents() { gapi.client.calendar.events.list(...); }
Xem lại hướng dẫn về ứng dụng web phía máy khách về cách truy cập vào các API của Google từ phía máy khách.
Ứng dụng dành cho máy tính
Nếu xác định rằng ứng dụng của bạn đang sử dụng luồng OOB trên ứng dụng máy tính, bạn nên chuyển sang sử dụng
luồng địa chỉ IP loopback (localhost
hoặc 127.0.0.1
).