I have a web app that needs to allow for users to book an appointment. The app loads my calander and shows a visual representation of what timeslots are available from my calander. Each timeslot available was made into a button. When the user clicks the button, it needs to set the event for that time slot. The event details are pre-made, the client doesn't do anything but click the time they want.
Ill be adding a form to accept their email and add it to the "attendees" object so that it can update their calendar.
Using the javascript quickstart, you use
gapi.load('client:auth2', () => {
gapi.client.init({
apiKey: API_KEY,
clientId: CLIENT_ID,
discoveryDocs: DISCOVERY_DOCS,
scope: SCOPES,
});
To get access to my calendar. But the rest of the quickstart
.then(() => {
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
});
function updateSigninStatus() {
gapi.auth2.getAuthInstance().isSignedIn.get();
}
Asks the user to sign into their own account using Oauth to add an event...
How do I just allow for them to add an event by clicking the timeslot button, without needing them to go through Oauth?
For visual representation of what it looks like:
The reason why it's asking the user to sign in is because your code is trying to make their account add a new event. What you probably want is to use a service account to be able to create the events without need to log in. This needs to be done in the backend, as it will contain the private key (which should never be public). This is called server to server application.
References & further reading
Using OAuth 2.0 for Server to Server Applications (Google's OAuth 2.0 Guide)
Google APIs Node.js Client (GitHub project)
I've implemented Google Calendar API. It works well. When I allow calendar integration in my app it asks for permissions to access calendars and everything works perfectly.
However, after a week or so the permissions just disappear.
api.client.init({
apiKey: API_KEY,
clientId: CLIENT_ID,
discoveryDocs: DISCOVERY_DOCS,
scope: SCOPES,
}).then((data) => {
resolve();
I can see in the network tab that the request is passing correct scopes.
But the response from Google misses the calendar scopes.
Scope sent:
scope: openid profile email https://www.googleapis.com/auth/calendar
Scope recieved:
scope: "email profile openid https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email"
The only way how to make it work again is to remove permissions to my app in the google account and start the whole process again.
It drives me crazy. I triple checked everything. Any ideas are hugely appreciated.
Some more info if it helps:
It's happening in my localhost. It's all allowed in Google API.
I use Google Firebase for auth process in my app.
I have an old-school angularJs app that has two pages. On both of the pages I include the auth0 lock script.
<script src="https://cdn.auth0.com/js/lock/11.9.0/lock.min.js"></script>
Of those two pages, one has the following js that specifies an auth0 lock to allow users to login:
new Auth0LockPasswordless(configuration.id,configuration.domain,
{
allowedConnections: ['email'],
passwordlessMethod: "link",
auth: {
redirectUrl: configuration.redirectUrl,
responseType: 'token id_token',
params: {
scope: 'openid profile email offline_access'
}
}
}).show();
and the other page is responsible for the call-back after they've clicked the link in their email.
var lock = new Auth0LockPasswordless(configuration.id, configuration.domain);
lock.on('authorization_error',
function(authResult) {
console.log("DEBUG::AUTHRESULT::", authResult);
});
lock.on('authenticated',
function(authResult) {
console.log("DEBUG::AUTHRESULT::", authResult);
});
Now I've set offline_access in the scope of the request, and on my local environment been prompted for additional permissions when authenticating (so it's making it through). However when I check the log from the lock.on('authenticated', function(authResult).. refreshToken is always null.
There's some conflicting documentation around the web, with both suggestions that lock will and wont return a refresh token. Is anyone able to confirm if this code should result in a valid refreshToken?
As #user44 said above in the comments, you shouldn't use a refresh token in a SPA (Single Page Application), as it's not a secure client and way to store it securely. Instead, use the silent authentication approach to request new access tokens.
https://auth0.com/docs/api-auth/tutorials/silent-authentication
Depending on which SDK you're using, either auth0-spa-js or auth0.js:
https://auth0.github.io/auth0-spa-js/classes/auth0client.html#gettokensilently
https://auth0.com/docs/libraries/auth0js/v9#polling-with-checksession-
(Disclaimer: I work at Auth0 as Sr. Solutions Engineer)
Update (07. May 2020):
It should be noted that Auth0 recently introduced Refresh Token Rotation https://auth0.com/docs/tokens/concepts/refresh-token-rotation, which is also supported by the Auth0 SPA SDK
I have a custom Google Sign In button in React (follows branding guidelines) that I need to implement into a web app. The android app already has Google Sign In implemented with the BE and requires the authorization code to be sent to the BE. I seem to have trouble accessing the authorization code (I can get the access token, id, and id_token fairly easily though).
I initialize as such:
static googleInit (googleSignInID) {
gapi.load('auth2', () => {
ThirdPartyLogInApi.auth2 = gapi.auth2.init({
// Retrieve the singleton for the GoogleAuth library and set up the client.
client_id: `${googleSignInID}.apps.googleusercontent.com`,
})
})
}
In my React component, I attach a click handler to a React ref (as I've seen in other stackoverflow problems).
componentDidMount () {
// element, options, success, failure
ThirdPartyLogInApi.auth2.attachClickHandler(
this.button,
{},
this.onGoogleSuccess,
this.setProcessingToFalse
);
}
In the success callback (this.onGoogleSuccess), I am able to call googleUser.getBasicProfile() to get user information and googleUser.getAuthResponse(true) to get id_token and access_token, but I need the authorization code too.
I'm at my wits end with Google's documentation on this - can someone point me in the right direction? I don't want to switch the entire auth flow to use gapi.auth2.authorize, as I do need the user information.
Thanks
EDIT: Is it even possible to access the authorization code? It seems like Google abstracts away that step and just returns the id_token right away. I just need something that looks like:
4/RQFWJLGd3sJQrgxuRaguzJy2yiUV4fAqVGftRSUYuqc
In my application, I implemented Google signout using jsapi.
I used the url https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=xxxxxx to connect to Google and then https://www.googleapis.com/plus/v1/people/xxxxxx to get user data from google profile.
Now I need to signout the user from Google while clicking a button from my application. How can I implement this in JavaScript, or at least it must ask the Google login page every time the user signs in.
I have tried approval_prompt=force, but seems not to be working.
Overview of OAuth: Is the User Who He/She Says He/She is?:
I'm not sure if you used OAuth to login to Stack Overflow, like the "Login with Google" option, but when you use this feature, Stack Overflow is simply asking Google if it knows who you are:
"Yo Google, this Vinesh fella claims that vinesh.e#gmail.com is him, is that true?"
If you're logged in already, Google will say YES. If not, Google will say:
"Hang on a sec Stack Overflow, I'll authenticate this fella and if he can enter the right password for his Google account, then it's him".
When you enter your Google password, Google then tells Stack Overflow you are who you say you are, and Stack Overflow logs you in.
When you logout of your app, you're logging out of your app:
Here's where developers new to OAuth sometimes get a little confused... Google and Stack Overflow, Assembla, Vinesh's-very-cool-slick-webapp, are all different entities, and Google knows nothing about your account on Vinesh's cool webapp, and vice versa, aside from what's exposed via the API you're using to access profile information.
When your user logs out, he or she isn't logging out of Google, he/she is logging out of your app, or Stack Overflow, or Assembla, or whatever web application used Google OAuth to authenticate the user.
In fact, I can log out of all of my Google accounts and still be logged into Stack Overflow. Once your app knows who the user is, that person can log out of Google. Google is no longer needed.
With that said, what you're asking to do is log the user out of a service that really doesn't belong to you. Think about it like this: As a user, how annoyed do you think I would be if I logged into 5 different services with my Google account, then the first time I logged out of one of them, I have to login to my Gmail account again because that app developer decided that, when I log out of his application, I should also be logged out of Google? That's going to get old really fast. In short, you really don't want to do this...
Yeh yeh, whatever, I still want to log the user out Of Google, just tell me how do I do this?
With that said, if you still do want to log a user out of Google, and realize that you may very well be disrupting their workflow, you could dynamically build the logout url from one of their Google services logout button, and then invoke that using an img element or a script tag:
<script type="text/javascript"
src="https://mail.google.com/mail/u/0/?logout&hl=en" />
OR
<img src="https://mail.google.com/mail/u/0/?logout&hl=en" />
OR
window.location = "https://mail.google.com/mail/u/0/?logout&hl=en";
If you redirect your user to the logout page, or invoke it from an element that isn't cross-domain restricted, the user will be logged out of Google.
Note that this does not necessarily mean the user will be logged out of your application, only Google. :)
Summary:
What's important for you to keep in mind is that, when you logout of your app, you don't need to make the user re-enter a password. That's the whole point! It authenticates against Google so the user doesn't have to enter his or her password over and over and over again in each web application he or she uses. It takes some getting used to, but know that, as long as the user is logged into Google, your app doesn't need to worry about whether or not the user is who he/she says he/she is.
I have the same implementation in a project as you do, using the Google Profile information with OAuth. I tried the very same thing you're looking to try, and it really started making people angry when they had to login to Google over and over again, so we stopped logging them out of Google. :)
You can log out and redirect to your site:
var logout = function() {
document.location.href = "https://www.google.com/accounts/Logout?continue=https://appengine.google.com/_ah/logout?continue=http://www.example.com";
}
For me, it works (java - android)
void RevokeAcess()
{
try{
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("https://accounts.google.com/o/oauth2/revoke?token="+ACCESS_TOKEN);
org.apache.http.HttpResponse response = client.execute(post);
}
catch(IOException e)
{
}
CookieManager.getInstance().removeAllCookie(); // this is clear the cookies which tends to same user in android web view
}
You have to call this function in AsyncTask in android
To logout from the app only but not the Gmail:
window.gapi.load('auth2', () => {
window.gapi.auth2
.init({
client_id:
'<Your client id configired on google console>'
})
.then(() => {
window.gapi.auth2
.getAuthInstance()
.signOut()
.then(function() {
console.log('User signed out.');
});
});
});
I'm using above in my ReactJs code.
You can simply Create a logout button and add this link to it and it will utimately log you out from the app and will redirect to your desired site:
https://appengine.google.com/_ah/logout?continue=http://www.YOURSITE.com
just toggle YOURSITE with your website
This works to sign the user out of the application, but not Google.
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('User signed out.');
});
Source: https://developers.google.com/identity/sign-in/web/sign-in
Ouath just makes the Google instance null, hence it you out of Google. Now that's how the architecture is made. Logging out of Google, if you Logout of your app is a dirty work, but can't help if the requirement stipulates the same. Hence add the following to your signOut() function. My project was an Angular 6 app:
document.location.href = "https://www.google.com/accounts/Logout?continue=https://appengine.google.com/_ah/logout?continue=http://localhost:4200";
Here localhost:4200 is the URL of my app. If your login page is xyz.com then input that.
this code will work to sign out
<script>
function signOut()
{
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('User signed out.');
auth2.disconnect();
});
auth2.disconnect();
}
</script>
I hope we can achieve this by storing the token in session while logging in and access the token when he clicked on logout.
String _accessToken=(String)session.getAttribute("ACCESS_TOKEN");
if(_accessToken!=null)
{
StringBuffer path=httpRequest.getRequestURL();
reDirectPage="https://www.google.com/accounts/Logout?
continue=https://appengine.google.com/_ah/logout?
continue="+path;
}
response.sendRedirect(reDirectPage);
It looks like Google recently broke something with their revoke stuff (it's started returning 400 errors for us). You now have to call
auth2.disconnect();
In our case we then have to wait a couple of seconds for the disconnect call to complete otherwise the sign-in code will re-authorise before it's done. It'd be good if google returned a promise from the disconnect method.
If any one want it in Java, Here is my Answer, For this you have to call Another Thread.
1. Try this code, if you are using onSignIn() function
2.
<script src="https://apis.google.com/js/platform.js?onload=onLoad" async defer></script>
<script>
function signOut() {
onLoad();
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('User signed out.');
if(auth2.isSignedIn)
{
auth2.isSignedIn.set(false);
}
});
}
function onLoad() {
gapi.load('auth2', function() {
gapi.auth2.init();
});
}
</script>