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 Anda. Server Anda menukar kode sekali pakai ini untuk memperoleh akses-nya sendiri dan token refresh 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 dengan alur sisi server murni dan lebih dari mengirim token akses ke server Anda.

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

Kode sekali pakai memiliki beberapa keunggulan keamanan. Dengan kode, Google menyediakan token langsung ke server Anda tanpa perantara. Meskipun kami tidak menyarankan untuk membocorkan kode, kode ini akan 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 ditukarkan oleh server Anda dengan server Google untuk mendapatkan token akses.

Kode contoh berikut menunjukkan cara melakukan alur kode sekali pakai.

Mengautentikasi Login dengan Google dengan alur kode satu kali mengharuskan Anda untuk:

Langkah 1: Membuat client ID dan rahasia klien

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

  1. Buka Konsol Google API.

  2. Dari drop-down project, pilih project yang sudah ada, atau buat yang baru dengan memilih Buat project baru.

  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 Application type, pilih Web application.

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

    1. Di kolom Asal JavaScript yang sah, masukkan origin aplikasi Anda. Anda dapat memasukkan beberapa origin agar aplikasi 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 Klien OAuth 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 mendemonstrasikan 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: Melakukan inisialisasi objek GoogleAuth

Muat library auth2 dan panggil gapi.auth2.init() untuk melakukan inisialisasi objek GoogleAuth. Tentukan client ID dan cakupan yang ingin diminta 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: 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() diberi objek JSON beserta kode otorisasi. Contoh:

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

Langkah 6: Kirim kode otorisasi ke server

code adalah kode sekali pakai Anda yang dapat ditukarkan oleh server Anda untuk token akses dan token refresh-nya sendiri. Anda hanya bisa memperoleh token refresh setelah pengguna melihat dialog otorisasi yang meminta akses offline. Jika telah menentukan select-account prompt dalam OfflineAccessOptions di 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 terhadap 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 berhasil login, 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, jika perlu, 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 tersebut.

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']