Login dengan Google untuk aplikasi sisi server

Untuk menggunakan layanan Google atas nama pengguna saat pengguna sedang offline, Anda harus menggunakan alur sisi server campuran tempat pengguna memberikan otorisasi ke aplikasi Anda di sisi klien menggunakan klien JavaScript API dan Anda mengirim kode otorisasi satu kali khusus ke server Anda. Server Anda menukarkan kode sekali pakai ini untuk mendapatkan token akses dan token refresh-nya sendiri dari Google agar server dapat melakukan panggilan API-nya sendiri, yang dapat dilakukan saat pengguna offline. Alur kode sekali pakai ini memiliki keunggulan keamanan dibandingkan alur sisi server murni dan pengiriman token akses ke server Anda.

Alur login untuk mendapatkan token akses bagi aplikasi sisi server Anda diilustrasikan di bawah.

Kode sekali pakai memiliki beberapa keunggulan keamanan. Dengan kode, Google menyediakan token langsung ke server Anda tanpa perantara. Meskipun kami tidak merekomendasikan kebocoran kode, kode tersebut sangat sulit digunakan tanpa secret klien Anda. Jaga rahasia klien Anda.

Mengimplementasikan alur kode sekali pakai

Tombol Login dengan Google memberikan token akses dan kode otorisasi. Kode ini adalah kode satu kali yang dapat ditukarkan server Anda dengan server Google untuk mendapatkan token akses.

Contoh kode berikut menunjukkan cara melakukan alur kode sekali pakai.

Untuk mengautentikasi Login dengan Google dengan alur kode sekali pakai, Anda harus:

Langkah 1: Buat client ID dan rahasia klien

Untuk membuat client ID dan secret klien, buat project Konsol API Google, konfigurasi client ID OAuth, dan daftarkan origin JavaScript Anda:

  1. Buka Konsol Google API.

  2. Dari menu drop-down project, pilih project yang sudah ada, atau buat project baru dengan memilih Create a new project.

  3. Di sidebar pada bagian "APIs & Services", pilih Credentials, lalu klik Configure consent screen.

    Pilih Alamat Email, tentukan Nama Produk, lalu tekan Simpan.

  4. Di tab Credentials, pilih menu drop-down Create credentials, lalu pilih OAuth client ID.

  5. Di bagian Application type, pilih Web application.

    Daftarkan origin tempat aplikasi Anda diizinkan untuk mengakses Google API, sebagai berikut. Origin adalah kombinasi unik dari protokol, nama host, dan port.

    1. Di kolom Authorized JavaScript origins, masukkan origin untuk aplikasi Anda. Anda dapat memasukkan beberapa origin untuk mengizinkan aplikasi Anda berjalan di protokol, domain, atau subdomain yang berbeda. Anda tidak dapat menggunakan karakter pengganti. Dalam contoh di bawah, URL kedua dapat berupa URL produksi.

      http://localhost:8080
      https://myproductionurl.example.com
      
    2. Kolom URI pengalihan yang sah tidak memerlukan nilai. URI pengalihan tidak digunakan dengan JavaScript API.

    3. Tekan tombol Create.

  6. Dari kotak dialog Klien OAuth yang muncul, salin Client ID. ID Klien memungkinkan aplikasi Anda mengakses Google API yang diaktifkan.

Langkah 2: Sertakan library platform Google di halaman Anda

Sertakan skrip berikut yang menunjukkan fungsi anonim yang menyisipkan skrip ke dalam DOM halaman web index.html ini.

<!-- The top of file index.html -->
<html itemscope itemtype="http://schema.org/Article">
<head>
  <!-- BEGIN Pre-requisites -->
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js">
  </script>
  <script src="https://apis.google.com/js/client:platform.js?onload=start" async defer>
  </script>
  <!-- END Pre-requisites -->

Langkah 3: Lakukan inisialisasi objek GoogleAuth

Muat library auth2 dan panggil gapi.auth2.init() untuk melakukan inisialisasi objek GoogleAuth. Tentukan client ID dan cakupan yang ingin Anda minta saat memanggil init().

<!-- Continuing the <head> section -->
  <script>
    function start() {
      gapi.load('auth2', function() {
        auth2 = gapi.auth2.init({
          client_id: 'YOUR_CLIENT_ID.apps.googleusercontent.com',
          // Scopes to request in addition to 'profile' and 'email'
          //scope: 'additional_scope'
        });
      });
    }
  </script>
</head>
<body>
  <!-- ... -->
</body>
</html>

Langkah 4: Tambahkan tombol login ke halaman Anda

Tambahkan tombol login ke halaman web Anda, dan lampirkan pengendali klik untuk memanggil grantOfflineAccess() untuk memulai alur kode sekali pakai.

<!-- Add where you want your sign-in button to render -->
<!-- Use an image that follows the branding guidelines in a real app -->
<button id="signinButton">Sign in with Google</button>
<script>
  $('#signinButton').click(function() {
    // signInCallback defined in step 6.
    auth2.grantOfflineAccess().then(signInCallback);
  });
</script>

Langkah 5: Memproses login pengguna

Pengguna mengklik tombol login dan memberikan akses ke izin yang Anda minta ke aplikasi Anda. Kemudian, fungsi callback yang Anda tentukan dalam metode grantOfflineAccess().then() akan menerima objek JSON dengan kode otorisasi. Contoh:

