Ringkasan
Untuk mendapatkan token akses per pengguna guna memanggil Google API, Google menawarkan beberapa library JavaScript:
Panduan ini memberikan petunjuk untuk bermigrasi dari library ini ke library Google Identity Services.
Dengan mengikuti panduan ini, Anda akan:
- mengganti Platform Library yang tidak digunakan lagi dengan library Identity Services,
- Jika menggunakan Library Klien API, hapus modul
gapi.auth2
yang tidak digunakan lagi, metode dan objeknya, lalu ganti dengan yang setara dari Layanan Identitas.
Untuk mengetahui deskripsi tentang perubahan pada pustaka JavaScript Layanan Identitas, baca ringkasan dan cara kerja otorisasi pengguna untuk meninjau istilah dan konsep utama.
Jika Anda mencari autentikasi untuk pendaftaran dan login pengguna, lihat Bermigrasi dari Login dengan Google.
Mengidentifikasi alur otorisasi Anda
Ada dua kemungkinan alur otorisasi pengguna: implisit dan kode otorisasi.
Tinjau aplikasi web Anda untuk mengidentifikasi jenis alur otorisasi yang digunakan.
Indikasi bahwa aplikasi web Anda menggunakan alur implisit:
- Aplikasi web Anda sepenuhnya berbasis browser, tanpa platform backend.
- Pengguna harus hadir untuk memanggil Google API, aplikasi Anda hanya menggunakan token akses, dan tidak memerlukan token refresh.
- Aplikasi web Anda dimuat
apis.google.com/js/api.js
. - Implementasi Anda didasarkan pada OAuth 2.0 untuk Aplikasi Web Sisi Klien.
- Aplikasi Anda menggunakan modul
gapi.client
ataugapi.auth2
yang ada di Library Klien Google API untuk JavaScript.
Indikasi bahwa aplikasi web Anda menggunakan alur kode otorisasi:
Penerapan Anda didasarkan pada:
Aplikasi Anda berjalan di browser pengguna dan di platform backend Anda.
Platform backend Anda menghosting endpoint kode otorisasi.
Platform backend Anda memanggil Google API atas nama pengguna tanpa mengharuskan mereka hadir, yang juga dikenal sebagai mode offline.
Token refresh dikelola dan disimpan oleh platform backend Anda.
Dalam beberapa kasus, codebase Anda mungkin mendukung kedua alur tersebut.
Memilih alur otorisasi
Sebelum memulai migrasi, Anda perlu menentukan apakah melanjutkan alur yang ada atau mengadopsi alur yang berbeda paling sesuai dengan kebutuhan Anda.
Tinjau memilih alur otorisasi untuk memahami perbedaan dan kelebihan/kekurangan utama antara kedua alur tersebut.
Pada umumnya, alur kode otorisasi direkomendasikan karena menawarkan tingkat keamanan pengguna tertinggi. Dengan menerapkan alur ini, platform Anda juga dapat menambahkan fungsi offline baru seperti mengambil pembaruan untuk memberi tahu pengguna tentang perubahan penting pada kalender, foto, dan langganan mereka.
Pilih alur otorisasi menggunakan pemilih.
Alur implisit
Mendapatkan token akses untuk penggunaan dalam browser saat pengguna hadir.
Contoh alur implisit menampilkan aplikasi web sebelum dan setelah migrasi ke Layanan Identitas.
Alur kode otorisasi
Kode otorisasi per pengguna yang dikeluarkan oleh Google dikirimkan ke platform backend Anda, yang kemudian ditukarkan dengan token akses dan token refresh.
Contoh alur kode otorisasi menampilkan aplikasi web sebelum dan sesudah migrasi ke Layanan Identitas.
Di sepanjang panduan ini, ikuti petunjuk yang tercantum dalam huruf tebal untuk Menambahkan, Menghapus, Memperbarui, atau Mengganti fungsi yang ada.
Perubahan pada aplikasi web dalam browser Anda
Bagian ini meninjau perubahan yang akan Anda lakukan pada aplikasi web dalam browser saat bermigrasi ke library JavaScript Google Identity Services.
Mengidentifikasi kode yang terpengaruh dan mengujinya
Cookie debug dapat membantu menemukan kode yang terpengaruh dan menguji perilaku setelah penghentian penggunaan.
Dalam aplikasi besar atau kompleks, mungkin sulit untuk menemukan semua kode yang terpengaruh oleh penghentian penggunaan modul gapi.auth2
. Untuk mencatat penggunaan fungsi yang akan segera dihentikan ke konsol, tetapkan nilai cookie G_AUTH2_MIGRATION
ke informational
. Jika perlu, tambahkan titik dua yang diikuti dengan nilai kunci untuk juga mencatat ke penyimpanan sesi. Setelah login
dan menerima kredensial, tinjau atau kirim log yang dikumpulkan ke backend untuk dianalisis nanti. Misalnya, informational:showauth2use
menyimpan asal dan URL ke kunci penyimpanan sesi bernama showauth2use
.
Untuk memverifikasi perilaku aplikasi saat modul gapi.auth2
tidak lagi dimuat, tetapkan
nilai cookie G_AUTH2_MIGRATION
ke enforced
. Hal ini memungkinkan pengujian perilaku setelah penghentian penggunaan sebelum tanggal pemberlakuan.
Kemungkinan nilai cookie G_AUTH2_MIGRATION
:
enforced
Jangan muat modulgapi.auth2
.informational
Mencatat penggunaan fungsi yang tidak digunakan lagi ke konsol JS. Juga mencatat ke penyimpanan sesi saat nama kunci opsional ditetapkan:informational:key-name
.
Untuk meminimalkan dampak pengguna, sebaiknya tetapkan cookie ini secara lokal terlebih dahulu selama pengembangan dan pengujian, sebelum menggunakannya di lingkungan produksi.
Library dan modul
Modul gapi.auth2
mengelola autentikasi pengguna untuk login dan alur implisit untuk otorisasi, ganti modul yang tidak digunakan lagi ini, serta objek dan metodenya dengan library Google Identity Services.
Tambahkan library Identity Services ke aplikasi web Anda dengan menyertakannya dalam dokumen Anda:
<script src="https://accounts.google.com/gsi/client" async defer></script>
Hapus semua instance pemuatan modul auth2
menggunakan gapi.load('auth2',
function)
.
Library Layanan Identitas Google menggantikan penggunaan modul gapi.auth2
.
Anda dapat terus menggunakan modul gapi.client
dengan aman dari Library Klien Google API untuk JavaScript, dan memanfaatkan pembuatan otomatis metode JS yang dapat dipanggil dari dokumen penemuan, pengelompokan beberapa panggilan API, dan fungsi pengelolaan CORS.
Kukis
Otorisasi pengguna tidak memerlukan penggunaan cookie.
Lihat Bermigrasi dari Login dengan Google untuk mengetahui detail tentang cara autentikasi pengguna menggunakan cookie, dan Cara Google menggunakan cookie untuk penggunaan cookie oleh produk dan layanan Google lainnya.
Kredensial
Google Identity Services memisahkan autentikasi dan otorisasi pengguna menjadi dua operasi yang berbeda, dan kredensial pengguna terpisah: token ID yang digunakan untuk mengidentifikasi pengguna ditampilkan secara terpisah dari token akses yang digunakan untuk otorisasi.
Untuk melihat perubahan ini, lihat kredensial contoh.
Alur implisit
Memisahkan autentikasi dan otorisasi pengguna dengan menghapus penanganan profil pengguna dari alur otorisasi.
Hapus referensi klien JavaScript Login dengan Google berikut:
Metode
GoogleUser.getBasicProfile()
GoogleUser.getId()
Alur kode otorisasi
Layanan Identitas memisahkan kredensial dalam browser menjadi token ID dan token akses. Perubahan ini tidak berlaku untuk kredensial yang diperoleh melalui panggilan langsung ke endpoint Google OAuth 2.0 dari platform backend Anda atau melalui library yang berjalan di server yang aman di platform Anda seperti Google APIs Node.js Client.
Status sesi
Sebelumnya, Login dengan Google membantu Anda mengelola status login pengguna menggunakan:
- Handler callback untuk Memantau status sesi pengguna.
- Listener untuk peristiwa dan perubahan pada status login untuk Akun Google pengguna.
Anda bertanggung jawab untuk mengelola status login dan sesi pengguna ke aplikasi web Anda.
Hapus referensi klien JavaScript Login dengan Google berikut:
Objek:
gapi.auth2.SignInOptions
Metode:
GoogleAuth.attachClickHandler()
GoogleAuth.isSignedIn()
GoogleAuth.isSignedIn.get()
GoogleAuth.isSignedIn.listen()
GoogleAuth.signIn()
GoogleAuth.signOut()
GoogleAuth.currentUser.get()
GoogleAuth.currentUser.listen()
GoogleUser.isSignedIn()
Konfigurasi klien
Perbarui aplikasi web Anda untuk menginisialisasi klien token untuk alur kode otorisasi atau implisit.
Hapus referensi klien JavaScript Login dengan Google berikut:
Objek:
gapi.auth2.ClientConfig
gapi.auth2.OfflineAccessOptions
Metode:
gapi.auth2.getAuthInstance()
GoogleUser.grant()
Alur implisit
Tambahkan objek TokenClientConfig
dan panggilan initTokenClient()
untuk
mengonfigurasi aplikasi web Anda, dengan mengikuti contoh di menginisialisasi klien
token.
Ganti referensi klien JavaScript Login dengan Google dengan Google Identity Services:
Objek:
gapi.auth2.AuthorizeConfig
denganTokenClientConfig
Metode:
gapi.auth2.init()
dengangoogle.accounts.oauth2.initTokenClient()
Parameter:
gapi.auth2.AuthorizeConfig.login_hint
denganTokenClientConfig.login_hint
.gapi.auth2.GoogleUser.getHostedDomain()
denganTokenClientConfig.hd
.
Alur kode otorisasi
Tambahkan objek CodeClientConfig
dan panggilan initCodeClient()
untuk mengonfigurasi
aplikasi web Anda, dengan mengikuti contoh di menginisialisasi Klien Kode.
Saat beralih dari alur implisit ke alur kode otorisasi:
Hapus referensi klien JavaScript Login dengan Google
Objek:
gapi.auth2.AuthorizeConfig
Metode:
gapi.auth2.init()
Parameter:
gapi.auth2.AuthorizeConfig.login_hint
gapi.auth2.GoogleUser.getHostedDomain()
Permintaan token
Gestur pengguna, seperti klik tombol, menghasilkan permintaan yang menghasilkan token akses yang ditampilkan langsung ke browser pengguna dengan alur implisit, atau ke platform backend Anda setelah menukar kode otorisasi per pengguna dengan token akses dan token refresh.
Alur implisit
Token akses dapat diperoleh dan digunakan di browser saat pengguna login dan memiliki sesi aktif dengan Google. Untuk mode implisit, gestur pengguna diperlukan untuk meminta token akses, meskipun ada permintaan sebelumnya.
Ganti referensi klien JavaScript Login dengan Google: dengan Google Identity Services:
Metode:
gapi.auth2.authorize()
denganTokenClient.requestAccessToken()
GoogleUser.reloadAuthResponse()
denganTokenClient.requestAccessToken()
Tambahkan link atau tombol untuk memanggil requestAccessToken()
guna memulai alur UX pop-up untuk meminta token akses, atau untuk mendapatkan token baru saat token yang ada berakhir masa berlakunya.
Perbarui codebase Anda menjadi:
- Memicu alur token OAuth 2.0 dengan
requestAccessToken()
. - Mendukung otorisasi inkremental dengan menggunakan
requestAccessToken
danOverridableTokenClientConfig
untuk memisahkan satu permintaan untuk banyak cakupan menjadi beberapa permintaan yang lebih kecil. - Minta token baru saat masa berlaku token yang ada habis, atau token dicabut.
Bekerja dengan beberapa cakupan mungkin memerlukan perubahan struktural pada codebase Anda untuk meminta akses ke cakupan hanya saat diperlukan, bukan sekaligus. Hal ini dikenal sebagai otorisasi inkremental. Setiap permintaan harus berisi sesedikit mungkin cakupan, dan idealnya satu cakupan. Lihat cara menangani izin pengguna untuk mengetahui lebih lanjut cara mengupdate aplikasi Anda untuk otorisasi inkremental.
Saat masa berlaku token akses berakhir, modul gapi.auth2
akan otomatis mendapatkan token akses baru yang valid untuk aplikasi web Anda. Untuk meningkatkan keamanan pengguna, proses refresh token otomatis ini tidak didukung oleh library Layanan Identitas Google. Aplikasi web Anda harus diupdate untuk mendeteksi masa berlaku token akses yang telah habis dan meminta token baru. Lihat bagian Penanganan token untuk mengetahui informasi selengkapnya.
Alur kode otorisasi
Tambahkan link atau tombol untuk memanggil requestCode()
guna meminta kode otorisasi dari Google. Untuk melihat contoh, lihat Memicu Alur Kode OAuth 2.0.
Lihat bagian Penanganan token untuk mengetahui informasi selengkapnya tentang cara merespons token akses yang telah habis masa berlakunya atau dicabut.
Penanganan token
Tambahkan penanganan error untuk mendeteksi panggilan Google API yang gagal saat token akses yang sudah tidak berlaku atau dicabut digunakan, dan untuk meminta token akses baru yang valid.
Pesan error kode status HTTP 401 Unauthorized
dan invalid_token
ditampilkan oleh Google API saat token akses yang sudah habis masa berlakunya atau dicabut digunakan. Sebagai
contoh, lihat Respons token tidak valid.
Token yang habis masa berlakunya
Token akses berumur pendek, dan sering kali hanya berlaku selama beberapa menit.
Pencabutan token
Kapan saja, pemilik Akun Google dapat mencabut izin yang sebelumnya diberikan. Tindakan ini akan membatalkan validitas token akses dan token refresh yang ada. Pencabutan dapat dipicu dari platform Anda menggunakan revoke()
atau melalui Akun Google.
Ganti referensi klien JavaScript Login dengan Google: dengan Google Identity Services:
Metode:
getAuthInstance().disconnect()
dengangoogle.accounts.oauth2.revoke()
GoogleUser.disconnect()
dengangoogle.accounts.oauth2.revoke()
Panggil revoke
saat pengguna menghapus akunnya di platform Anda, atau ingin mencabut izin untuk membagikan data ke aplikasi Anda.
Dialog izin pengguna
Google menampilkan dialog izin kepada pengguna saat aplikasi web atau platform backend Anda meminta token akses. Lihat contoh dialog izin yang ditampilkan oleh Google kepada pengguna.
Sebelum mengeluarkan token akses ke aplikasi Anda, sesi Google yang ada dan aktif diperlukan untuk meminta izin pengguna dan mencatat hasilnya. Pengguna mungkin diminta untuk login ke Akun Google jika sesi yang ada belum dibuat.
Login pengguna
Pengguna mungkin login ke Akun Google di tab browser terpisah, atau secara native melalui browser atau sistem operasi. Sebaiknya tambahkan Login dengan Google ke situs Anda untuk membuat sesi aktif antara Akun Google dan browser saat pengguna pertama kali membuka aplikasi Anda. Tindakan ini memberikan manfaat berikut:
- Meminimalkan frekuensi pengguna harus login, permintaan token akses memulai proses login Akun Google jika sesi aktif belum ada.
- Gunakan langsung kolom credential JWT ID Token
email
sebagai nilai parameterlogin_hint
dalam objekCodeClientConfig
atauTokenClientConfig
. Hal ini sangat membantu jika platform Anda tidak memiliki sistem pengelolaan akun pengguna. - Cari dan kaitkan Akun Google dengan akun pengguna lokal yang ada di platform Anda, sehingga membantu meminimalkan akun duplikat di platform Anda.
- Saat akun lokal baru dibuat, dialog dan alur pendaftaran Anda dapat dipisahkan dengan jelas dari dialog dan alur autentikasi pengguna, sehingga mengurangi jumlah langkah yang diperlukan dan meningkatkan tingkat penghentian.
Setelah login, dan sebelum token akses dikeluarkan, pengguna harus memberikan izin untuk aplikasi Anda terkait cakupan yang diminta.
Respons token dan izin
Setelah izin diberikan, token akses akan ditampilkan bersama dengan daftar cakupan yang disetujui atau ditolak oleh pengguna.
Izin terperinci memungkinkan pengguna menyetujui atau menolak cakupan individual. Saat meminta akses ke beberapa cakupan, setiap cakupan diberikan atau ditolak secara terpisah dari cakupan lainnya. Berdasarkan pilihan pengguna, aplikasi Anda akan mengaktifkan fitur dan fungsi yang bergantung pada cakupan individual secara selektif.
Alur implisit
Ganti referensi klien JavaScript Login dengan Google dengan Google Identity Services:
Objek:
gapi.auth2.AuthorizeResponse
denganTokenClient.TokenResponse
gapi.auth2.AuthResponse
denganTokenClient.TokenResponse
Metode:
GoogleUser.hasGrantedScopes()
dengangoogle.accounts.oauth2.hasGrantedAllScopes()
GoogleUser.getGrantedScopes()
dengangoogle.accounts.oauth2.hasGrantedAllScopes()
Hapus referensi klien JavaScript Login dengan Google:
Metode:
GoogleUser.getAuthResponse()
Perbarui aplikasi web Anda dengan hasGrantedAllScopes()
dan
hasGrantedAnyScope()
dengan mengikuti contoh izin terperinci ini.
Alur kode otorisasi
Perbarui atau Tambahkan endpoint kode otorisasi ke platform backend Anda dengan mengikuti petunjuk di penanganan kode otorisasi.
Perbarui platform Anda untuk mengikuti langkah-langkah yang dijelaskan dalam panduan Menggunakan Model Kode untuk memvalidasi permintaan dan mendapatkan token akses serta token refresh.
Perbarui platform Anda untuk mengaktifkan atau menonaktifkan fitur dan fungsi secara selektif berdasarkan cakupan individual yang telah disetujui pengguna dengan mengikuti petunjuk untuk otorisasi inkremental dan memeriksa cakupan akses yang diberikan oleh pengguna.
Contoh alur implisit
Cara lama
Library Klien GAPI
Contoh Library Klien Google API untuk JavaScript yang berjalan di browser menggunakan dialog pop-up untuk izin pengguna.
Modul gapi.auth2
dimuat dan digunakan secara otomatis oleh
gapi.client.init()
, sehingga disembunyikan.
<!DOCTYPE html>
<html>
<head>
<script src="https://apis.google.com/js/api.js"></script>
<script>
function start() {
gapi.client.init({
'apiKey': 'YOUR_API_KEY',
'clientId': 'YOUR_CLIENT_ID',
'scope': 'https://www.googleapis.com/auth/cloud-translation',
'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
}).then(function() {
// Execute an API request which is returned as a Promise.
// The method name language.translations.list comes from the API discovery.
return gapi.client.language.translations.list({
q: 'hello world',
source: 'en',
target: 'de',
});
}).then(function(response) {
console.log(response.result.data.translations[0].translatedText);
}, function(reason) {
console.log('Error: ' + reason.result.error.message);
});
};
// Load the JavaScript client library and invoke start afterwards.
gapi.load('client', start);
</script>
</head>
<body>
<div id="results"></div>
</body>
</html>
Library Klien JS
OAuth 2.0 untuk Aplikasi Web Sisi Klien yang berjalan di browser menggunakan dialog pop-up untuk izin pengguna.
Modul gapi.auth2
dimuat secara manual.
<!DOCTYPE html>
<html><head></head><body>
<script>
var GoogleAuth;
var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
function handleClientLoad() {
// Load the API's client and auth2 modules.
// Call the initClient function after the modules load.
gapi.load('client:auth2', initClient);
}
function initClient() {
// In practice, your app can retrieve one or more discovery documents.
var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';
// Initialize the gapi.client object, which app uses to make API requests.
// Get API key and client ID from Google Cloud console.
// 'scope' field specifies space-delimited list of access scopes.
gapi.client.init({
'apiKey': 'YOUR_API_KEY',
'clientId': 'YOUR_CLIENT_ID',
'discoveryDocs': [discoveryUrl],
'scope': SCOPE
}).then(function () {
GoogleAuth = gapi.auth2.getAuthInstance();
// Listen for sign-in state changes.
GoogleAuth.isSignedIn.listen(updateSigninStatus);
// Handle initial sign-in state. (Determine if user is already signed in.)
var user = GoogleAuth.currentUser.get();
setSigninStatus();
// Call handleAuthClick function when user clicks on
// "Sign In/Authorize" button.
$('#sign-in-or-out-button').click(function() {
handleAuthClick();
});
$('#revoke-access-button').click(function() {
revokeAccess();
});
});
}
function handleAuthClick() {
if (GoogleAuth.isSignedIn.get()) {
// User is authorized and has clicked "Sign out" button.
GoogleAuth.signOut();
} else {
// User is not signed in. Start Google auth flow.
GoogleAuth.signIn();
}
}
function revokeAccess() {
GoogleAuth.disconnect();
}
function setSigninStatus() {
var user = GoogleAuth.currentUser.get();
var isAuthorized = user.hasGrantedScopes(SCOPE);
if (isAuthorized) {
$('#sign-in-or-out-button').html('Sign out');
$('#revoke-access-button').css('display', 'inline-block');
$('#auth-status').html('You are currently signed in and have granted ' +
'access to this app.');
} else {
$('#sign-in-or-out-button').html('Sign In/Authorize');
$('#revoke-access-button').css('display', 'none');
$('#auth-status').html('You have not authorized this app or you are ' +
'signed out.');
}
}
function updateSigninStatus() {
setSigninStatus();
}
</script>
<button id="sign-in-or-out-button"
style="margin-left: 25px">Sign In/Authorize</button>
<button id="revoke-access-button"
style="display: none; margin-left: 25px">Revoke access</button>
<div id="auth-status" style="display: inline; padding-left: 25px"></div><hr>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body></html>
Endpoint OAuth 2.0
OAuth 2.0 untuk Aplikasi Web Sisi Klien yang berjalan di browser menggunakan pengalihan ke Google untuk izin pengguna.
Contoh ini menunjukkan panggilan langsung ke endpoint OAuth 2.0 Google dari
browser pengguna dan tidak menggunakan modul gapi.auth2
atau library
JavaScript.
<!DOCTYPE html>
<html><head></head><body>
<script>
var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';
var fragmentString = location.hash.substring(1);
// Parse query string to see if page request is coming from OAuth 2.0 server.
var params = {};
var regex = /([^&=]+)=([^&]*)/g, m;
while (m = regex.exec(fragmentString)) {
params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
}
if (Object.keys(params).length > 0) {
localStorage.setItem('oauth2-test-params', JSON.stringify(params) );
if (params['state'] && params['state'] == 'try_sample_request') {
trySampleRequest();
}
}
// If there's an access token, try an API request.
// Otherwise, start OAuth 2.0 flow.
function trySampleRequest() {
var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
if (params && params['access_token']) {
var xhr = new XMLHttpRequest();
xhr.open('GET',
'https://www.googleapis.com/drive/v3/about?fields=user&' +
'access_token=' + params['access_token']);
xhr.onreadystatechange = function (e) {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.response);
} else if (xhr.readyState === 4 && xhr.status === 401) {
// Token invalid, so prompt for user permission.
oauth2SignIn();
}
};
xhr.send(null);
} else {
oauth2SignIn();
}
}
/*
* Create form to request access token from Google's OAuth 2.0 server.
*/
function oauth2SignIn() {
// Google's OAuth 2.0 endpoint for requesting an access token
var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';
// Create element to open OAuth 2.0 endpoint in new window.
var form = document.createElement('form');
form.setAttribute('method', 'GET'); // Send as a GET request.
form.setAttribute('action', oauth2Endpoint);
// Parameters to pass to OAuth 2.0 endpoint.
var params = {'client_id': YOUR_CLIENT_ID,
'redirect_uri': YOUR_REDIRECT_URI,
'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
'state': 'try_sample_request',
'include_granted_scopes': 'true',
'response_type': 'token'};
// Add form parameters as hidden input values.
for (var p in params) {
var input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', p);
input.setAttribute('value', params[p]);
form.appendChild(input);
}
// Add form to page and submit it to open the OAuth 2.0 endpoint.
document.body.appendChild(form);
form.submit();
}
</script>
<button onclick="trySampleRequest();">Try sample request</button>
</body></html>
Cara baru
Khusus GIS
Contoh ini hanya menampilkan library JavaScript Google Identity Service menggunakan model token dan dialog pop-up untuk izin pengguna. Contoh ini diberikan untuk mengilustrasikan jumlah langkah minimum yang diperlukan untuk mengonfigurasi klien, meminta dan mendapatkan token akses, serta memanggil Google API.
<!DOCTYPE html>
<html>
<head>
<script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
</head>
<body>
<script>
var client;
var access_token;
function initClient() {
client = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly \
https://www.googleapis.com/auth/contacts.readonly',
callback: (tokenResponse) => {
access_token = tokenResponse.access_token;
},
});
}
function getToken() {
client.requestAccessToken();
}
function revokeToken() {
google.accounts.oauth2.revoke(access_token, () => {console.log('access token revoked')});
}
function loadCalendar() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
xhr.send();
}
</script>
<h1>Google Identity Services Authorization Token model</h1>
<button onclick="getToken();">Get access token</button><br><br>
<button onclick="loadCalendar();">Load Calendar</button><br><br>
<button onclick="revokeToken();">Revoke token</button>
</body>
</html>
GAPI async/await
Contoh ini menunjukkan cara menambahkan library Google Identity Service menggunakan
model token, menghapus modul gapi.auth2
, dan memanggil API menggunakan
Library Klien Google API untuk JavaScript.
Promise, async, dan await digunakan untuk menerapkan urutan pemuatan library serta untuk mendeteksi dan mencoba lagi error otorisasi. Panggilan API dilakukan hanya setelah token akses yang valid tersedia.
Pengguna diharapkan menekan tombol 'Tampilkan Kalender' saat token akses tidak ada saat halaman dimuat pertama kali, atau nanti setelah token akses kedaluwarsa.
<!DOCTYPE html>
<html>
<head>
<title>GAPI and GIS Example</title>
<script async defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script>
<script async defer src="https://accounts.google.com/gsi/client" onload="gisLoad()"></script>
</head>
<body>
<h1>GAPI Client with GIS Authorization</h1>
<button id="authorizeBtn" style="visibility:hidden;">Authorize and Load Events</button>
<button id="revokeBtn" style="visibility:hidden;">Revoke Access</button>
<div id="content"></div>
<script>
const YOUR_CLIENT_ID = "YOUR_CLIENT_ID";
const YOUR_API_KEY = 'YOUR_API_KEY';
const CALENDAR_SCOPE = 'https://www.googleapis.com/auth/calendar.readonly';
let tokenClient;
let libsLoaded = 0;
function gapiLoad() {
gapi.load('client', initGapiClient);
}
async function initGapiClient() {
try {
await gapi.client.init({ apiKey: YOUR_API_KEY });
await gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
console.log('GAPI client initialized.');
checkAllLoaded();
} catch (err) {
handleError('GAPI initialization failed:', err);
}
}
function gisLoad() {
try {
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: YOUR_CLIENT_ID,
scope: CALENDAR_SCOPE,
callback: '', // Will be set dynamically
error_callback: handleGisError,
});
console.log('GIS TokenClient initialized.');
checkAllLoaded();
} catch (err) {
handleError('GIS initialization failed:', err);
}
}
function checkAllLoaded() {
libsLoaded++;
if (libsLoaded === 2) {
document.getElementById('authorizeBtn').style.visibility = 'visible';
document.getElementById('revokeBtn').style.visibility = 'visible';
document.getElementById('authorizeBtn').onclick = makeApiCall;
document.getElementById('revokeBtn').onclick = revokeAccess;
console.log('Ready to authorize.');
}
}
function handleGisError(err) {
console.error('GIS Error:', err);
let message = 'An error occurred during authorization.';
if (err && err.type === 'popup_failed_to_open') {
message = 'Failed to open popup. Please disable popup blockers.';
} else if (err && err.type === 'popup_closed') {
message = 'Authorization popup was closed.';
}
document.getElementById('content').textContent = message;
}
function handleError(message, error) {
console.error(message, error);
document.getElementById('content').textContent = `${message} ${error.message || JSON.stringify(error)}`;
}
async function makeApiCall() {
document.getElementById('content').textContent = 'Processing...';
try {
let token = gapi.client.getToken();
if (!token || !token.access_token) {
console.log('No token, fetching one...');
await getToken();
}
console.log('Calling Calendar API...');
const response = await gapi.client.calendar.events.list({ 'calendarId': 'primary' });
displayEvents(response.result);
} catch (err) {
console.error('API call failed:', err);
const errorInfo = err.result && err.result.error;
if (errorInfo && (errorInfo.code === 401 || (errorInfo.code === 403 && errorInfo.status === "PERMISSION_DENIED"))) {
console.log('Auth error on API call, refreshing token...');
try {
await getToken({ prompt: 'consent' }); // Force refresh
const retryResponse = await gapi.client.calendar.events.list({ 'calendarId': 'primary' });
displayEvents(retryResponse.result);
} catch (refreshErr) {
handleError('Failed to refresh token or retry API call:', refreshErr);
}
} else {
handleError('Error loading events:', err.result ? err.result.error : err);
}
}
}
async function getToken(options = { prompt: '' }) {
return new Promise((resolve, reject) => {
if (!tokenClient) return reject(new Error("GIS TokenClient not initialized."));
tokenClient.callback = (tokenResponse) => {
if (tokenResponse.error) {
reject(new Error(`Token Error: ${tokenResponse.error} - ${tokenResponse.error_description}`));
} else {
console.log('Token acquired.');
resolve(tokenResponse);
}
};
tokenClient.requestAccessToken(options);
});
}
function displayEvents(result) {
const events = result.items;
if (events && events.length > 0) {
let eventList = '<h3>Upcoming Events:</h3><ul>' + events.map(event =>
`<li>${event.summary} (${event.start.dateTime || event.start.date})</li>`
).join('') + '</ul>';
document.getElementById('content').innerHTML = eventList;
} else {
document.getElementById('content').textContent = 'No upcoming events found.';
}
}
function revokeAccess() {
const token = gapi.client.getToken();
if (token && token.access_token) {
google.accounts.oauth2.revoke(token.access_token, () => {
console.log('Access revoked.');
document.getElementById('content').textContent = 'Access has been revoked.';
gapi.client.setToken(null);
});
} else {
document.getElementById('content').textContent = 'No token to revoke.';
}
}
</script>
</body>
</html>
Callback GAPI
Contoh ini menunjukkan cara menambahkan library Google Identity Service menggunakan
model token, menghapus modul gapi.auth2
, dan memanggil API menggunakan
Library Klien Google API untuk JavaScript.
Variabel digunakan untuk menerapkan urutan pemuatan library. Panggilan GAPI dilakukan dari dalam callback setelah token akses yang valid ditampilkan.
Pengguna diharapkan menekan tombol Tampilkan Kalender saat halaman pertama kali dimuat dan lagi saat mereka ingin memuat ulang info Kalender mereka.
<!DOCTYPE html>
<html>
<head>
<script async defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script>
<script async defer src="https://accounts.google.com/gsi/client" onload="gisInit()"></script>
</head>
<body>
<h1>GAPI with GIS callbacks</h1>
<button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
<button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>
<script>
let tokenClient;
let gapiInited;
let gisInited;
document.getElementById("showEventsBtn").style.visibility="hidden";
document.getElementById("revokeBtn").style.visibility="hidden";
function checkBeforeStart() {
if (gapiInited && gisInited){
// Start only when both gapi and gis are initialized.
document.getElementById("showEventsBtn").style.visibility="visible";
document.getElementById("revokeBtn").style.visibility="visible";
}
}
function gapiInit() {
gapi.client.init({
// NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
})
.then(function() { // Load the Calendar API discovery document.
gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
gapiInited = true;
checkBeforeStart();
});
}
function gapiLoad() {
gapi.load('client', gapiInit)
}
function gisInit() {
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
callback: '', // defined at request time
});
gisInited = true;
checkBeforeStart();
}
function showEvents() {
tokenClient.callback = (resp) => {
if (resp.error !== undefined) {
throw(resp);
}
// GIS has automatically updated gapi.client with the newly issued access token.
console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));
gapi.client.calendar.events.list({ 'calendarId': 'primary' })
.then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
.catch(err => console.log(err));
document.getElementById("showEventsBtn").innerText = "Refresh Calendar";
}
// Conditionally ask users to select the Google Account they'd like to use,
// and explicitly obtain their consent to fetch their Calendar.
// NOTE: To request an access token a user gesture is necessary.
if (gapi.client.getToken() === null) {
// Prompt the user to select a Google Account and asked for consent to share their data
// when establishing a new session.
tokenClient.requestAccessToken({prompt: 'consent'});
} else {
// Skip display of account chooser and consent dialog for an existing session.
tokenClient.requestAccessToken({prompt: ''});
}
}
function revokeToken() {
let cred = gapi.client.getToken();
if (cred !== null) {
google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
gapi.client.setToken('');
document.getElementById("showEventsBtn").innerText = "Show Calendar";
}
}
</script>
</body>
</html>
Contoh alur kode otorisasi
UX pop-up library Layanan Identitas Google dapat menggunakan pengalihan URL untuk menampilkan kode otorisasi langsung ke endpoint token backend Anda, atau handler callback JavaScript yang berjalan di browser pengguna yang memproksi respons ke platform Anda. Dalam kedua kasus tersebut, platform backend Anda akan menyelesaikan alur OAuth 2.0 untuk mendapatkan token akses dan refresh yang valid.
Cara lama
Aplikasi Web Sisi Server
Login dengan Google untuk aplikasi sisi server yang berjalan di platform backend menggunakan pengalihan ke Google untuk mendapatkan izin pengguna.
<!DOCTYPE html>
<html>
<head>
<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>
<script>
function start() {
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({
client_id: 'YOUR_CLIENT_ID',
api_key: 'YOUR_API_KEY',
discovery_docs: ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
// Scopes to request in addition to 'profile' and 'email'
scope: 'https://www.googleapis.com/auth/cloud-translation',
});
});
}
function signInCallback(authResult) {
if (authResult['code']) {
console.log("sending AJAX request");
// Send authorization code obtained from Google to backend platform
$.ajax({
type: 'POST',
url: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
// Always include an X-Requested-With header to protect against CSRF attacks.
headers: {
'X-Requested-With': 'XMLHttpRequest'
},
contentType: 'application/octet-stream; charset=utf-8',
success: function(result) {
console.log(result);
},
processData: false,
data: authResult['code']
});
} else {
console.log('error: failed to obtain authorization code')
}
}
</script>
</head>
<body>
<button id="signinButton">Sign In With Google</button>
<script>
$('#signinButton').click(function() {
// Obtain an authorization code from Google
auth2.grantOfflineAccess().then(signInCallback);
});
</script>
</body>
</html>
HTTP/REST menggunakan pengalihan
Menggunakan OAuth 2.0 untuk Aplikasi Server Web guna mengirim kode otorisasi dari browser pengguna ke platform backend Anda. Izin pengguna ditangani dengan mengalihkan browser pengguna ke Google.
/\*
\* Create form to request access token from Google's OAuth 2.0 server.
\*/
function oauthSignIn() {
// Google's OAuth 2.0 endpoint for requesting an access token
var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';
// Create <form> element to submit parameters to OAuth 2.0 endpoint.
var form = document.createElement('form');
form.setAttribute('method', 'GET'); // Send as a GET request.
form.setAttribute('action', oauth2Endpoint);
// Parameters to pass to OAuth 2.0 endpoint.
var params = {'client\_id': 'YOUR_CLIENT_ID',
'redirect\_uri': 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
'response\_type': 'token',
'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
'include\_granted\_scopes': 'true',
'state': 'pass-through value'};
// Add form parameters as hidden input values.
for (var p in params) {
var input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', p);
input.setAttribute('value', params[p]);
form.appendChild(input);
}
// Add form to page and submit it to open the OAuth 2.0 endpoint.
document.body.appendChild(form);
form.submit();
}
Cara baru
UX Pop-up GIS
Contoh ini hanya menampilkan library JavaScript Google Identity Service menggunakan model kode otorisasi dialog pop-up untuk izin pengguna dan handler callback untuk menerima kode otorisasi dari Google. Diagram ini diberikan untuk mengilustrasikan jumlah langkah minimum yang diperlukan untuk mengonfigurasi klien, mendapatkan izin, dan mengirim kode otorisasi ke platform backend Anda.
<!DOCTYPE html>
<html>
<head>
<script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
</head>
<body>
<script>
var client;
function initClient() {
client = google.accounts.oauth2.initCodeClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
ux_mode: 'popup',
callback: (response) => {
var code_receiver_uri = 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI',
// Send auth code to your backend platform
const xhr = new XMLHttpRequest();
xhr.open('POST', code_receiver_uri, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onload = function() {
console.log('Signed in as: ' + xhr.responseText);
};
xhr.send('code=' + response.code);
// After receipt, the code is exchanged for an access token and
// refresh token, and the platform then updates this web app
// running in user's browser with the requested calendar info.
},
});
}
function getAuthCode() {
// Request authorization code and obtain user consent
client.requestCode();
}
</script>
<button onclick="getAuthCode();">Load Your Calendar</button>
</body>
</html>
UX Pengalihan GIS
Model kode otorisasi mendukung mode UX pop-up dan pengalihan untuk mengirim kode otorisasi per pengguna ke endpoint yang dihosting oleh platform Anda. Mode UX pengalihan ditampilkan di sini:
<!DOCTYPE html>
<html>
<head>
<script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
</head>
<body>
<script>
var client;
function initClient() {
client = google.accounts.oauth2.initCodeClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly \
https://www.googleapis.com/auth/photoslibrary.readonly',
ux_mode: 'redirect',
redirect_uri: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI'
});
}
// Request an access token
function getAuthCode() {
// Request authorization code and obtain user consent
client.requestCode();
}
</script>
<button onclick="getAuthCode();">Load Your Calendar</button>
</body>
</html>
Library JavaScript
Google Identity Services adalah satu library JavaScript yang digunakan untuk autentikasi dan otorisasi pengguna yang menggabungkan dan menggantikan fitur dan fungsi yang ada di beberapa library dan modul yang berbeda:
Tindakan yang harus dilakukan saat bermigrasi ke Layanan Identitas:
Library JS yang ada | Library JS baru | Catatan |
---|---|---|
apis.google.com/js/api.js |
accounts.google.com/gsi/client |
Tambahkan library baru dan ikuti alur implisit. |
apis.google.com/js/client.js |
accounts.google.com/gsi/client |
Tambahkan library baru dan alur kode otorisasi. |
Referensi cepat library
Perbandingan objek dan metode antara library klien Google Sign-In JavaScript Lama dan library Google Identity Services Baru serta Catatan dengan informasi tambahan dan tindakan yang harus dilakukan selama migrasi.
Lama | Baru | Catatan |
---|---|---|
Objek GoogleAuth dan metode terkait: | ||
GoogleAuth.attachClickHandler() | Hapus | |
GoogleAuth.currentUser.get() | Hapus | |
GoogleAuth.currentUser.listen() | Hapus | |
GoogleAuth.disconnect() | google.accounts.oauth2.revoke | Ganti yang lama dengan yang baru. Pencabutan juga dapat terjadi dari https://myaccount.google.com/permissions |
GoogleAuth.grantOfflineAccess() | Hapus, ikuti alur kode otorisasi. | |
GoogleAuth.isSignedIn.get() | Hapus | |
GoogleAuth.isSignedIn.listen() | Hapus | |
GoogleAuth.signIn() | Hapus | |
GoogleAuth.signOut() | Hapus | |
GoogleAuth.then() | Hapus | |
Objek GoogleUser dan metode terkait: | ||
GoogleUser.disconnect() | google.accounts.id.revoke | Ganti yang lama dengan yang baru. Pencabutan juga dapat terjadi dari https://myaccount.google.com/permissions |
GoogleUser.getAuthResponse() | requestCode() or requestAccessToken() | Mengganti yang lama dengan yang baru |
GoogleUser.getBasicProfile() | Hapus. Gunakan Token ID sebagai gantinya, lihat Bermigrasi dari Login dengan Google. | |
GoogleUser.getGrantedScopes() | hasGrantedAnyScope() | Mengganti yang lama dengan yang baru |
GoogleUser.getHostedDomain() | Hapus | |
GoogleUser.getId() | Hapus | |
GoogleUser.grantOfflineAccess() | Hapus, ikuti alur kode otorisasi. | |
GoogleUser.grant() | Hapus | |
GoogleUser.hasGrantedScopes() | hasGrantedAnyScope() | Mengganti yang lama dengan yang baru |
GoogleUser.isSignedIn() | Hapus | |
GoogleUser.reloadAuthResponse() | requestAccessToken() | Hapus yang lama, panggil yang baru untuk mengganti token akses yang telah habis masa berlakunya atau dicabut. |
Objek gapi.auth2 dan metode terkait: | ||
Objek gapi.auth2.AuthorizeConfig | TokenClientConfig atau CodeClientConfig | Mengganti yang lama dengan yang baru |
Objek gapi.auth2.AuthorizeResponse | Hapus | |
Objek gapi.auth2.AuthResponse | Hapus | |
gapi.auth2.authorize() | requestCode() or requestAccessToken() | Mengganti yang lama dengan yang baru |
gapi.auth2.ClientConfig() | TokenClientConfig atau CodeClientConfig | Mengganti yang lama dengan yang baru |
gapi.auth2.getAuthInstance() | Hapus | |
gapi.auth2.init() | initTokenClient() or initCodeClient() | Mengganti yang lama dengan yang baru |
Objek gapi.auth2.OfflineAccessOptions | Hapus | |
Objek gapi.auth2.SignInOptions | Hapus | |
Objek gapi.signin2 dan metode terkait: | ||
gapi.signin2.render() | Hapus. Pemuatan DOM HTML dari elemen g_id_signin atau panggilan JS ke google.accounts.id.renderButton memicu login pengguna ke Akun Google. |
Contoh kredensial
Kredensial yang ada
Library platform Login dengan Google, Google API Client Library for JavaScript, atau panggilan langsung ke endpoint Google OAuth 2.0 akan menampilkan token akses OAuth 2.0 dan Token ID OpenID Connect dalam satu respons.
Contoh respons yang berisi access_token
dan id_token
:
{
"token_type": "Bearer",
"access_token": "ya29.A0ARrdaM-SmArZaCIh68qXsZSzyeU-8mxhQERHrP2EXtxpUuZ-3oW8IW7a6D2J6lRnZrRj8S6-ZcIl5XVEqnqxq5fuMeDDH_6MZgQ5dgP7moY-yTiKR5kdPm-LkuPM-mOtUsylWPd1wpRmvw_AGOZ1UUCa6UD5Hg",
"scope": "https://www.googleapis.com/auth/calendar.readonly",
"login_hint": "AJDLj6I2d1RH77cgpe__DdEree1zxHjZJr4Q7yOisoumTZUmo5W2ZmVFHyAomUYzLkrluG-hqt4RnNxrPhArd5y6p8kzO0t8xIfMAe6yhztt6v2E-_Bb4Ec3GLFKikHSXNh5bI-gPrsI",
"expires_in": 3599,
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjkzNDFhYmM0MDkyYjZmYzAzOGU0MDNjOTEwMjJkZDNlNDQ1MzliNTYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiYXVkIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTE3NzI2NDMxNjUxOTQzNjk4NjAwIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXRfaGFzaCI6IkJBSW55TjN2MS1ZejNLQnJUMVo0ckEiLCJuYW1lIjoiQnJpYW4gRGF1Z2hlcnR5IiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hLS9BT2gxNEdnenAyTXNGRGZvbVdMX3VDemRYUWNzeVM3ZGtxTE5ybk90S0QzVXNRPXM5Ni1jIiwiZ2l2ZW5fbmFtZSI6IkJyaWFuIiwiZmFtaWx5X25hbWUiOiJEYXVnaGVydHkiLCJsb2NhbGUiOiJlbiIsImlhdCI6MTYzODk5MTYzOCwiZXhwIjoxNjM4OTk1MjM4LCJqdGkiOiI5YmRkZjE1YWFiNzE2ZDhjYmJmNDYwMmM1YWM3YzViN2VhMDQ5OTA5In0.K3EA-3Adw5HA7O8nJVCsX1HmGWxWzYk3P7ViVBb4H4BoT2-HIgxKlx1mi6jSxIUJGEekjw9MC-nL1B9Asgv1vXTMgoGaNna0UoEHYitySI23E5jaMkExkTSLtxI-ih2tJrA2ggfA9Ekj-JFiMc6MuJnwcfBTlsYWRcZOYVw3QpdTZ_VYfhUu-yERAElZCjaAyEXLtVQegRe-ymScra3r9S92TA33ylMb3WDTlfmDpWL0CDdDzby2asXYpl6GQ7SdSj64s49Yw6mdGELZn5WoJqG7Zr2KwIGXJuSxEo-wGbzxNK-mKAiABcFpYP4KHPEUgYyz3n9Vqn2Tfrgp-g65BQ",
"session_state": {
"extraQueryParams": {
"authuser": "0"
}
},
"first_issued_at": 1638991637982,
"expires_at": 1638995236982,
"idpId": "google"
}
Kredensial Google Identity Services
Google Identity Services library menampilkan:
token akses saat digunakan untuk otorisasi:
{ "access_token": "ya29.A0ARrdaM_LWSO-uckLj7IJVNSfnUityT0Xj-UCCrGxFQdxmLiWuAosnAKMVQ2Z0LLqeZdeJii3TgULp6hR_PJxnInBOl8UoUwWoqsrGQ7-swxgy97E8_hnzfhrOWyQBmH6zs0_sUCzwzhEr_FAVqf92sZZHphr0g", "token_type": "Bearer", "expires_in": 3599, "scope": "https://www.googleapis.com/auth/calendar.readonly" }
atau, token ID saat digunakan untuk autentikasi:
{ "clientId": "538344653255-758c5h5isc45vgk27d8h8deabovpg6to.apps.googleusercontent.com", "credential": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxODkyZWI0OWQ3ZWY5YWRmOGIyZTE0YzA1Y2EwZDAzMjcxNGEyMzciLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2MzkxNTcyNjQsImF1ZCI6IjUzODM0NDY1MzI1NS03NThjNWg1aXNjNDV2Z2syN2Q4aDhkZWFib3ZwZzZ0by5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjExNzcyNjQzMTY1MTk0MzY5ODYwMCIsIm5vbmNlIjoiZm9vYmFyIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwibmFtZSI6IkJyaWFuIERhdWdoZXJ0eSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS0vQU9oMTRHZ3pwMk1zRkRmb21XTF91Q3pkWFFjc3lTN2RrcUxOcm5PdEtEM1VzUT1zOTYtYyIsImdpdmVuX25hbWUiOiJCcmlhbiIsImZhbWlseV9uYW1lIjoiRGF1Z2hlcnR5IiwiaWF0IjoxNjM5MTU3NTY0LCJleHAiOjE2MzkxNjExNjQsImp0aSI6IjRiOTVkYjAyZjU4NDczMmUxZGJkOTY2NWJiMWYzY2VhYzgyMmI0NjUifQ.Cr-AgMsLFeLurnqyGpw0hSomjOCU4S3cU669Hyi4VsbqnAV11zc_z73o6ahe9Nqc26kPVCNRGSqYrDZPfRyTnV6g1PIgc4Zvl-JBuy6O9HhClAK1HhMwh1FpgeYwXqrng1tifmuotuLQnZAiQJM73Gl-J_6s86Buo_1AIx5YAKCucYDUYYdXBIHLxrbALsA5W6pZCqqkMbqpTWteix-G5Q5T8LNsfqIu_uMBUGceqZWFJALhS9ieaDqoxhIqpx_89QAr1YlGu_UO6R6FYl0wDT-nzjyeF5tonSs3FHN0iNIiR3AMOHZu7KUwZaUdHg4eYkU-sQ01QNY_11keHROCRQ", "select_by": "user" }
Respons token tidak valid
Contoh respons dari Google saat mencoba membuat permintaan API menggunakan token akses yang telah habis masa berlakunya, dicabut, atau tidak valid:
Header Respons HTTP
www-authenticate: Bearer realm="https://accounts.google.com/", error="invalid_token"
Isi respons
{
"error": {
"code": 401,
"message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"errors": [
{
"message": "Invalid Credentials",
"domain": "global",
"reason": "authError",
"location": "Authorization",
"locationType": "header"
}
],
"status": "UNAUTHENTICATED"
}
}