API jembatan JavaScript
Masuk dan passkey
Pemilih akun Google yang sungguhan, native dan bukan pengalihan web, dan passkey melalui Credential Manager Android - navigator.credentials berfungsi seperti di Chrome, atau gunakan AppMint.passkey dengan opsi JSON dari server Anda.
AppMint.passkey helper#
window.AppMint.passkey — create(options), get(options), isAvailable(), origin(), assetLinks()
Contoh
Passkey (masuk dengan sidik jari, wajah, atau kunci layar - tanpa kata sandi) melalui pengelola passkey Android, memakai opsi JSON yang dibuat server passkey Anda.
Mengembalikan: create(optionsJSON) → Promise dari RegistrationResponseJSON; get(optionsJSON) → Promise dari AuthenticationResponseJSON (kirim salah satunya ke server Anda untuk diverifikasi). Keduanya ditolak dengan DOMException (err.name, dan err.reason = kode singkat). isAvailable() → boolean, origin() → string, assetLinks() → array - semuanya seketika. Membutuhkan: Android 9+ dengan Google Play services, server passkey, dan dua langkah penyiapan di bawah. Tidak ada sakelar build.
Masuk:
async function signInWithPasskey() {
if (!window.AppMint || !window.AppMint.passkey || !window.AppMint.passkey.isAvailable()) {
alert('Passkeys are not available on this phone.');
return;
}
var options = await (await fetch('https://your-domain.com/passkey/login-options')).json();
var answer;
try {
answer = await window.AppMint.passkey.get(options); // rpId must be your domain
} catch (err) {
if (err.name === 'NotAllowedError') return; // cancelled, or no passkey on this phone
alert('Passkey problem: ' + err.message);
return;
}
var res = await fetch('https://your-domain.com/passkey/login-verify', {
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(answer)
});
if (res.ok) showAccount();
}Buat satu (setelah pengguna masuk dengan cara lain):
async function addPasskey() {
var options = await (await fetch('https://your-domain.com/passkey/register-options')).json();
try {
var answer = await window.AppMint.passkey.create(options);
await fetch('https://your-domain.com/passkey/register-verify', {
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(answer)
});
} catch (err) {
if (err.name === 'InvalidStateError') alert('You already have a passkey here.');
else if (err.name !== 'NotAllowedError') alert('Passkey problem: ' + err.message);
}
}Atur sekali saja - jalankan ini di aplikasi yang diinstal DARI Google Play (Play menandatangani dengan kuncinya sendiri):
console.log(JSON.stringify(window.AppMint.passkey.assetLinks(), null, 2));
// save as https://your-domain.com/.well-known/assetlinks.json
console.log(window.AppMint.passkey.origin());
// android:apk-key-hash:... — add to your server's expected originsCatatan: err.name / err.reason: NotAllowedError (cancelled, no_credential, interrupted), InvalidStateError (sudah ada), SecurityError dengan not_linked (assetlinks.json tidak mencantumkan aplikasi) atau rp_mismatch (rpId bukan domain halaman ini), NotSupportedError / unavailable (Android < 9 atau tanpa Play services), TypeError / invalid_options (halaman yang dibundel di aplikasi tidak memiliki domain, jadi atur rp.id / rpId ke domain Anda). window.AppMint.passkey hanya ada di aplikasi; di browser gunakan navigator.credentials (kode yang sama berfungsi di aplikasi juga).
WebToApkAuth.signInWithGoogle helper#
window.WebToApkAuth.signInWithGoogle(webClientId)
Contoh
Memasukkan pengguna dengan akun Google mereka melalui pemilih akun bawaan Android, dan memberi Anda Google ID token. Google memblokir halaman masuknya di dalam WebView aplikasi ("disallowed_useragent"); jalur native ini tidak diblokir.
Mengembalikan: Promise dari {ok:true, idToken, email, displayName, profilePictureUri}. DITOLAK dengan Error yang message-nya adalah kodenya (cancelled, google_play_services_unavailable, missing_web_client_id, failed, …). Membutuhkan: Web client ID OAuth Anda (berakhir dengan .apps.googleusercontent.com), dan sidik jari SHA-1 dan SHA-256 aplikasi terdaftar di proyek Google / Firebase Anda (dari file _signkey_info.txt build Anda, dan kunci App signing Play jika Anda menerbitkan di Play). Tidak ada sakelar build.
Dengan Firebase Authentication (SDK compat):
var WEB_CLIENT_ID = '1234567890-abc.apps.googleusercontent.com';
document.getElementById('google-button').addEventListener('click', async function () {
if (!window.WebToApkAuth) {
alert('Google sign-in works in the app.'); // or run your normal web sign-in here
return;
}
try {
var r = await window.WebToApkAuth.signInWithGoogle(WEB_CLIENT_ID);
var cred = firebase.auth.GoogleAuthProvider.credential(r.idToken);
await firebase.auth().signInWithCredential(cred);
showWelcome(r.displayName || r.email);
} catch (err) {
if (err.message === 'cancelled') return; // user closed the picker
if (err.message === 'google_play_services_unavailable') {
alert('No Google account or Google Play services on this phone.');
return;
}
alert('Google sign-in failed: ' + err.message);
}
});Dengan server Anda sendiri - kirim ID token dan verifikasi di sana (jangan pernah mempercayainya hanya di halaman):
async function signInWithMyServer() {
var r = await window.WebToApkAuth.signInWithGoogle(WEB_CLIENT_ID);
await fetch('https://your-domain.com/auth/google', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ idToken: r.idToken })
});
}Dengan Supabase Auth (serahkan ID token ke signInWithIdToken):
async function signInWithSupabase() {
if (!window.WebToApkAuth) {
return supabase.auth.signInWithOAuth({ provider: 'google' }); // normal web sign-in in a browser
}
try {
var r = await window.WebToApkAuth.signInWithGoogle(WEB_CLIENT_ID);
var res = await supabase.auth.signInWithIdToken({ provider: 'google', token: r.idToken });
if (res.error) throw res.error;
showWelcome(res.data.user.email);
} catch (err) {
if (err.message !== 'cancelled') alert('Google sign-in failed: ' + err.message);
}
}Catatan: Berikan Web client ID. Tanpa argumen helper memakai window.firebaseConfig._googleWebClientId jika halaman Anda menetapkannya, lalu klien Web di google-services.json yang Anda unggah untuk aplikasi ini (hanya jika file itu proyek Firebase Anda sendiri dengan masuk Google diaktifkan - jangan pernah build AppMint Push); jika semuanya tidak ada, ditolak dengan missing_web_client_id. Halaman yang bukan milik aplikasi (situs eksternal yang dibuka di dalam aplikasi) ditolak dengan foreign_origin. Gunakan WEB client ID, bukan Android client ID. "No credentials available" biasanya berarti SHA-1 belum terdaftar. Helper ini hanya ada di aplikasi - di browser gunakan cara masuk web biasa. Panggil dari ketukan tombol.
WebToApkAuth.signOutGoogle helper#
window.WebToApkAuth.signOutGoogle()
Contoh
Menghapus pilihan masuk Google yang tersimpan di Android, sehingga signInWithGoogle berikutnya menampilkan pemilih akun lagi alih-alih diam-diam memakai akun terakhir.
Mengembalikan: Promise dari {ok:true}; ditolak dengan Error yang message-nya menyatakan apa yang salah. Membutuhkan: tidak ada.
Panggil bersama proses keluar Anda sendiri:
document.getElementById('sign-out').addEventListener('click', async function () {
await firebase.auth().signOut(); // your normal sign-out (Firebase here)
if (window.WebToApkAuth) {
try {
await window.WebToApkAuth.signOutGoogle();
} catch (err) {
console.log('Could not clear the Google choice: ' + err.message);
}
}
showSignInScreen();
});Tombol "Switch account": hapus pilihan tersimpan, lalu masuk lagi agar pengguna memilih akun lain:
async function switchGoogleAccount() {
if (!window.WebToApkAuth) return;
await firebase.auth().signOut();
try { await window.WebToApkAuth.signOutGoogle(); } catch (err) { /* nothing saved to clear */ }
try {
var r = await window.WebToApkAuth.signInWithGoogle('1234567890-abc.apps.googleusercontent.com');
await firebase.auth().signInWithCredential(firebase.auth.GoogleAuthProvider.credential(r.idToken));
} catch (err) {
if (err.message !== 'cancelled') alert('Google sign-in failed: ' + err.message);
showSignInScreen();
}
}Keluar dari server Anda sendiri dulu, lalu hapus pilihan Google tanpa membiarkan kegagalan menghalangi proses keluar:
async function signOutEverywhere() {
await fetch('https://your-domain.com/auth/logout', { method: 'POST', credentials: 'include' });
localStorage.removeItem('profile');
if (window.WebToApkAuth) {
var r = await window.WebToApkAuth.signOutGoogle()
.catch(function (err) { return { ok: false, error: err.message }; });
if (!r.ok) console.log('Google choice not cleared: ' + r.error);
}
location.replace('/login');
}Catatan: Ini tidak mengakhiri sesi aplikasi Anda sendiri - keluarkan pengguna dari backend Anda sendiri. Ini hanya mengatur ulang akun Google mana yang ditawarkan ponsel berikutnya.
OTPCredential standar web#
navigator.credentials.get({ otp: { transport: ['sms'] } }) — WebOTP
Contoh
API WebOTP standar: kode masuk dari SMS terisi sendiri. Android menampilkan lembar "Allow this app to read this message?" dari Google - tanpa izin SMS.
Mengembalikan: Promise dari OTPCredential {type:'otp', code}. Ditolak AbortError saat pengguna mengetuk Deny atau sinyal dibatalkan, InvalidStateError setelah lima menit tanpa SMS, NotSupportedError tanpa Google Play services. Membutuhkan: tidak ada yang perlu diaktifkan. SMS harus DIAKHIRI dengan baris yang menyebut host halaman ini: @<host> #<code>.
const input = document.querySelector('input[autocomplete="one-time-code"]');
if ('OTPCredential' in window) {
const ac = new AbortController();
document.querySelector('form').addEventListener('submit', () => ac.abort());
navigator.credentials.get({ otp: { transport: ['sms'] }, signal: ac.signal })
.then((otp) => { input.value = otp.code; input.form.requestSubmit(); })
.catch((e) => console.log('Type the code instead:', e.name));
}SMS yang dikirim server Anda (baris terakhir adalah pengikatnya):
Your Acme code is 482913.
@acme.example #482913Setelah "Resend code", mulai permintaan baru (menggantikan yang masih menunggu, yang ditolak dengan AbortError):
async function resendAndWait(phone) {
await fetch('/api/send-code', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ phone })
});
if (!('OTPCredential' in window)) return;
try {
const otp = await navigator.credentials.get({ otp: { transport: ['sms'] } });
await verifyCode(otp.code);
} catch (e) {
if (e.name === 'InvalidStateError') showMessage('No SMS yet. Tap Resend to try again.');
}
}Catatan: host harus host halaman itu sendiri - untuk aplikasi berbasis situs web itu adalah domain Anda (SMS yang sudah dibaca Chrome); untuk aplikasi offline/buatan AI itu adalah appassets.androidplatform.net. Pesan untuk host lain diabaikan dan aplikasi terus menunggu. Hanya halaman teratas (kode yang terikat ke origin tertanam, @top #code @iframe, tidak didukung). Hanya satu permintaan yang menunggu pada satu waktu; yang lebih baru membatalkan yang lama. Event di baliknya: appmint:otp.
__otpCancel jembatan#
window.WebToApk.__otpCancel(requestId: String)
Membatalkan permintaan WebOTP yang tertunda (AbortSignal, atau permintaan baru menggantikannya).
Contoh
Transport internal di balik pembatalan permintaan WebOTP (AbortSignal). Halaman memakai API standar; jangan pernah memanggil ini langsung - metode __ dapat berubah tanpa pemberitahuan.
Mengembalikan: tidak ada. Membutuhkan: tidak ada yang perlu diaktifkan.
Gunakan API publik:
const ac = new AbortController();
const cred = await navigator.credentials.get({ otp: { transport: ['sms'] }, signal: ac.signal });
codeInput.value = cred.code;
ac.abort(); // the pending get() rejects with AbortErrorBerhenti menunggu begitu pengguna mulai mengetik kodenya sendiri:
const input = document.querySelector('input[autocomplete="one-time-code"]');
const ac = new AbortController();
input.addEventListener('input', () => ac.abort(), { once: true });
navigator.credentials.get({ otp: { transport: ['sms'] }, signal: ac.signal })
.then((cred) => { input.value = cred.code; })
.catch((e) => { if (e.name !== 'AbortError') console.log('No code:', e.name); });Batalkan penantian saat pengguna kembali untuk mengubah nomor ponselnya:
let otpAbort = null;
function waitForSms() {
otpAbort = new AbortController();
return navigator.credentials.get({ otp: { transport: ['sms'] }, signal: otpAbort.signal });
}
document.getElementById('change-number').addEventListener('click', () => {
if (otpAbort) { otpAbort.abort(); otpAbort = null; } // the pending get() rejects with AbortError
showPhoneStep();
});Catatan: Diimplementasikan di shell aplikasi (WebApiPolyfills.kt). Kode halaman yang sama berfungsi tanpa perubahan di Chrome.
__otpStart jembatan#
window.WebToApk.__otpStart(requestId: String)
WebOTP: menunggu (hingga lima menit) satu SMS melalui lembar SMS User Consent Google - tanpa izin SMS. Jawabannya adalah `appmint:otp {requestId, message|error}`.
Contoh
Transport internal di balik navigator.credentials.get({ otp: { transport: ['sms'] } }). Halaman memakai API standar; jangan pernah memanggil ini langsung - metode __ dapat berubah tanpa pemberitahuan.
Mengembalikan: tidak ada; jawaban datang sebagai event appmint:otp {requestId, message} atau {requestId, error} (cancelled, timeout, unavailable). Membutuhkan: tidak ada yang perlu diaktifkan.
Gunakan API publik:
const ac = new AbortController();
const cred = await navigator.credentials.get({ otp: { transport: ['sms'] }, signal: ac.signal });
codeInput.value = cred.code;Berhenti menunggu setelah satu menit dengan sinyal batas waktu:
async function waitForCode(input) {
if (!('OTPCredential' in window)) return;
try {
const cred = await navigator.credentials.get({
otp: { transport: ['sms'] },
signal: AbortSignal.timeout(60000)
});
input.value = cred.code;
} catch (e) {
// TimeoutError after 60 s, AbortError when the user taps Deny
showMessage('Type the code from the SMS.');
}
}Beri tahu pengguna apa yang harus dilakukan selanjutnya berdasarkan nama kesalahan:
async function readOtp() {
try {
const cred = await navigator.credentials.get({ otp: { transport: ['sms'] } });
return cred.code;
} catch (e) {
if (e.name === 'InvalidStateError') showResendButton(); // no SMS within five minutes
else if (e.name === 'NotSupportedError') showManualEntry(); // no Google Play services
return null; // AbortError: the user tapped Deny
}
}Catatan: Diimplementasikan di shell aplikasi (WebApiPolyfills.kt). Kode halaman yang sama berfungsi tanpa perubahan di Chrome.
passkeyAssetLinks jembatan#
window.WebToApk.passkeyAssetLinks(): String
Array assetlinks.json (sebagai teks) yang mengotorisasi aplikasi terpasang ini untuk domain Anda.
Contoh
Membuat konten assetlinks.json yang memberi tahu Android bahwa domain Anda memercayai aplikasi ini (nama paket + SHA-256 sertifikat yang dipakai menandatangani aplikasi terpasang). Halaman biasanya memakai API publik AppMint.passkey.assetLinks(), yang membungkus panggilan ini dan mengembalikan array yang sudah diurai.
Mengembalikan: array JSON sebagai TEKS, seketika ("[]" jika sertifikat tidak dapat dibaca). Membutuhkan: tidak ada.
Jalankan sekali di aplikasi yang terpasang DARI Google Play, lalu simpan hasilnya sebagai https://your-domain.com/.well-known/assetlinks.json:
if (window.AppMint && window.AppMint.passkey) {
console.log(JSON.stringify(window.AppMint.passkey.assetLinks(), null, 2));
}Panggilan mentah mengembalikan teks yang sudah diformat:
if (window.WebToApk && typeof window.WebToApk.passkeyAssetLinks === 'function') {
var text = window.WebToApk.passkeyAssetLinks();
console.log(text);
}Baca nama paket dan sidik jari SHA-256 dari pernyataan, untuk konsol yang memintanya satu per satu:
if (window.AppMint && window.AppMint.passkey) {
var statements = window.AppMint.passkey.assetLinks();
if (statements.length === 0) {
console.log('The signing certificate could not be read.');
} else {
var target = statements[0].target;
console.log('Package: ' + target.package_name);
console.log('SHA-256: ' + target.sha256_cert_fingerprints[0]); // AB:CD:... upper-case, colon-separated
}
}Catatan: Domain harus persis sama dengan rpID server Anda (www. adalah domain yang berbeda), disajikan lewat https tanpa pengalihan. Jika file salah, panggilan passkey gagal dengan SecurityError (alasan not_linked).
passkeyIsAvailable jembatan#
window.WebToApk.passkeyIsAvailable(): Boolean
True di Android 9+ dengan Google Play services - ponsel yang dapat menyimpan passkey.
Contoh
Menyatakan apakah ponsel ini dapat memakai passkey. Halaman biasanya memakai API publik AppMint.passkey.isAvailable() (atau PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()), yang membungkus panggilan ini.
Mengembalikan: boolean, seketika - true di Android 9+ dengan Google Play services dan WebView yang cukup baru untuk saluran passkey. Membutuhkan: tidak ada.
API publik:
var canPasskey = !!(window.AppMint && window.AppMint.passkey && window.AppMint.passkey.isAvailable());
document.getElementById('passkey-button').hidden = !canPasskey;Panggilan mentahnya, jika Anda membutuhkannya:
var canPasskey = !!window.WebToApk &&
typeof window.WebToApk.passkeyIsAvailable === 'function' &&
window.WebToApk.passkeyIsAvailable() === true;Tawarkan "Add a passkey" sekali setelah masuk dengan kata sandi, hanya di ponsel yang dapat menyimpannya (pemeriksaan standar, kode yang sama di Chrome):
async function offerPasskeyAfterLogin() {
var ok = !!window.PublicKeyCredential &&
await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
if (!ok) return; // Android below 9 or no Google Play services
if (localStorage.getItem('passkey-offered')) return;
localStorage.setItem('passkey-offered', '1');
document.getElementById('add-passkey-banner').hidden = false;
}Catatan: Jika ini false, AppMint.passkey.create/get ditolak dengan NotSupportedError. Sembunyikan tombol passkey dan tawarkan cara masuk lainnya.
passkeyOrigin jembatan#
window.WebToApk.passkeyOrigin(): String
Origin yang dilihat server passkey dari aplikasi ini: `android:apk-key-hash:<base64url SHA-256>`.
Contoh
Memberi origin yang dilihat server passkey Anda dari aplikasi ini: android:apk-key-hash:<base64url SHA-256 of the signing certificate>. Halaman biasanya memakai API publik AppMint.passkey.origin(), yang membungkus panggilan ini.
Mengembalikan: string, seketika ("" jika sertifikat tidak dapat dibaca). Membutuhkan: tidak ada.
Jalankan ini sekali di aplikasi yang terpasang DARI Google Play, dan tambahkan nilainya ke origin yang diizinkan server Anda:
if (window.AppMint && window.AppMint.passkey) {
console.log(window.AppMint.passkey.origin()); // android:apk-key-hash:Lir5oIjf552K...
}Panggilan mentahnya memberikan string yang sama:
if (window.WebToApk && typeof window.WebToApk.passkeyOrigin === 'function') {
console.log(window.WebToApk.passkeyOrigin());
}Tampilkan origin di layar pengaturan tersembunyi, agar Anda bisa membacanya dari instalasi Play tanpa debugger:
var out = document.getElementById('passkey-origin');
var origin = (window.AppMint && window.AppMint.passkey) ? window.AppMint.passkey.origin() : '';
if (!origin) {
out.textContent = 'Open this screen in the installed app.';
} else {
out.textContent = origin; // android:apk-key-hash:...
out.style.userSelect = 'all'; // one long-press selects the whole value
}Catatan: Google Play menandatangani ulang aplikasi Anda, jadi APK uji memberi nilai yang berbeda dari instalasi Play. Contoh SimpleWebAuthn: expectedOrigin: ['https://your-domain.com', 'android:apk-key-hash:...'].
signInWithGoogle jembatan#
window.WebToApk.signInWithGoogle(serverClientId: String, callbackId: String)
===== Native Google Sign-In via Credential Manager ===== Melewati pemblokiran OAuth WebView Android oleh Google (kesalahan disallowed_useragent) dengan menjalankan alur masuk di Android native dan menjembatani hanya Google ID token yang dihasilkan kembali ke JS, tempat Firebase Web SDK memakainya lewat GoogleAuthProvider.credential(idToken) + signInWithCredential(...). Kontrak JS: window.WebToApk.signInWithGoogle(serverClientId, callbackId) serverClientId "" = klien Web (tipe 3) di google-services.json milik pembuat untuk paket ini; jika tidak ada, kesalahan "missing_web_client_id". Halaman yang bukan milik aplikasi mendapat kesalahan "foreign_origin". -> saat selesai, window.__webToApkAuth[callbackId](resultJsonString) dipanggil resultJsonString = '{"ok":true,"idToken":"...","email":"...","displayName":"..."}' atau '{"ok":false,"error":"<message>"}'
Contoh
Memulai masuk Google native (pemilih akun Android) dan menjawab dengan Google ID token. Halaman biasanya memakai helper Promise WebToApkAuth.signInWithGoogle(webClientId), yang membungkus panggilan ini.
Mengembalikan: tidak ada. Jawaban datang kemudian: shell memanggil window.__webToApkAuth[callbackId](json) dengan '{"ok":true,"idToken":"...","email":"...","displayName":"...","profilePictureUri":"..."}' atau '{"ok":false,"error":"<code>","detail":"..."}', lalu menghapus entri itu. Membutuhkan: OAuth Web client ID Anda, dan SHA-1 / SHA-256 aplikasi terdaftar di proyek Google atau Firebase Anda. Tidak ada sakelar build.
Helper (disarankan):
async function googleSignIn() {
if (!window.WebToApkAuth) return null;
try {
var r = await window.WebToApkAuth.signInWithGoogle('1234567890-abc.apps.googleusercontent.com');
return r.idToken;
} catch (err) {
if (err.message !== 'cancelled') alert('Google sign-in failed: ' + err.message);
return null;
}
}Panggilan mentah (urutan argumen: web client ID, lalu id callback Anda):
function googleSignInRaw(done) {
if (!window.WebToApk || typeof window.WebToApk.signInWithGoogle !== 'function') return;
var id = 'g_' + Date.now();
window.__webToApkAuth = window.__webToApkAuth || {};
window.__webToApkAuth[id] = function (json) {
var r = JSON.parse(json);
if (r.ok) done(r.idToken, r.email);
else if (r.error !== 'cancelled') alert('Google sign-in failed: ' + r.error);
};
window.WebToApk.signInWithGoogle('1234567890-abc.apps.googleusercontent.com', id);
}Panggilan mentah dengan client ID kosong, yang memakai klien Web dari google-services.json yang Anda unggah:
function googleSignInFromUploadedFile() {
return new Promise(function (resolve, reject) {
if (!window.WebToApk || typeof window.WebToApk.signInWithGoogle !== 'function') {
return reject(new Error('not_in_app'));
}
var id = 'g_' + Date.now();
window.__webToApkAuth = window.__webToApkAuth || {};
window.__webToApkAuth[id] = function (json) {
var r = JSON.parse(json);
if (r.ok) resolve(r); else reject(new Error(r.error));
};
window.WebToApk.signInWithGoogle('', id);
});
}
googleSignInFromUploadedFile()
.then(function (r) { showProfile(r.displayName, r.profilePictureUri); })
.catch(function (e) {
if (e.message === 'missing_web_client_id') console.log('Pass your Web client ID: the uploaded file has none.');
});Catatan: Kode kesalahan: cancelled (pengguna menutup pemilih), google_play_services_unavailable (tidak ada akun atau penyedia Google - juga tampilan jika pendaftaran SHA-1 hilang), missing_web_client_id (tidak ada yang diberikan, dan tidak ada klien Web di google-services.json yang Anda unggah), foreign_origin (halaman yang tampil bukan milik aplikasi), failed, unexpected_credential_type, parse_failed: .... Argumen pertama yang kosong memakai klien Web dari google-services.json unggahan Anda sendiri jika ada. Verifikasi ID token di server Anda (atau serahkan ke Firebase dengan GoogleAuthProvider.credential(idToken)).
signOutGoogle jembatan#
window.WebToApk.signOutGoogle(callbackId: String)
Menghapus status Credential Manager yang tersimpan sehingga panggilan signInWithGoogle berikutnya menampilkan pemilih akun lagi (bukan diam-diam memilih ulang akun terakhir). Aplikasi yang dibuat sebaiknya memanggil ini saat pengguna keluar, selain firebase.auth().signOut().
Contoh
Menghapus status masuk Google yang tersimpan di Android, sehingga proses masuk berikutnya menampilkan pemilih akun lagi. Halaman biasanya memakai helper Promise WebToApkAuth.signOutGoogle(), yang membungkus panggilan ini.
Mengembalikan: tidak ada. Jawaban datang kemudian: shell memanggil window.__webToApkAuth[callbackId](json) dengan '{"ok":true}' atau '{"ok":false,"error":"..."}'. Membutuhkan: tidak ada.
Helper (disarankan):
async function signOut() {
await myBackendSignOut(); // end your own session first
if (window.WebToApkAuth) {
try { await window.WebToApkAuth.signOutGoogle(); } catch (err) { /* nothing to undo */ }
}
}Panggilan mentah:
if (window.WebToApk && typeof window.WebToApk.signOutGoogle === 'function') {
var id = 'gout_' + Date.now();
window.__webToApkAuth = window.__webToApkAuth || {};
window.__webToApkAuth[id] = function (json) {
var r = JSON.parse(json);
if (!r.ok) console.log('Google sign-out failed: ' + r.error);
};
window.WebToApk.signOutGoogle(id);
}Panggilan mentah yang dibungkus dalam Promise, dipakai saat pengguna menghapus akunnya:
function clearGoogleChoice() {
return new Promise(function (resolve) {
if (!window.WebToApk || typeof window.WebToApk.signOutGoogle !== 'function') return resolve(false);
var id = 'gout_' + Date.now();
window.__webToApkAuth = window.__webToApkAuth || {};
window.__webToApkAuth[id] = function (json) { resolve(JSON.parse(json).ok === true); };
window.WebToApk.signOutGoogle(id);
});
}
async function deleteAccount() {
await fetch('https://your-domain.com/account', { method: 'DELETE', credentials: 'include' });
await clearGoogleChoice(); // the next sign-in starts from the account picker
showSignInScreen();
}Catatan: Ini tidak mengeluarkan pengguna dari Firebase atau server Anda - lakukan sendiri.