Google API Uncaught exception when use gapi.load - javascript

When I used this type of initialization:
var auth2;
gapi.load('auth2', function() {
gapi.auth2.init({
client_id: 'MY_CLIENT_ID.apps.googleusercontent.com',
}).then(function(){
auth2 = gapi.auth2.getAuthInstance();
console.log(auth2.isSignedIn.get()); //now this always returns correctly
});
});
I got the following error:
uncaught exception: gapi.auth2.ExternallyVisibleError: Missing required parameter 'client_id' (unknown)
TypeError: auth2 is undefined
But if I initialized using meta tag
<meta name="google-signin-client_id" content="MY_CLIENT_ID.apps.googleusercontent.com">
That works, but auth2.isSignedIn.get() gave me inconsistent values.
How can I solved this issue?

You may have included the below line of code to display Google's Sign In button.
<div class="g-signin2" data-onsuccess="onSignIn"></div>
If so, remove that from your html page and check if you are still getting error in console.

Building on Krishna's answer, specifically, you want to remove the data-onsuccess="onSignIn"></div> section, then create a custom button:
<div id="my-signin2"></div>
<script>
function renderButton() {
gapi.signin2.render('my-signin2', {
'scope': 'profile email',
'width': 240,
'height': 50,
'longtitle': true,
'theme': 'dark',
});
}
</script>
As my sign-in is handled server-side I've added another jquery function to redirect to my backend flow, but you can adjust accordingly:
<script>
$('#my-signin2').click(function() {
// if your sign in is handled by your backend:
location.href = "/signin";
// signInCallback defined in step 6.
// auth2.grantOfflineAccess().then(signInCallback);
});
</script>

Related

change label of sign in with google button

I made a "sign in with google" button, but I just want to change its text to "sign up with google " nothing else but I want to change the label, any help, please!
Here is my code :
<!doctype html>
<html>
<head>
<meta name="google-signin-client_id" content="xxxxx
.apps.googleusercontent.com">
</head>
<body>
<div id="my-signin2"></div>
<script>
function onSuccess(googleUser) {
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut();
}//end of googleSignIn
function onFailure(error) {
console.log(error);
}
//custom google button
function renderButton() {
gapi.signin2.render('my-signin2', {
'scope': 'profile email',
'width': 245,
'height': 40,
'longtitle': true,
'theme': 'dark',
'onsuccess': onSuccess,
'onfailure': onFailure
});
}
</script>
<script src="https://apis.google.com/js/platform.js?
onload=renderButton" async defer></script>
</body>
</html>
It might be straightforward to render the new Sign In With Google button in HTML using the
data-text attribute. Setting data-text="signup_with" will render a button called "Sign up with Google" as you asked.
Like the older library shown in your code snippet, the new button supports either a JavaScript callback handler or a back-end server redirect which shares the ID token credential after user sign-in.

reCAPTCHA: Cannot combine methods in JavaScript

