ภาพรวม
เมื่อวันที่ 16 กุมภาพันธ์ 2022 เราได้ประกาศแผนที่จะทำให้การโต้ตอบ OAuth ของ Google ปลอดภัยยิ่งขึ้นโดยใช้โฟลว์ OAuth ที่ปลอดภัยกว่า คู่มือนี้จะช่วยให้คุณเข้าใจการเปลี่ยนแปลงและขั้นตอนที่จำเป็นในการย้ายข้อมูลจากขั้นตอนที่อยู่ IP แบบ Loopback ไปยังทางเลือกที่รองรับได้สำเร็จ
ความพยายามนี้เป็นมาตรการป้องกันการโจมตีแบบฟิชชิงและการแอบอ้างเป็นแอปในระหว่างการโต้ตอบกับปลายทางการให้สิทธิ์ OAuth 2.0 ของ Google
ขั้นตอนการใช้ที่อยู่ IP แบบ Loopback คืออะไร
ขั้นตอนที่อยู่ IP แบบ Loopback รองรับการใช้ที่อยู่ IP แบบ Loopback หรือ localhost เป็นคอมโพเนนต์โฮสต์ของ URI การเปลี่ยนเส้นทางที่ระบบจะส่งข้อมูลเข้าสู่ระบบไปให้หลังจากที่ผู้ใช้อนุมัติคำขอยินยอม OAuth ขั้นตอนการทำงานนี้เสี่ยงต่อการโจมตีแบบแทรกกลางการสื่อสาร ซึ่งแอปที่เป็นอันตรายซึ่งเข้าถึงอินเทอร์เฟซ Loopback เดียวกันในระบบปฏิบัติการบางระบบอาจขัดขวางการตอบกลับจากเซิร์ฟเวอร์การให้สิทธิ์ไปยัง URI การเปลี่ยนเส้นทางที่ระบุและเข้าถึงรหัสการให้สิทธิ์
เราจะเลิกใช้งานขั้นตอนที่อยู่ IP ของ Loopback สำหรับประเภทไคลเอ็นต์ OAuth ของ iOS, Android และ Chrome แต่จะยังคงรองรับในแอปบนเดสก์ท็อป
วันที่สำคัญในการปฏิบัติตามข้อกำหนด
- 14 มีนาคม 2022 - บล็อกไคลเอ็นต์ OAuth ใหม่ไม่ให้ใช้โฟลว์ที่อยู่ IP แบบ Loopback
- 1 สิงหาคม 2022 - ข้อความเตือนที่แสดงต่อผู้ใช้อาจแสดงขึ้นสำหรับคำขอ OAuth ที่ไม่เป็นไปตามข้อกำหนด
- 31 สิงหาคม 2022 - ระบบจะบล็อกขั้นตอนที่อยู่ IP ของ Loopback สำหรับไคลเอ็นต์ OAuth ของ Android, แอป Chrome และ iOS ที่สร้างก่อนวันที่ 14 มีนาคม 2022
- 21 ตุลาคม 2022 - ไคลเอ็นต์ที่มีอยู่ทั้งหมดจะถูกบล็อก (รวมถึงไคลเอ็นต์ที่ได้รับการยกเว้น)
ข้อความแสดงข้อผิดพลาดที่แสดงต่อผู้ใช้จะปรากฏขึ้นสำหรับคำขอที่ไม่เป็นไปตามข้อกำหนด ข้อความจะแจ้งให้ผู้ใช้ทราบว่าแอปถูกบล็อกขณะแสดงอีเมลสนับสนุนที่คุณลงทะเบียนไว้ในหน้าจอขอความยินยอม OAuth ในคอนโซล Google Cloud
คุณต้องทำตาม 2 ขั้นตอนหลักต่อไปนี้เพื่อย้ายข้อมูลให้เสร็จสมบูรณ์
- ตรวจสอบว่าคุณได้รับผลกระทบหรือไม่
- โปรดเปลี่ยนไปใช้ทางเลือกอื่นที่รองรับหากคุณได้รับผลกระทบ
ตรวจสอบว่าคุณได้รับผลกระทบหรือไม่
ตรวจสอบประเภทรหัสไคลเอ็นต์ OAuth
ไปที่หน้าไคลเอ็นต์ของคอนโซล Google Cloud และดูประเภทรหัสไคลเอ็นต์ OAuth ในส่วนรหัสไคลเอ็นต์ OAuth 2.0 ซึ่งจะเป็นประเภทใดประเภทหนึ่งต่อไปนี้ เว็บแอปพลิเคชัน, Android, iOS, Universal Windows Platform (UWP), แอป Chrome, ทีวีและอุปกรณ์ที่มีอินพุตจำกัด, แอปบนเดสก์ท็อป
ดำเนินการต่อในขั้นตอนถัดไปหากประเภทไคลเอ็นต์ของคุณคือ Android, แอป Chrome หรือ iOS และคุณกำลังใช้ขั้นตอนที่อยู่ IP ของ Loopback
คุณไม่จำเป็นต้องดำเนินการใดๆ ที่เกี่ยวข้องกับการเลิกใช้งานนี้หากใช้ขั้นตอนที่อยู่ IP แบบ Loopback ในไคลเอ็นต์ OAuth ของแอปบนเดสก์ท็อป เนื่องจากระบบจะยังคงรองรับการใช้งานกับไคลเอ็นต์ OAuth ประเภทดังกล่าวต่อไป
วิธีตรวจสอบว่าแอปของคุณใช้ขั้นตอนการตรวจสอบสิทธิ์ที่อยู่ IP แบบ Loopback หรือไม่
ตรวจสอบโค้ดของแอปหรือการเรียกเครือข่ายขาออก (ในกรณีที่แอปใช้ไลบรารี OAuth) เพื่อดูว่าคำขอการให้สิทธิ์ OAuth ของ Google ที่แอปสร้างขึ้นใช้ค่า URI การเปลี่ยนเส้นทางแบบ Loopback หรือไม่
ตรวจสอบโค้ดของแอปพลิเคชัน
ตรวจสอบส่วนของโค้ดแอปพลิเคชันที่คุณเรียกใช้ปลายทางการให้สิทธิ์ของ Google OAuth และพิจารณาว่าพารามิเตอร์ redirect_uri มีค่าใดค่าหนึ่งต่อไปนี้หรือไม่
redirect_uri=http://127.0.0.1:<port>(เช่นredirect_uri=http://127.0.0.1:3000)redirect_uri=http://[::1]:<port>(เช่นredirect_uri=http://[::1]:3000)redirect_uri=http://localhost:<port>(เช่นredirect_uri=http://localhost:3000)
ตัวอย่างคำขอขั้นตอนการเปลี่ยนเส้นทางที่อยู่ IP แบบ Loopback จะมีลักษณะดังนี้
https://accounts.google.com/o/oauth2/v2/auth? redirect_uri=http://localhost:3000& response_type=code& scope=<SCOPES>& state=<STATE>& client_id=<CLIENT_ID>
ตรวจสอบการเรียกใช้เครือข่ายขาออก
วิธีการตรวจสอบการเรียกใช้เครือข่ายจะแตกต่างกันไปตามประเภทไคลเอ็นต์ของแอปพลิเคชัน
- เว็บแอปพลิเคชัน - ตรวจสอบกิจกรรมเครือข่ายใน Chrome
- Android - ตรวจสอบการจราจรของข้อมูลในเครือข่ายด้วยเครื่องมือตรวจสอบเครือข่าย
- แอป Chrome
- ไปที่หน้าส่วนขยาย Chrome
- เลือกช่องทำเครื่องหมายโหมดนักพัฒนาซอฟต์แวร์ที่มุมขวาบนของหน้าส่วนขยาย
- เลือกส่วนขยายที่ต้องการตรวจสอบ
- คลิกลิงก์หน้าพื้นหลังในส่วนตรวจสอบมุมมองของหน้าส่วนขยาย
- กล่องโต้ตอบเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์จะเปิดขึ้น ซึ่งคุณสามารถตรวจสอบการจราจรของข้อมูลในเครือข่ายได้ในแท็บเครือข่าย
- iOS - การวิเคราะห์การเข้าชม HTTP ด้วย Instruments
- แอปบนเดสก์ท็อป - ใช้เครื่องมือจับภาพเครือข่าย ที่พร้อมใช้งานสำหรับระบบปฏิบัติการที่พัฒนาแอปขึ้นมา
ขณะตรวจสอบการเรียกใช้เครือข่าย ให้มองหาคำขอที่ส่งไปยังปลายทางการให้สิทธิ์ OAuth ของ Google และพิจารณาว่าพารามิเตอร์ redirect_uri มีค่าใดค่าหนึ่งต่อไปนี้หรือไม่
redirect_uri=http://127.0.0.1:<port>(เช่นredirect_uri=http://127.0.0.1:3000)redirect_uri=http://[::1]:<port>(เช่นredirect_uri=http://[::1]:3000)redirect_uri=http://localhost:<port>(เช่นredirect_uri=http://localhost:3000)
ตัวอย่างคำขอขั้นตอนการเปลี่ยนเส้นทางที่อยู่ IP แบบ Loopback จะมีลักษณะดังนี้
https://accounts.google.com/o/oauth2/v2/auth? redirect_uri=http://localhost:3000& response_type=code& scope=<SCOPES>& state=<STATE>& client_id=<CLIENT_ID>
ย้ายข้อมูลไปยังทางเลือกอื่นที่รองรับ
ไคลเอ็นต์มือถือ (Android และ iOS)
หากพบว่าแอปใช้ขั้นตอนที่อยู่ IP แบบ Loopback กับประเภทไคลเอ็นต์ OAuth ของ Android หรือ iOS คุณควรย้ายข้อมูลไปใช้ SDK ที่แนะนำ (Android, iOS)
SDK ช่วยให้คุณเข้าถึง Google APIs และจัดการการเรียกใช้ปลายทางการให้สิทธิ์ OAuth 2.0 ของ Google ทั้งหมด
ลิงก์เอกสารต่อไปนี้ให้ข้อมูลเกี่ยวกับวิธีใช้ SDK ที่แนะนำเพื่อเข้าถึง Google APIs โดยไม่ต้องใช้ URI การเปลี่ยนเส้นทางที่อยู่ IP แบบ Loopback
เข้าถึง Google APIs ใน Android
การเข้าถึงฝั่งไคลเอ็นต์
ตัวอย่างต่อไปนี้แสดงวิธีเข้าถึง Google API ฝั่งไคลเอ็นต์ใน Android โดยใช้ไลบรารี Android ของ Google Identity Services ที่แนะนำ
List<Scopes> requestedScopes = 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));
ส่ง authorizationResult ไปยังเมธอดที่กำหนดไว้เพื่อบันทึกเนื้อหาลงในโฟลเดอร์ไดรฟ์ของผู้ใช้ authorizationResult มีเมธอด getAccessToken() ที่แสดงผลโทเค็นเพื่อการเข้าถึง
การเข้าถึงฝั่งเซิร์ฟเวอร์ (ออฟไลน์)
ตัวอย่างต่อไปนี้แสดงวิธีเข้าถึง Google APIs ฝั่งเซิร์ฟเวอร์ใน Android
List<Scopes> requestedScopes = 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 มีเมธอด getServerAuthCode() ที่แสดงรหัสการให้สิทธิ์ซึ่งคุณสามารถส่งไปยังแบ็กเอนด์เพื่อรับโทเค็นเพื่อการเข้าถึงและโทเค็นการรีเฟรช
เข้าถึง Google APIs ในแอป iOS
การเข้าถึงฝั่งไคลเอ็นต์
ตัวอย่างต่อไปนี้แสดงวิธีเข้าถึง Google APIs ฝั่งไคลเอ็นต์ใน 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() }
ใช้โทเค็นเพื่อการเข้าถึงเพื่อเรียก API โดยใส่โทเค็นเพื่อการเข้าถึงไว้ในส่วนหัวของคำขอ REST หรือ gRPC (Authorization: Bearer <var>ACCESS_TOKEN</var>) หรือใช้ผู้อนุมัติ Fetcher (GTMFetcherAuthorizationProtocol) กับไลบรารีของไคลเอ็นต์ Google APIs สำหรับ Objective-C สำหรับ REST
ดูคู่มือการเข้าถึงฝั่งไคลเอ็นต์เกี่ยวกับวิธีเข้าถึง Google API ในฝั่งไคลเอ็นต์
การเข้าถึงฝั่งเซิร์ฟเวอร์ (ออฟไลน์)
ตัวอย่างต่อไปนี้แสดงวิธีเข้าถึง Google APIs ฝั่งเซิร์ฟเวอร์เพื่อรองรับไคลเอ็นต์ 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
}ดูคู่มือการเข้าถึงฝั่งเซิร์ฟเวอร์เกี่ยวกับวิธีเข้าถึง Google APIs จากฝั่งเซิร์ฟเวอร์
ไคลเอ็นต์แอป Chrome
หากพบว่าแอปใช้ขั้นตอนที่อยู่ IP ของ Loopback ในไคลเอ็นต์แอป Chrome คุณควรเปลี่ยนไปใช้ Chrome Identity API
ตัวอย่างต่อไปนี้แสดงวิธีรับรายชื่อติดต่อของผู้ใช้ทั้งหมดโดยไม่ต้องใช้ URI การเปลี่ยนเส้นทางที่อยู่ IP แบบ Loopback
window.onload = function() { document.querySelector('button').addEventListener('click', function() { // retrieve access token chrome.identity.getAuthToken({interactive: true}, function(token) { // .......... // the following example 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) }); }); }); };
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีเข้าถึงผู้ใช้ที่ตรวจสอบสิทธิ์แล้วและเรียกใช้ปลายทางของ Google ด้วย Chrome Identity API ได้ที่คู่มือ Chrome Identity API