คู่มือการย้ายข้อมูลโฟลว์ IP ของ Loopback

ภาพรวม

เมื่อวันที่ 16 กุมภาพันธ์ 2022 เราได้ ประกาศ แผนที่จะทำให้การโต้ตอบของ Google OAuth ปลอดภัยยิ่งขึ้นโดยใช้ขั้นตอน OAuth ที่ปลอดภัยกว่า คู่มือนี้จะช่วยให้คุณเข้าใจการเปลี่ยนแปลงและขั้นตอนที่จำเป็นเพื่อ ย้ายข้อมูลจากโฟลว์ที่อยู่ IP แบบวนรอบไปยังทางเลือกที่รองรับได้สำเร็จ

ความพยายามนี้เป็นมาตรการป้องกันการโจมตีแบบฟิชชิงและการแอบอ้างเป็นแอป ในระหว่างการโต้ตอบกับปลายทางการให้สิทธิ์ OAuth 2.0 ของ Google

ขั้นตอนการทำงานของที่อยู่ IP แบบวนรอบคืออะไร

โฟลว์ที่อยู่ IP แบบวนรอบรองรับการใช้ที่อยู่ IP แบบวนรอบหรือ localhost เป็นคอมโพเนนต์โฮสต์ของ URI เปลี่ยนเส้นทางซึ่ง ระบบจะส่งข้อมูลเข้าสู่ระบบไปหลังจากที่ผู้ใช้อนุมัติคำขอความยินยอมของ OAuth ขั้นตอนการทำงานนี้ เสี่ยงต่อ การโจมตีแบบแทรกกลางการสื่อสาร ซึ่งแอปที่ไม่ประสงค์ดีที่เข้าถึงอินเทอร์เฟซแบบวนรอบเดียวกันในระบบปฏิบัติการ บางระบบอาจสกัดกั้นการตอบกลับจากเซิร์ฟเวอร์การให้สิทธิ์ไปยัง 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 API

คุณต้องทำตาม 2 ขั้นตอนหลักต่อไปนี้เพื่อให้กระบวนการย้ายข้อมูลเสร็จสมบูรณ์
  1. ตรวจสอบว่าคุณได้รับผลกระทบหรือไม่
  2. โปรดเปลี่ยนไปใช้ทางเลือกอื่นที่รองรับหากคุณได้รับผลกระทบ

ตรวจสอบว่าคุณได้รับผลกระทบหรือไม่

ตรวจสอบประเภทรหัสไคลเอ็นต์ OAuth

ไปที่ Clients page ของ Google Cloud Console และดูประเภทรหัสไคลเอ็นต์ OAuth ในส่วน รหัสไคลเอ็นต์ OAuth 2.0 ซึ่งจะเป็นอย่างใดอย่างหนึ่งต่อไปนี้ เว็บแอปพลิเคชัน, Android, iOS, Universal Windows Platform (UWP), แอป Chrome, ทีวีและอุปกรณ์ที่มีการป้อนข้อมูลจำกัด, แอปเดสก์ท็อป

ไปยังขั้นตอนถัดไปหากประเภทไคลเอ็นต์ของคุณคือ Android, แอป Chrome หรือ iOS และคุณใช้ โฟลว์ที่อยู่ IP ของ Loopback

คุณไม่จำเป็นต้องดำเนินการใดๆ เกี่ยวกับการเลิกใช้งานนี้หากใช้โฟลว์ที่อยู่ IP ของ Loopback ในไคลเอ็นต์ OAuth ของแอปบนเดสก์ท็อป เนื่องจากระบบจะยังคงรองรับการใช้งานกับประเภทไคลเอ็นต์ OAuth นั้นต่อไป

วิธีตรวจสอบว่าแอปใช้โฟลว์ที่อยู่ IP แบบวนกลับหรือไม่