I tried to integrate reCAPTCHA v3 to my Login form and applied all the necessary configuration combinations and examples. Here is my implementation based on Documentation page. However, I cannot pass the g-recaptcha-response value to my Java backend. I think the problem is related to combining grecaptcha and submit methods below.
index.html:
<script src="https://www.google.com/recaptcha/api.js?render=reCAPTCHA_site_key"></script>
login.vue:
<a-button class="primary g-recaptcha" <!-- added "g-recaptcha" to the class -->
#click="onSubmit">
Login
</a-button>
onSubmit() {
grecaptcha.ready(function() {
grecaptcha.execute('reCAPTCHA_site_key', {action: 'submit'})
.then(function(token) {
// I move my login block to here ---------------------------------
this.$refs.formContainer.validate((valid) => { // --> throws error
if (valid) {
const params = { email: 'test#test.com', password: '******' };
this.login(params).then((response) => {
// pass "token" value to the backend
});
}
return false;
});
// ---------------------------------------------------------------
});
});
}
},
Although I get the token value properly, the this.$refs.formContainer.validate((valid) line throws "Uncaught (in promise) TypeError: Cannot read property '$refs' of undefined" error. So, how should I combine these methods (grecaptcha.execute and my login block) properly?

Using Google One Tap in Angular

I'd like to use Google One Tap in my Angular 11 app. Following the documentation I added <script async defer src="https://accounts.google.com/gsi/client"></script> to my html and then used the following code in my app.component.html:
<div id="g_id_onload"
data-client_id="MY_GOOGLE_CLIENT_ID"
data-callback="handleCredentialResponse",
data-cancel_on_tap_outside="false">
</div>
The popup works fine, though I can't seem to log in. If I create a function handleCredentialResponse in app.component.ts, I get the following error: [GSI_LOGGER]: The value of 'callback' is not a function. Configuration ignored.
If I instead try to use the JavaScript API, Typescript throws the following error: Property 'accounts' does not exist on type 'typeof google'
What should I do to be able to using Google One Tap in Angular?
I had a similar problem when I used the HTML API approach, so I ended up using the JavaScript API instead.
Here's what I did:
First, make sure to install the #types/google-one-tap package.
As you mentioned, I'm also importing the script in my index.html file, like so:
<body>
<script src="https://accounts.google.com/gsi/client" async defer></script>
<app-root></app-root>
</body>
Now, moving on to your main component which in my case is app.component.ts, import the following first:
import { CredentialResponse, PromptMomentNotification } from 'google-one-tap';
Then, you can add this on the ngOnInit(). Make sure to read the documentation to get more details on the onGoogleLibraryLoad event:
// #ts-ignore
window.onGoogleLibraryLoad = () => {
console.log('Google\'s One-tap sign in script loaded!');
// #ts-ignore
google.accounts.id.initialize({
// Ref: https://developers.google.com/identity/gsi/web/reference/js-reference#IdConfiguration
client_id: 'XXXXXXXX',
callback: this.handleCredentialResponse.bind(this), // Whatever function you want to trigger...
auto_select: true,
cancel_on_tap_outside: false
});
// OPTIONAL: In my case I want to redirect the user to an specific path.
// #ts-ignore
google.accounts.id.prompt((notification: PromptMomentNotification) => {
console.log('Google prompt event triggered...');
if (notification.getDismissedReason() === 'credential_returned') {
this.ngZone.run(() => {
this.router.navigate(['myapp/somewhere'], { replaceUrl: true });
console.log('Welcome back!');
});
}
});
};
Then, the handleCredentialResponse function is where you handle the actual response with the user's credential. In my case, I wanted to decode it first. Check this out to get more details on how the credential looks once it has been decoded: https://developers.google.com/identity/gsi/web/reference/js-reference#credential
handleCredentialResponse(response: CredentialResponse) {
// Decoding JWT token...
let decodedToken: any | null = null;
try {
decodedToken = JSON.parse(atob(response?.credential.split('.')[1]));
} catch (e) {
console.error('Error while trying to decode token', e);
}
console.log('decodedToken', decodedToken);
}
I too had the same problem in adding the function to the angular component.
Then i found a solution by adding JS function in appComponent like this:
(window as any).handleCredentialResponse = (response) => {
/* your code here for handling response.credential */
}
Hope this help!
set the div in template to be rendered in ngOnInit
`<div id="loginBtn" > </div>`
dynamically inject script tag in your login.ts as follows
constructor(private _renderer2: Renderer2, #Inject(DOCUMENT) private _document: Document){}
ngAfterViewInit() {
const script1 = this._renderer2.createElement('script');
script1.src = `https://accounts.google.com/gsi/client`;
script1.async = `true`;
script1.defer = `true`;
this._renderer2.appendChild(this._document.body, script1);
}
ngOnInit(): void {
// #ts-ignore
window.onGoogleLibraryLoad = () => {
// #ts-ignore
google.accounts.id.initialize({
client_id: '335422918527-fd2d9vpim8fpvbcgbv19aiv98hjmo7c5.apps.googleusercontent.com',
callback: this.googleResponse.bind(this),
auto_select: false,
cancel_on_tap_outside: true,
})
// #ts-ignore
google.accounts!.id.renderButton( document!.getElementById('loginBtn')!, { theme: 'outline', size: 'large', width: 200 } )
// #ts-ignore
google.accounts.id.prompt();
}
}
async googleResponse(response: google.CredentialResponse) {
// your logic goes here
}
Google One Tap js library tries to find callback in the global scope and can't find it, because your callback function is scoped somewhere inside of your app, so you can attach your callback to window, like window.callback = function(data) {...}.
Also, since you are attaching it to window, it's better to give the function a less generic name.

Issue with Auth0 and javascript Lock v11

I'm trying to test a basic authentication module on my web app using auth0 and Lock v1 login form.
This is a snapshot of the code I'm using:
<script src="https://cdn.auth0.com/js/lock/11.23.1/lock.min.js"></script>
<script type="text/javascript" src="js/auth0variables.js"></script>
<script type="text/javascript" src="js/auth0app.js"></script>
<script>
$( document ).ready(function() {
console.log("start");
var lock = new Auth0Lock(AUTH0_CLIENT_ID, AUTH0_DOMAIN, {
auth: {
redirectUrl: 'undefined',
responseType: 'code',
params: {
scope: 'openid email' // Learn about scopes: https://auth0.com/docs/scopes
}
}
});
lock.show();
});
</script>
The problem is that I'm not able to get the auth0 modal since I'm getting the following error:
Uncaught TypeError: Cannot read property 'protocol' of null
at Object.getOriginFromUrl (auth0.min.esm.js:8)
at G.run (auth0.min.esm.js:8)
at $.checkSession (auth0.min.esm.js:8)
at nt.getSSOData (auth0.min.esm.js:8)
at t.getSSOData (p2_api.js:190)
at t.getSSOData (web_api.js:64)
at t.fetchFn (data.js:4)
at t.fetch (cache.js:17)
at t.get (cache.js:13)
at r (data.js:7)
I don't understand if I'm configuring in a wrong way my application on Auth0 dashboard, if I'm missing some configuration parameter calling the the Auth0Lock method or if the issue is somewhere else.
Can anybody help me with this? Thanks!
I found a workaround looking at the following discussion hosted on ath0 github repo:
https://github.com/auth0/lock/issues/1638
In order to avoid getLocationFromUrl returning null value I set the redirectUrl option in Auth0Lock constructor
<script src="https://cdn.auth0.com/js/lock/11.23.1/lock.min.js"></script>
<script type="text/javascript" src="js/auth0variables.js"></script>
<script type="text/javascript" src="js/auth0app.js"></script>
<script>
$( document ).ready(function() {
console.log("start");
var lock = new Auth0Lock(AUTH0_CLIENT_ID, AUTH0_DOMAIN, {
auth: {
redirectUrl: 'http://localhost',
//redirectUrl: 'file://',
responseType: 'code',
params: {
scope: 'openid email' // Learn about scopes: https://auth0.com/docs/scopes
}
}
});
lock.show();
});
</script>
Both redirectUrl: 'http://localhost' or redirectUrl: 'file://' options are working fine for my development purposes.

How to detect if a user is signed in on page load with Google Sign In

I'm using this simple code as shown here: https://developers.google.com/identity/sign-in/web/build-button
<script>
function renderSignInButton() {
gapi.signin2.render('my-signin2', {
'scope': 'profile',
'width': 220,
'height': 40,
'longtitle': true,
'theme': 'dark',
'prompt': 'select_account',
'onsuccess': onSignIn,
'onfailure': onSignInFailed
});
}
</script>
<script src="https://apis.google.com/js/platform.js?onload=renderSignInButton" async defer></script>
All works fine with Signing in and it remembers the sign in state when the user comes back to the page later.
PROBLEM: How do I detect when a user arrives at the page and is NOT currently signed in? (The button is rendered but the success or failure handlers never fire so I'm not clear where/how to check for the current sign in state)
I would think it should be straightforward, but the various solutions I've searched for and tried are not working.
This answer worked for me: https://stackoverflow.com/a/60084966/6281777
Only edit I made was to call window.gapi.auth2.init with no options as they conflict with the options already set by gapi.signin2.render.
So, within the onload specified here:
<script src="https://apis.google.com/js/platform.js?onload=renderSignInButton" async defer></script>
The check for not signedIn looks like this:
async function renderSignInButton() {
gapi.signin2.render('my-signin2', {
'scope': 'profile',
'width': 220,
'height': 40,
'longtitle': true,
'theme': 'dark',
'prompt': 'select_account',
'onsuccess': onSignIn,
'onfailure': onSignInFailed
});
//BEGIN CHECK IF USER IS NOT SIGNED IN
window.gapi.load('auth2', async () => {
window.auth2 = await window.gapi.auth2.init({
});
var authInstance = await window.gapi.auth2.getAuthInstance();
var signedIn = authInstance.isSignedIn.get();
if (!signedIn) {
console.log("USER IS NOT SIGNED IN");
//do stuff
}
})
//END CHECK IF USER IS SIGNED IN
}

Categories

Resources