Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang
Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.
Tính năng liên kết Lật ứng dụng dựa trên OAuth (App Flip) sẽ mở ứng dụng iOS của bạn từ một ứng dụng của Google
để giúp người dùng ứng dụng Google liên kết tài khoản của họ dễ dàng hơn. Bạn cần thực hiện
các thay đổi nhỏ về mã đối với ứng dụng iOS để triển khai tính năng này.
Trong tài liệu này, bạn sẽ tìm hiểu cách sửa đổi ứng dụng iOS của mình để hỗ trợ tính năng Lật ứng dụng.
Dùng thử mẫu
Ứng dụng mẫu App Flip
minh hoạ hoạt động tích hợp liên kết tài khoản trên iOS tương thích với ứng dụng App Flip.
Bạn có thể dùng ứng dụng này để xác minh cách phản hồi một lượt chuyển đổi ứng dụng đến ở dạng phổ quát
liên kết từ ứng dụng di động của Google.
Ứng dụng mẫu được định cấu hình sẵn để tích hợp với Công cụ kiểm thử độ lật ứng dụng cho
iOS,
mà bạn có thể sử dụng để xác minh việc tích hợp ứng dụng iOS của mình với App Flip trước
bạn định cấu hình liên kết tài khoản với Google. Ứng dụng này mô phỏng đường liên kết phổ quát
được kích hoạt bởi các ứng dụng di động của Google khi Lật ứng dụng được bật.
Cách hoạt động
Sau đây là các bước quy trình mà ứng dụng Google và ứng dụng của bạn sẽ thực hiện khi
Lật ứng dụng sẽ diễn ra:
Ứng dụng Google cố gắng mở đường liên kết chung của ứng dụng. Công cụ này có thể
mở ứng dụng của bạn nếu ứng dụng đó được cài đặt trên thiết bị của người dùng và được liên kết với
đường liên kết phổ quát. Hãy xem phần Hỗ trợ đường liên kết phổ quát để biết thông tin chi tiết.
Ứng dụng của bạn sẽ kiểm tra để đảm bảo rằng tham số client_id và redirect_uri đã mã hoá
trong URL đến khớp với đường liên kết chung dự kiến của Google.
Ứng dụng của bạn yêu cầu mã uỷ quyền từ máy chủ OAuth2. Ở cuối
của quy trình này, ứng dụng của bạn sẽ trả về một mã uỷ quyền hoặc một lỗi
ứng dụng Google. Để thực hiện thao tác này, thao tác này sẽ mở đường liên kết chung của Google với
các tham số cho mã hoặc lỗi uỷ quyền.
Ứng dụng Google xử lý đường liên kết phổ quát đến của Google và tiếp tục với
phần còn lại của quy trình. Nếu bạn cung cấp mã uỷ quyền, việc liên kết sẽ
hoàn tất ngay lập tức. Quá trình trao đổi mã thông báo diễn ra từ máy chủ đến máy chủ, tương tự như
trong quy trình liên kết OAuth dựa trên trình duyệt. Nếu mã lỗi là
sẽ trả về, quy trình liên kết sẽ tiếp tục với các tuỳ chọn thay thế.
Sửa đổi ứng dụng iOS của bạn để hỗ trợ tính năng Lật ứng dụng
Để hỗ trợ App Flip (Lật ứng dụng), hãy thay đổi mã sau đây cho ứng dụng iOS của bạn:
Xử lý NSUserActivityTypeBrowsingWeb trong Uỷ quyền ứng dụng.
Thu thập tham số redirect_uri và state từ URL để sử dụng sau này.
Kiểm tra để đảm bảo redirect_uri khớp với định dạng sau:
Sau khi uỷ quyền thành công, hãy gọi URI chuyển hướng bằng lệnh uỷ quyền
. Hãy sử dụng mã mẫu sau:
funcreturnAuthCode(code:String,state:String,redirectUri:String){varredirectURL=URL(string:redirectUri)varcomponents=URLComponents(url:redirectURL,resolvingAgainstBaseURL:false)// Return the authorization code and original stateletparamAuthCode=URLQueryItem(name:"code",value:code)letparamState=URLQueryItem(name:"state",value:state)components?.queryItems=[paramAuthCode,paramState]ifletresultURL=components?.url{UIApplication.shared.open(resultURL,options:[UIApplicationOpenURLOptionUniversalLinksOnly:true],completionHandler:nil)}}
Nếu xảy ra lỗi, hãy đính kèm kết quả lỗi vào URI chuyển hướng.
Hãy sử dụng mã mẫu sau:
funcreturnError(redirectUri:String){varredirectURL=URL(string:redirectUri)varcomponents=URLComponents(url:redirectURL,resolvingAgainstBaseURL:false)// Return the authorization code and original stateletparamError=URLQueryItem(name:"error",value:"invalid_request")letparamDescription=URLQueryItem(name:"error_description",value:"Invalid Request")components?.queryItems=[paramError,paramDescription]ifletresultURL=components?.url{UIApplication.shared.open(resultURL,options:[UIApplicationOpenURLOptionUniversalLinksOnly:true],completionHandler:nil)}}
Tham số truy vấn cho đường liên kết chung của ứng dụng
Khi ứng dụng Google mở, đường liên kết chung của ứng dụng sẽ chứa những thông tin sau
tham số truy vấn:
client_id (String): Google client_id được đăng ký trong ứng dụng của bạn.
scope (List of String): Danh sách các phạm vi được phân tách bằng dấu cách được yêu cầu.
state (String): Một số chỉ dùng một lần được Google sử dụng để xác minh rằng lệnh uỷ quyền
là nhằm phản hồi yêu cầu gửi đi của Google.
redirect_uri (String): Đường liên kết phổ quát của Google. "Lật trang" URI sẽ mở
ứng dụng Google và chuyển kết quả.
Tham số truy vấn cho đường liên kết phổ quát của Google
Các tham số được dùng khi kết quả uỷ quyền được trả về thành công:
code (String): Giá trị của mã uỷ quyền, nếu có.
state (String): Giá trị chính xác nhận được từ đường liên kết chung đến.
Các tham số được dùng khi kết quả uỷ quyền được trả về không thành công:
error (String), với các giá trị sau:
cancelled: Lỗi có thể khôi phục. Ứng dụng Google sẽ cố gắng tìm tài khoản
bằng cách sử dụng URL uỷ quyền. Một số ví dụ là người dùng không thành công
để đăng nhập, thiết bị không có kết nối mạng hoặc hết thời gian kết nối.
unrecoverable: Lỗi không thể khôi phục. Ví dụ: người dùng cố gắng liên kết với một tài khoản đã bị vô hiệu hoá.Ứng dụng Google sẽ huỷ việc liên kết tài khoản.
invalid_request: Tham số yêu cầu không hợp lệ hoặc bị thiếu. Đây là lỗi có thể khôi phục. Ứng dụng Google sẽ cố gắng liên kết tài khoản bằng URL uỷ quyền.
access_denied: Người dùng từ chối yêu cầu đồng ý. Đây là lỗi không thể khôi phục; ứng dụng Google sẽ huỷ liên kết.
error_description (String, không bắt buộc): Thông báo lỗi thân thiện với người dùng.
Đối với tất cả các loại lỗi, bạn phải trả về dữ liệu phản hồi cho
REDIRECT_URI để đảm bảo phân loại dự phòng thích hợp.
Sửa đổi điểm cuối uỷ quyền để hỗ trợ App Flip
Định cấu hình nền tảng của bạn để chấp nhận các yêu cầu sử dụng URL chuyển hướng App Flip của Google:
Kiểm tra để đảm bảo client_id và URL được chỉ định bởi tham số redirect_uri
khớp với các giá trị dự kiến khi nhận được yêu cầu. nếu khách hàng xác minh
không thành công, hãy trả về lỗi invalid_request cho redirect_uri.
[null,null,["Cập nhật lần gần đây nhất: 2025-07-25 UTC."],[[["\u003cp\u003eOAuth-based App Flip linking simplifies account linking for Google app users by enabling them to seamlessly open your iOS app for authorization.\u003c/p\u003e\n"],["\u003cp\u003eTo support App Flip, you need to modify your iOS app to handle universal links, validate incoming parameters, and return authorization codes or errors to the Google app.\u003c/p\u003e\n"],["\u003cp\u003eYour authorization endpoint must be configured to accept Google's App Flip redirect URLs and perform client verification for incoming requests.\u003c/p\u003e\n"],["\u003cp\u003eThe App Flip sample app and test tool provide a practical demonstration and verification environment for your iOS app's integration with App Flip.\u003c/p\u003e\n"]]],[],null,["OAuth-based App Flip linking (App Flip) opens your iOS app from a Google app\nto help the Google app user link their account more easily. You need to make\nminor code changes to your iOS app to implement this feature.\n\nIn this document, you learn how to modify your iOS app to support App Flip.\n\nTry the sample\n\nThe App Flip [sample app](https://github.com/googlesamples/identity-appflip-ios)\ndemonstrates an account linking integration on iOS that's App Flip-compatible.\nYou can use this app to verify how to respond to an incoming App Flip universal\nlink from Google mobile apps.\n\nThe sample app is preconfigured to integrate with the [App Flip Test Tool for\niOS](https://github.com/googlesamples/identity-appflip-tester-ios),\nwhich you can use to verify your iOS app's integration with App Flip before\nyou configure account linking with Google. This app simulates the universal link\ntriggered by Google mobile apps when App Flip is enabled.\n\nHow it works\n\nThe following are the flow steps that the Google app and your app take when\nApp Flip occurs:\n\n1. The Google app attempts to open your app's universal link. It's able to\n open your app if it's installed on the user's device and associated with\n the universal link. See [Supporting Universal Links](https://developer.apple.com/documentation/uikit/inter-process_communication/allowing_apps_and_websites_to_link_to_your_content) for details.\n\n2. Your app checks that the `client_id` and `redirect_uri` parameter encoded\n in the incoming URL matches the expected Google universal link.\n\n3. Your app requests an authorization code from your OAuth2 server. At the end\n of this flow, your app returns either an authorization code or an error to\n the Google app. To do this, it opens Google's universal link with appended\n parameters for the authorization code or error.\n\n4. The Google app handles the incoming Google universal link and continues with\n the rest of the flow. If an authorization code is provided, the linking is\n completed immediately. The token exchange happens server-to-server, the same\n way it does in the browser-based OAuth linking flow. If an error code is\n returned, the linking flow continues with the alternative options.\n\nModify your iOS app to support App Flip\n\nTo support App Flip, make the following code changes to your iOS app:\n\n1. Handle `NSUserActivityTypeBrowsingWeb` in your App Delegate.\n2. Capture `redirect_uri` and `state` parameters from the URL to use later.\n3. Check that `redirect_uri` matches this format: \n\n ```\n https://oauth-redirect.googleusercontent.com/a/GOOGLE_APP_BUNDLE_ID\n https://oauth-redirect-sandbox.googleusercontent.com/a/GOOGLE_APP_BUNDLE_ID\n ```\n4. Verify that the client ID matches the expected value. Use the following\n code sample:\n\n func application(_ application: UIApplication,\n continue userActivity: NSUserActivity,\n restorationHandler: @escaping ([Any]?) -\u003e Void) -\u003e Bool\n {\n guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,\n let incomingURL = userActivity.webpageURL,\n let components = URLComponents(url: incomingURL, resolvingAgainstBaseURL: false),\n let params = components.queryItems else {\n return false\n }\n\n if let clientId = params.filter({$0.name == \"client_id\"}).first?.value,\n let state = params.filter({$0.name == \"state\"}).first?.value,\n let redirectUri = params.filter({$0.name == \"redirect_uri\"}).first?.value {\n\n // Save the redirect_uri and state for later...\n\n // Verify the client id\n return (clientId == GOOGLE_CLIENT_ID)\n } else {\n // Missing required parameters\n return false\n }\n }\n\n5. Upon successful authorization, call the redirect URI with the authorization\n code. Use the following code sample:\n\n func returnAuthCode(code: String, state: String, redirectUri: String) {\n var redirectURL = URL(string: redirectUri)\n var components = URLComponents(url: redirectURL, resolvingAgainstBaseURL: false)\n\n // Return the authorization code and original state\n let paramAuthCode = URLQueryItem(name: \"code\", value: code)\n let paramState = URLQueryItem(name: \"state\", value: state)\n components?.queryItems = [paramAuthCode, paramState]\n if let resultURL = components?.url {\n UIApplication.shared.open(\n resultURL,\n options: [UIApplicationOpenURLOptionUniversalLinksOnly : true],\n completionHandler: nil)\n }\n }\n\n6. If an error occurred, attach an error result to the redirect URI instead.\n Use the following code sample:\n\n **Note:** Do not handle the error directly within your app, instead return the error result to the `REDIRECT_URL`. This ensures that the appropriate fallback method is trigerred if the app linking flow fails. \n\n func returnError(redirectUri: String) {\n var redirectURL = URL(string: redirectUri)\n var components = URLComponents(url: redirectURL, resolvingAgainstBaseURL: false)\n\n // Return the authorization code and original state\n let paramError = URLQueryItem(name: \"error\", value: \"invalid_request\")\n let paramDescription = URLQueryItem(name: \"error_description\", value: \"Invalid Request\")\n components?.queryItems = [paramError, paramDescription]\n if let resultURL = components?.url {\n UIApplication.shared.open(\n resultURL,\n options: [UIApplicationOpenURLOptionUniversalLinksOnly : true],\n completionHandler: nil)\n }\n }\n\nQuery parameters for your app's universal link\n\nWhen opened by the Google app, your app's universal link includes the following\nquery parameters:\n\n- `client_id` (`String`): Google `client_id` that's registered under your app.\n- `scope` (`List of String`): A list of space-separated scopes requested.\n- `state` (`String`): A nonce used by Google to verify that the authorization result is in response to Google's outgoing request.\n- `redirect_uri` (`String`): Google's universal link. The \"flip\" URI to open the Google app and pass results.\n\nQuery parameters for Google's universal link\n\nParameters used when the authorization result is returned successfully:\n\n- `code` (`String`): The value of the authorization code, if available.\n- `state` (`String`): The exact value received from the incoming universal link.\n\nParameters used when the authorization result is returned unsuccessfully:\n\n- `error` (`String`), with the following values:\n\n - `cancelled`: A recoverable error. The Google app will attempt account linking using the authorization URL. Some examples are the user failing to sign in, a device being offline or a connection timing out.\n - `unrecoverable`: An unrecoverable error. For example, the user attempts to link with a disabled account.The Google app will abort account linking.\n - `invalid_request`: The request parameters are invalid or missing. This is a recoverable error. The Google app will attempt account linking using the authorization URL.\n - `access_denied`: The user rejects the consent request. This is a non-recoverable error; the Google app aborts linking.\n- `error_description` (`String`, optional): A user-friendly error message.\n\n | **Note:** For more information on [possible errors](https://www.oauth.com/oauth2-servers/server-side-apps/possible-errors/) and the optional contents of the `error_description` field, see the OAuth 2.0 standard.\n\nFor all error types, you must return the response data to the specified\n`REDIRECT_URI` to ensure the appropriate fallback is trigerred.\n\nModify your authorization endpoint to support App Flip\n\nConfigure your platform to accept requests using Google's App Flip redirect URLs:\n\n- Google Home app \n\n ```\n https://oauth-redirect.googleusercontent.com/a/com.google.Chromecast.dev\n https://oauth-redirect.googleusercontent.com/a/com.google.Chromecast.enterprise\n https://oauth-redirect.googleusercontent.com/a/com.google.Chromecast\n https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.Chromecast.dev\n https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.Chromecast.enterprise\n https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.Chromecast\n ```\n- Google Assistant app \n\n ```\n https://oauth-redirect.googleusercontent.com/a/com.google.OPA.dev\n https://oauth-redirect.googleusercontent.com/a/com.google.OPA.enterprise\n https://oauth-redirect.googleusercontent.com/a/com.google.OPA\n https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.OPA.dev\n https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.OPA.enterprise\n https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.OPA\n ```\n\nCheck that `client_id` and the URL specified by the `redirect_uri` parameter\nmatch the expected values when a request is received. if the client verification\nfails, return the error `invalid_request` to the `redirect_uri`."]]