ตรวจสอบโค้ดแอปหรือการเรียกเครือข่ายขาออก (ในกรณีที่แอปใช้ไลบรารี OAuth) เพื่อพิจารณาว่า คำขอการให้สิทธิ์ ของ Google OAuth ที่แอปของคุณสร้างใช้ค่า URI เปลี่ยนเส้นทางแบบวนซ้ำหรือไม่

ตรวจสอบโค้ดของแอปพลิเคชัน

ตรวจสอบส่วนของโค้ดแอปพลิเคชันที่คุณทำการเรียกไปยัง 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 แบบวนซ้ำตัวอย่างจะมีลักษณะดังที่ ด้านล่าง
https://accounts.google.com/o/oauth2/v2/auth?
redirect_uri=http://localhost:3000&
response_type=code&
scope=<SCOPES>&
state=<STATE>&
client_id=<CLIENT_ID>

ตรวจสอบการเรียกเครือข่ายขาออก

วิธีการตรวจสอบการเรียกเครือข่ายจะแตกต่างกันไปตามประเภทไคลเอ็นต์ของแอปพลิเคชัน
ขณะตรวจสอบการเรียกเครือข่าย ให้มองหาคำขอที่ส่งไปยัง 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 แบบวนซ้ำตัวอย่างจะมีลักษณะดังตัวอย่างด้านล่าง
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 แบบวนซ้ำกับไคลเอ็นต์ OAuth ของ Android หรือ iOS คุณควรย้ายข้อมูลไปใช้ SDK ที่แนะนํา (Android iOS)

SDK ช่วยให้เข้าถึง Google APIs ได้ง่ายและจัดการการเรียกไปยัง ปลายทางการให้สิทธิ์ OAuth 2.0 ของ Google ทั้งหมด

ลิงก์เอกสารประกอบด้านล่างนี้มีข้อมูลเกี่ยวกับวิธีใช้ SDK ที่แนะนำเพื่อเข้าถึง Google APIs โดยไม่ต้องใช้ที่อยู่ IP แบบวนรอบ URI การเปลี่ยนเส้นทาง

เข้าถึง Google APIs ใน Android

การเข้าถึงฝั่งไคลเอ็นต์

ตัวอย่างต่อไปนี้แสดงวิธีเข้าถึง Google APIs ในฝั่งไคลเอ็นต์บน Android โดยใช้ไลบรารี Android ของบริการระบุตัวตนของ Google ที่แนะนำ

  List 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 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 ACCESS_TOKEN) หรือใช้เครื่องมือให้สิทธิ์ของตัวดึงข้อมูล (GTMFetcherAuthorizationProtocol) กับ ไลบรารีของไคลเอ็นต์ Google APIs สำหรับ Objective-C สำหรับ REST

ดู คู่มือการเข้าถึงฝั่งไคลเอ็นต์เกี่ยวกับวิธีเข้าถึง Google API ในฝั่งไคลเอ็นต์ เกี่ยวกับวิธีเข้าถึง Google APIs ในฝั่งไคลเอ็นต์

การเข้าถึงฝั่งเซิร์ฟเวอร์ (ออฟไลน์)
ตัวอย่างด้านล่างแสดงวิธีเข้าถึง Google API ในฝั่งเซิร์ฟเวอร์เพื่อรองรับไคลเอ็นต์ 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 API จากฝั่งเซิร์ฟเวอร์

ไคลเอ็นต์แอป Chrome

หากพิจารณาแล้วว่าแอปของคุณใช้โฟลว์ที่อยู่ IP ของ Loopback ในไคลเอ็นต์แอป Chrome คุณควรเปลี่ยนไปใช้ Chrome Identity API

ตัวอย่างด้านล่างแสดงวิธีรับรายชื่อติดต่อของผู้ใช้ทั้งหมดโดยไม่ต้องใช้ URI การเปลี่ยนเส้นทางที่อยู่ IP แบบวนรอบ

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)
    });
   });
 });
};

โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีเข้าถึงผู้ใช้ที่ตรวจสอบสิทธิ์และเรียกปลายทางของ Google ด้วย Chrome Identity API ใน คู่มือ Chrome Identity API