ยืนยันโทเค็นรหัส Google ในฝั่งเซิร์ฟเวอร์ของคุณ

หลังจากที่ Google ส่งคืนโทเค็นรหัสแล้ว โทเค็นนี้จะส่งโดยคำขอเมธอด HTTP POST ที่มีชื่อพารามิเตอร์ credential ไปยังปลายทางการเข้าสู่ระบบ

ตัวอย่างในภาษา Python ที่แสดงขั้นตอนทั่วไปในการตรวจสอบและใช้โทเค็นรหัส มีดังนี้

  1. ยืนยันโทเค็น Cross-Site Request Forgery (CSRF) เมื่อคุณส่งข้อมูลเข้าสู่ระบบไปยังปลายทางการเข้าสู่ระบบ เราจะใช้รูปแบบการส่งคุกกี้ซ้ำเพื่อป้องกันการโจมตี CSRF ก่อนที่จะส่งแต่ละครั้ง เราจะสร้างโทเค็น จากนั้น ระบบจะใส่โทเค็นลงในทั้งคุกกี้และส่วนเนื้อความของโพสต์ ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้

    csrf_token_cookie = self.request.cookies.get('g_csrf_token')
    if not csrf_token_cookie:
        webapp2.abort(400, 'No CSRF token in Cookie.')
    csrf_token_body = self.request.get('g_csrf_token')
    if not csrf_token_body:
        webapp2.abort(400, 'No CSRF token in post body.')
    if csrf_token_cookie != csrf_token_body:
        webapp2.abort(400, 'Failed to verify double submit cookie.')
    
  2. ยืนยันโทเค็นรหัส

    To verify that the token is valid, ensure that the following criteria are satisfied:

    • The ID token is properly signed by Google. Use Google's public keys (available in JWK or PEM format) to verify the token's signature. These keys are regularly rotated; examine the Cache-Control header in the response to determine when you should retrieve them again.
    • The value of aud in the ID token is equal to one of your app's client IDs. This check is necessary to prevent ID tokens issued to a malicious app being used to access data about the same user on your app's backend server.
    • The value of iss in the ID token is equal to accounts.google.com or https://accounts.google.com.
    • The expiry time (exp) of the ID token has not passed.
    • If you want to restrict access to only members of your G Suite domain, verify that the ID token has an hd claim that matches your G Suite domain name.

    Rather than writing your own code to perform these verification steps, we strongly recommend using a Google API client library for your platform, or a general-purpose JWT library. For development and debugging, you can call our tokeninfo validation endpoint.

    การใช้ไลบรารีของไคลเอ็นต์ Google API

    การใช้ไลบรารีของไคลเอ็นต์ Google API แบบใดแบบหนึ่ง (เช่น Java, Node.js, PHP, Python) เป็นวิธีที่แนะนำในการตรวจสอบโทเค็นรหัส Google ในสภาพแวดล้อมการใช้งานจริง

    Java

    หากต้องการตรวจสอบโทเค็นรหัสใน Java ให้ใช้ออบเจ็กต์ GoogleIdTokenVerifier เช่น

    import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
    import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload;
    import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
    
    ...
    
    GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
        // Specify the CLIENT_ID of the app that accesses the backend:
        .setAudience(Collections.singletonList(CLIENT_ID))
        // Or, if multiple clients access the backend:
        //.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3))
        .build();
    
    // (Receive idTokenString by HTTPS POST)
    
    GoogleIdToken idToken = verifier.verify(idTokenString);
    if (idToken != null) {
      Payload payload = idToken.getPayload();
    
      // Print user identifier
      String userId = payload.getSubject();
      System.out.println("User ID: " + userId);
    
      // Get profile information from payload
      String email = payload.getEmail();
      boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
      String name = (String) payload.get("name");
      String pictureUrl = (String) payload.get("picture");
      String locale = (String) payload.get("locale");
      String familyName = (String) payload.get("family_name");
      String givenName = (String) payload.get("given_name");
    
      // Use or store profile information
      // ...
    
    } else {
      System.out.println("Invalid ID token.");
    }

    เมธอด GoogleIdTokenVerifier.verify() ยืนยันลายเซ็น JWT, การอ้างสิทธิ์ aud, การอ้างสิทธิ์ iss และการอ้างสิทธิ์ exp

    หากคุณต้องการจำกัดการเข้าถึงให้เฉพาะสมาชิกในโดเมน G Suite เท่านั้น โปรดยืนยันการอ้างสิทธิ์ hd ด้วยโดยตรวจสอบชื่อโดเมนที่แสดงผลโดยเมธอด Payload.getHostedDomain()

    Node.js

    หากต้องการตรวจสอบโทเค็นรหัสใน Node.js ให้ใช้ไลบรารี Google Auth สำหรับ Node.js ติดตั้งไลบรารี:

    npm install google-auth-library --save
    จากนั้นเรียกใช้ฟังก์ชัน verifyIdToken() เช่น

    const {OAuth2Client} = require('google-auth-library');
    const client = new OAuth2Client();
    async function verify() {
      const ticket = await client.verifyIdToken({
          idToken: token,
          audience: CLIENT_ID,  // Specify the CLIENT_ID of the app that accesses the backend
          // Or, if multiple clients access the backend:
          //[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]
      });
      const payload = ticket.getPayload();
      const userid = payload['sub'];
      // If request specified a G Suite domain:
      // const domain = payload['hd'];
    }
    verify().catch(console.error);
    

    ฟังก์ชัน verifyIdToken ยืนยันลายเซ็น JWT, การอ้างสิทธิ์ aud, การอ้างสิทธิ์ exp และการอ้างสิทธิ์ iss

    หากคุณต้องการจำกัดการเข้าถึงให้เฉพาะสมาชิกของโดเมน G Suite เท่านั้น โปรดยืนยันว่าการอ้างสิทธิ์ hd ตรงกับชื่อโดเมน G Suite ของคุณ

    PHP

    หากต้องการตรวจสอบโทเค็นรหัสใน PHP ให้ใช้ไลบรารีของไคลเอ็นต์ Google API สำหรับ PHP ติดตั้งไลบรารี (เช่น การใช้คอมโพสเซอร์) ดังนี้

    composer require google/apiclient
    จากนั้นเรียกฟังก์ชัน verifyIdToken() เช่น

    require_once 'vendor/autoload.php';
    
    // Get $id_token via HTTPS POST.
    
    $client = new Google_Client(['client_id' => $CLIENT_ID]);  // Specify the CLIENT_ID of the app that accesses the backend
    $payload = $client->verifyIdToken($id_token);
    if ($payload) {
      $userid = $payload['sub'];
      // If request specified a G Suite domain:
      //$domain = $payload['hd'];
    } else {
      // Invalid ID token
    }
    

    ฟังก์ชัน verifyIdToken ยืนยันลายเซ็น JWT, การอ้างสิทธิ์ aud, การอ้างสิทธิ์ exp และการอ้างสิทธิ์ iss

    หากคุณต้องการจำกัดการเข้าถึงให้เฉพาะสมาชิกของโดเมน G Suite เท่านั้น โปรดยืนยันว่าการอ้างสิทธิ์ hd ตรงกับชื่อโดเมน G Suite ของคุณ

    Python

    หากต้องการตรวจสอบโทเค็นรหัสใน Python ให้ใช้ฟังก์ชัน verify_oauth2_token เช่น

    from google.oauth2 import id_token
    from google.auth.transport import requests
    
    # (Receive token by HTTPS POST)
    # ...
    
    try:
        # Specify the CLIENT_ID of the app that accesses the backend:
        idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID)
    
        # Or, if multiple clients access the backend server:
        # idinfo = id_token.verify_oauth2_token(token, requests.Request())
        # if idinfo['aud'] not in [CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]:
        #     raise ValueError('Could not verify audience.')
    
        # If auth request is from a G Suite domain:
        # if idinfo['hd'] != GSUITE_DOMAIN_NAME:
        #     raise ValueError('Wrong hosted domain.')
    
        # ID token is valid. Get the user's Google Account ID from the decoded token.
        userid = idinfo['sub']
    except ValueError:
        # Invalid token
        pass
    

    ฟังก์ชัน verify_oauth2_token ยืนยันลายเซ็น JWT, การอ้างสิทธิ์ aud และการอ้างสิทธิ์ exp คุณต้องยืนยันการอ้างสิทธิ์ hd (หากมี) โดยการตรวจสอบออบเจ็กต์ที่ verify_oauth2_token ส่งคืนด้วย หากมีไคลเอ็นต์หลายคนเข้าถึงเซิร์ฟเวอร์แบ็กเอนด์ ให้ตรวจสอบการอ้างสิทธิ์ aud ด้วยตนเองด้วย

  3. เมื่อยืนยันความถูกต้องของโทเค็นแล้ว คุณจะใช้ข้อมูลในโทเค็นรหัส Google เพื่อเชื่อมโยงสถานะบัญชีของเว็บไซต์ได้ ดังนี้

    • ผู้ใช้ที่ไม่ได้ลงทะเบียน: คุณจะแสดงอินเทอร์เฟซผู้ใช้ (UI) สำหรับการลงชื่อสมัครใช้ที่อนุญาตให้ผู้ใช้ให้ข้อมูลโปรไฟล์เพิ่มเติมได้ หากจำเป็น นอกจากนี้ยังอนุญาตให้ผู้ใช้สร้างบัญชีใหม่และ เซสชันผู้ใช้ที่เข้าสู่ระบบโดยไม่ต้องแจ้งให้ทราบ

    • บัญชีที่มีอยู่แล้วในเว็บไซต์ของคุณ: คุณแสดงหน้าเว็บที่ให้ผู้ใช้ปลายทางป้อนรหัสผ่านและลิงก์บัญชีเดิมด้วยข้อมูลเข้าสู่ระบบของ Google ได้ เพื่อเป็นการยืนยันว่า ผู้ใช้มีสิทธิ์เข้าถึงบัญชีที่มีอยู่

    • ผู้ใช้ที่กลับมาแบบรวมศูนย์ที่กลับมา: คุณสามารถให้ผู้ใช้ลงชื่อเข้าใช้แบบเงียบ