{"code":"4/yU4cQZTMnnMtetyFcIWNItG32eKxxxgXXX-Z4yyJJJo.4qHskT-UtugceFc0ZRONyF4z7U4UmAI"}

Langkah 6: Kirim kode otorisasi ke server

code adalah kode satu kali yang dapat ditukarkan server Anda dengan token akses dan token refreshnya sendiri. Anda hanya dapat memperoleh token refresh setelah pengguna melihat dialog otorisasi yang meminta akses offline. Jika telah menentukan select-account prompt di OfflineAccessOptions pada langkah 4, Anda harus menyimpan token refresh yang diambil untuk digunakan nanti karena pertukaran berikutnya akan menampilkan null untuk token refresh. Alur ini memberikan peningkatan keamanan atas alur OAuth 2.0 standar Anda.

Token akses selalu ditampilkan dengan pertukaran kode otorisasi yang valid.

Skrip berikut menentukan fungsi callback untuk tombol login. Saat login berhasil, fungsi akan menyimpan token akses untuk penggunaan sisi klien dan mengirimkan kode sekali pakai ke server Anda di domain yang sama.

<!-- Last part of BODY element in file index.html -->
<script>
function signInCallback(authResult) {
  if (authResult['code']) {

    // Hide the sign-in button now that the user is authorized, for example:
    $('#signinButton').attr('style', 'display: none');

    // Send the code to the server
    $.ajax({
      type: 'POST',
      url: 'http://example.com/storeauthcode',
      // Always include an `X-Requested-With` header in every AJAX request,
      // to protect against CSRF attacks.
      headers: {
        'X-Requested-With': 'XMLHttpRequest'
      },
      contentType: 'application/octet-stream; charset=utf-8',
      success: function(result) {
        // Handle or verify the server response.
      },
      processData: false,
      data: authResult['code']
    });
  } else {
    // There was an error.
  }
}
</script>

Langkah 7: Tukarkan kode otorisasi dengan token akses

Di server, tukar kode autentikasi dengan token akses dan token refresh. Gunakan token akses untuk memanggil Google API atas nama pengguna dan, secara opsional, simpan token refresh untuk memperoleh token akses baru saat masa berlaku token akses berakhir.

Jika meminta akses profil, Anda juga akan mendapatkan token ID yang berisi informasi profil dasar untuk pengguna.

Contoh:

Java
// (Receive authCode via HTTPS POST)


if (request.getHeader("X-Requested-With") == null) {
  // Without the `X-Requested-With` header, this request could be forged. Aborts.
}

// Set path to the Web application client_secret_*.json file you downloaded from the
// Google API Console: https://console.cloud.google.com/apis/credentials
// You can also find your Web application client ID and client secret from the
// console and specify them directly when you create the GoogleAuthorizationCodeTokenRequest
// object.
String CLIENT_SECRET_FILE = "/path/to/client_secret.json";

// Exchange auth code for access token
GoogleClientSecrets clientSecrets =
    GoogleClientSecrets.load(
        JacksonFactory.getDefaultInstance(), new FileReader(CLIENT_SECRET_FILE));
GoogleTokenResponse tokenResponse =
          new GoogleAuthorizationCodeTokenRequest(
              new NetHttpTransport(),
              JacksonFactory.getDefaultInstance(),
              "https://oauth2.googleapis.com/token",
              clientSecrets.getDetails().getClientId(),
              clientSecrets.getDetails().getClientSecret(),
              authCode,
              REDIRECT_URI)  // Specify the same redirect URI that you use with your web
                             // app. If you don't have a web version of your app, you can
                             // specify an empty string.
              .execute();

String accessToken = tokenResponse.getAccessToken();

// Use access token to call API
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
Drive drive =
    new Drive.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), credential)
        .setApplicationName("Auth Code Exchange Demo")
        .build();
File file = drive.files().get("appfolder").execute();

// Get profile info from ID token
GoogleIdToken idToken = tokenResponse.parseIdToken();
GoogleIdToken.Payload payload = idToken.getPayload();
String userId = payload.getSubject();  // Use this value as a key to identify a user.
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");
Python
from apiclient import discovery
import httplib2
from oauth2client import client

# (Receive auth_code by HTTPS POST)


# If this request does not have `X-Requested-With` header, this could be a CSRF
if not request.headers.get('X-Requested-With'):
    abort(403)

# Set path to the Web application client_secret_*.json file you downloaded from the
# Google API Console: https://console.cloud.google.com/apis/credentials
CLIENT_SECRET_FILE = '/path/to/client_secret.json'

# Exchange auth code for access token, refresh token, and ID token
credentials = client.credentials_from_clientsecrets_and_code(
    CLIENT_SECRET_FILE,
    ['https://www.googleapis.com/auth/drive.appdata', 'profile', 'email'],
    auth_code)

# Call Google API
http_auth = credentials.authorize(httplib2.Http())
drive_service = discovery.build('drive', 'v3', http=http_auth)
appfolder = drive_service.files().get(fileId='appfolder').execute()

# Get profile info from ID token
userid = credentials.id_token['sub']
email = credentials.id_token['email']