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 mengizinkan aplikasi Anda di sisi klien menggunakan klien JavaScript API dan Anda mengirimkan kode otorisasi satu kali khusus ke server. Server Anda menukar kode sekali pakai ini untuk memperoleh akses dan token refresh-nya sendiri dari Google agar server dapat melakukan panggilan API-nya sendiri, yang dapat dilakukan saat pengguna sedang offline. Alur kode sekali pakai ini memiliki keunggulan keamanan dibandingkan alur murni sisi server dan lebih dari sekadar mengirim token akses ke server Anda.

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

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

Mengimplementasikan alur kode sekali pakai

Tombol Login dengan Google menyediakan token akses dan kode otorisasi. Kode ini adalah kode sekali pakai yang dapat dipertukarkan oleh server Anda dengan token akses ke server Google.

Kode contoh berikut menunjukkan cara menjalankan 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 rahasia klien, buat project Konsol API Google, siapkan client ID OAuth, dan daftarkan asal JavaScript Anda:

  1. Buka Konsol Google API.

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

  3. Di sidebar di 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 Jenis aplikasi, pilih Aplikasi web.

    Daftarkan origin tempat aplikasi Anda diizinkan untuk mengakses Google API, sebagai berikut. Asal adalah kombinasi unik dari protokol, nama {i>host<i}, dan porta.

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

      http://localhost:8080
      https://myproductionurl.example.com
      
    2. Kolom Authorized redirect URI tidak memerlukan nilai. URI Pengalihan tidak digunakan dengan JavaScript API.

    3. Tekan tombol Buat.

  6. Dari kotak dialog OAuth client yang dihasilkan, salin Client ID. Client ID 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 menginisialisasi objek GoogleAuth. Tentukan client ID dan cakupan yang ingin diminta saat Anda 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: Buat pengguna login

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

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

Langkah 6: Kirim kode otorisasi ke server

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

Token akses selalu ditampilkan dengan pertukaran kode otorisasi yang valid.

Skrip berikut menentukan fungsi callback untuk tombol login. Jika proses login berhasil, fungsi tersebut 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 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 Anda 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']