Account sign-in details are out of date. Sign in again. (Issue after upgrade to Chrome 33) - google-chrome-app

I have been trying to follow the sample gdrive in the Google Drive API samples. I started out with Chrome 32 and the login and authorization was working well. I upgraded to Chrome 33 and now the sample fails during authorization and takes me to settings page with this error message - "Account sign-in details are out of date. Sign in again". I am already signed in to the account, but it still thinks I am not signed in. Any ideas what the problem is?

Check chrome.runtime.lastError in the getAuthToken callback. There should be an error string describing what went wrong in a little more detail.
If you're not using the default OAuth client ID and manifest "key" parameter that came with the sample, I would double check that those match up with your registration in the cloud console.

Related

Google Sign-In: "Certificate for key id xxxx not found" when using google-auth Python package

I'm maintaining a website and its mobile apps (iOS and Android). For Google Sign-In in mobile app, I'm using google-auth Python package on the server side.
Since about one month ago, I started to receive error reports related to Google Sign-In from the server side. The error message looks like the following:
Certificate for key id 728f4016652079b9ed99861bb09bafc5a45baa86 not found.
The server-side Google Sign-In authentication backend follows this document:
from google.oauth2 import id_token
from google.auth.transport import requests
# ...
try:
# The following line may raise ValueError with message:
# Certificate for key id xxxx not found.
id_info = id_token.verify_oauth2_token(google_id_token, requests.Request())
if id_info['aud'] not in VALID_CLIENT_IDS:
logger.error('Invalid aud from Google ID token: %s', id_info['aud'])
raise ValueError('Unverified audience.')
# ...
except ValueError as exc:
logger.error('Fail to verify Google ID token: %s', exc, extra={'request': request})
The error comes from the google.auth.jwt module, when verifying the Google-issued JWT against a list of Google public certificates.
Diving into the google-auth code, I can see that verify_oauth2_token() function is fetching Google public certificates from the URL https://www.googleapis.com/oauth2/v1/certs. It seems that sometimes, for some Google ID token sent from some Android phones, the key id cannot be found in that URL.
Here are some other details which might be useful:
It seems that iOS app does not have this kind of issue. From the USER_AGENT header, I can see that the error happens only in Android app (USER_AGENT=okhttp/3.11.0). And it happens only in some Android device, not all.
I was wondering if this happens only for Android phones from China (e.g. if they are connecting via a VPN). So I also checked the user IP address. But it turned out that some of those users were from Europe.
Some key id is recurring again and again in the server error logs. For example, the key id aa436c3f63b281ce0d976da0b51a34860ff960eb is seen dozens of times, from the beginning of November to now (end of Dec).
I am constantly seeing this error, several times (10 ~ 30 times) every day.
My website is running on the following environment:
OS: Linux (CentOS 7) 64-bit
Apache 2 with mod_wsgi 4.5.24
Python 3.6.7 and Django 2.1.2
google-auth version: tried both 1.3.0 and 1.6.1
As I could not reproduce this issue either with my iPhone, or with my Android phone (Huawei P20, bought in France), I am completely stuck.
But, one of my friends is having this issue now, and he bought his Android phone from Hongkong. This makes me think if it is possible that for some countries, Google Sign-In uses some different certs other than the public ones at https://www.googleapis.com/oauth2/v1/certs?
I don't think this is a bug in google-auth package. I'm wondering if any of you have ever heard of this error, and could give me a hint about the possible cause of it?
Thanks in advance!
OK, I finally figured it out. I'm posting my findings here, hoping that it could help someone else.
The server-side Python code has nothing wrong. The reason why it failed was that, the client app submitted an expired Google ID token.
Here's the fixed version of my LoginActivity:
...
#OnClick(R.id.google_sign_in_button)
void loginWithGoogle() {
//
// If user has already signed in to our app with Google, sign him out first.
//
// NOTE: This step is required, or the ID token might not pass the server-side validation!
//
// After sign-in, we need to get the user's ID token issued and signed by Google, and send
// it back to our server for validation.
//
// Google is rotating its OAuth2 certificate regularly, so an old ID token issued long time
// ago by Google might not pass the server-side validation -- if the certificate used to
// sign the ID token has expired.
//
// This may happen when user has already signed in to our app with Google. In such case,
// the ID token we get from the user's Google account is obsolete. Our server will fail to
// validate it, with the error message:
//
// Fail to verify Google ID token: Certificate for key id xxx not found.
//
// Google recommends using the `silentSignIn` method for the already-signed-in user
// (see step 2 of: https://developers.google.com/identity/sign-in/android/backend-auth).
// For the sake of simplicity, we don't do that. Instead, we go directly to step 3
// by signing user out, giving him the option to sign-in again.
//
final GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
if (account != null) {
// User has already signed in: Sign out and sign in again.
// NOTE: THIS IS THE FIX TO MY PROBLEM.
mGoogleSignInClient.signOut().addOnCompleteListener(this, new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
startGoogleSignInActivity();
}
});
} else {
// User is not yet signed in: Start the Google sign-in flow.
startGoogleSignInActivity();
}
}
private void startGoogleSignInActivity() {
final Intent intent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(intent, REQUEST_LOGIN_WITH_GOOGLE);
}
The key point is that: I need to check if user has already signed in with Google. If yes, I need to sign the user out and re-start the Sign-in-with-Google activity.
As Android has native support for Google account, I suppose the OS may cache user's Google account if user is already authenticated (in some other app or system-wide). But that cached account may probably contain an expired ID token. Forcing to sign the user out and re-sign-in will give me a fresh new ID token.
This also explains why my iOS app does not have this issue. Because iOS never caches user's Google account.

Actions on Google - Account Linking process hits Token URL before Authorize URL?

We are trying to support the 'traditional' Account Linking flow as it seems the most general purpose, gives us a chance to surface T&C's, and we thought would be most bedded in.
But testing in the Assistant mobile app for starters, it fails for most users in our Actions app in Dev - After the user sees the Google-driven pop-up in the Assistant app with the "LINK ACCOUNTS" option - They tap that option, and our authorization screen does not appear.
Actions support have had a look at our Account Linking config and can't see any problems.
A couple of test users with newer Android phones DO see our Authorization screen, but the majority do not.
If we test the Authorization URL by pasting into a browser on the same device - It always displays just fine.
What is strange - If we look in our web server logs during the failed cases, the only hits we are seeing are to our 'TOKEN URL', whereas my understanding is a newly linking user should hit our 'Authorization URL' before ever hitting Token.
The successful cases DO hit our Authorization URL first, as expected.
Feel free to pipe up if anyone can answer ANY of the following:
Any ideas what could be causing problems here?
Or ways we might investigate deeper?
Does an app need to be in Alpha testing, or anything like that before Account Linking works?
Is it normal/expected to hit the Token URL for a user that has never successfully linked accounts?
Can anyone confirm what the Token fetch response should be in that case? (Maybe we are not responding in a way that satisfies the other end)
Does anyone have a dummy/HelloWorld Account Linking web end-point we could test against? (Geeze that would be handy for the developer community!)
I don't know exactly what is going on, but there are a couple of hints about what is happening and what avenue to investigate. I'm going to assume you're doing Account Linking with OAuth only. If you are doing a combination of "Google Sign In for Assistant and OAuth", that might change some things. To address some of your questions:
What could cause the Assistant to go to the Token Endpoint instead of the Auth endpoint?
It wouldn't go to the Token Endpoint unless it already had a Token. I could think of a few possible scenarios:
If it was going to Auth, getting a token since it was already authorized, so no window would pop up. (But you indicated it isn't going to that page.)
If the account in question is already authorized to the project via some other means. You can check https://myaccount.google.com/permissions to see if it is already authorized.
If you had tested it with this account previously and it has a token from then. If so, it should be listed at https://myaccount.google.com/permissions. Probably.
If you're not using the account you think you're using on the device in question.
How to investigate this?
Once you double-check some of the more obvious things (using the right account?):
Look at what is being sent to the Token endpoint
Does the token look familiar? Is it the same between calls? Same between different accounts?
Do you log tokens being issued? Can you?
What about the other information sent along with the token such as the client_id and client_secret?
Does it need to be in Alpha?
I'm not sure. Last I checked, it did not. I do think that it no longer works in the simulator, which is annoying, but doesn't require being in Alpha.
It does make it a little more difficult to check, however, since there is no Directory page that can tell you if the account is already linked. You'll need to go to the list of linked apps for the account to remove your app if it is: https://myaccount.google.com/permissions
Is this normal?
I wouldn't think so. It shouldn't hit the Token Endpoint unless it has an auth code or refresh token to exchange. It has to have that code/token from somewhere.
How should you respond?
If you get an auth code or refresh token that is invalid, or any of the other information provided at the token endpoint doesn't match what it should, you must return HTTP error code 400 "Bad Request" and include as the body the JSON
{"error": "invalid_grant"}
This should force it to go through reauth with the user.
Is there a public test server?
Auth0 isn't exactly public, but is free for basic use, and well suited for test purposes.

Understanding Sign-in process in actions-on-google

I have a Google Assistant (Actions on Google) app where I want the user to log in. I use actions-on-google with DialogFlow which in turn has a webhook.
For a specific action where signin in required, in the webhook, I launch app.askForSignIn();
I have an intent called actions.intent.SIGN_IN which has an event called actions_intent_SIGN_IN. On this action, I check app.getSignInStatus() and I get null for this.
Am I missing something? Will Google Assistant / Actions on Google do something to extract link the token and scopes from oauth and associate it with the user?
I was able to make it work on my app but I'm not calling app.askForSignIn(), instead I've checked the option "Sign in required" on the DialogFlow integration with Google Assistant, then I provided all informations regarding client ID and secret and Authorization and Token URLs in the "Account linking" section of the App's overview on the Action on Google console.
I basically followed this guide.
PS: To make it work on the console either you have to sign in from a smartphone or call the auth URL directly in a browser window.
hi rochan i had same problem a while ago see my post its still an open issue for me. Google Actions SDK Sign-In implicit flow
But it hadnt much priority for me. What you can try is using a google assistant enabled smartphone and test there instead of inside the simulator. Maybe it works.
You have to enable the Sign in Required option in Google assistant integration settings in dialogflow
After enabling this, Use Account Linking option in the actions-on-google overview and follow the below steps
We have to enable the webhook first and we can see how to enable the webhook in the dialogflow fulfillment docs.
Open your project under google cloud console
1. Go to google cloud console -> APIsand Services -> Credentials -> OAuth 2.0 client IDs -> Web client -> Note the client ID, client secret from there
-> Download JSON - from json note down the project id, auth_uri, token_uri
-> Authorised Redirect URIs -> White list our app's URL -> in this URL fixed part is https://oauth-redirect.googleusercontent.com/r/ and append the project id in the URL
-> Save the changes
Actions on Google -> Account linking setup
1. Grant type = Authorisation code
2. Client info
1. Fill up client id,client secrtet, auth_uri, token_uri
2. Enter the auth uri as https://www.googleapis.com/auth and token_uri as https://www.googleapis.co.in
3. Save and run from google assistant on some device.
4. It will show an error while running on the google assistant, but dont worry.
5. Come back to the account linking section in the assistant settings and enter auth_uri as https://accounts.google.com/o/oauth2/auth
and token_uri as https://accounts.google.com/o/oauth2/token
6. Put the scopes as https://www.googleapis.com/auth/userinfo.profile and https://www.googleapis.com/auth/userinfo.email
and weare good to go.
7. Save the changes.
In the hosting server logs, we can see the access token value and through access token, we can get the details regarding the email address.
Append the access token to this link "https://www.googleapis.com/oauth2/v1/userinfo?access_token=" and we can get the required details in the resulting json page.
Additionally, to get the Username and email address, you can use this below snipet
accessToken = req.get("originalRequest").get("data").get("user").get("accessToken")
r = requests.get(link)
print("Email Id= " + r.json()["email"])
print("Name= " + r.json()["name"])

On trying to verify digits user on Server I am getting error code 32 “Could not authenticate you”

The server side verification is failing for me with code 32 and message "Could not authenticate you.". I have an android app where i am using digits to authenticate users using their mobile number. Inside the success callback, i follow the oauth echo tutorial and use the consumer key and secret along with auth token and secret obtained from digit session to generate an oauth signature(X-Verify-Credentials-Authorization) as well get the url to hit to verify credentials(X-Auth-Service-Provider) on the backend. I then try to do a curl request by plugging the oauth signature into Authorization header for the request as indicated in the tutorial. However i get error code 32 - could not authenticate you. Have tried with multiple numbers without any success. It would be great if anyone could indicate what i am doing wrong or provide any help in fixing this. Without this fix, i am afraid i would have to use my exisiting OTP architecture and won't be able to take advantage of this fantastic library.

Unexpected Authorization Request in Workflow C2QB WF3.0

We have a multi-tenanted/multi-domain app and we're looking at publishing on IPP. Because of the multi-domain nature our configured endpoints in the App setup are generic and users are then redirected to their specific account once their identity is established.
The issue is with C2QB WF3.0.
The test steps are:
go here: https://appcenter.intuit.com/Home/MyApps/
on the "Launch My Apps" tab, click the app
Expected Result:
the Sign In screen for the app is displayed
The requirement is:
if not still signed into the app, sign in screen is displayed
if still signed into the app, take user into the app
The issue is that the even if the user is currently logged into our application, it still requests authorization as per this message:
"domain" is requesting some information from your Intuit account
By approving this request "domain" will be able to access your:
Name
Email Address
The workflow that it is actually following is to perform a callback to our connect url. The normal way to determine which account the callback is coming from is via the realmId, but this is not received from Intuit and therefore it needs to be requested. Once a user has completed this authorization, it will not ask again. It should be noted that we're not actually requesting a name or an email address as the screen suggests.
We've been informed by Intuit that it should not request authorization and it is not part of the workflow.
We're wondering if anyone else has encountered this problem and if there is a workaround for it.
We discussed with the Engineering teams and they confirmed what Pete has mentioned above. This is not a bug and please follow the steps as Pete has mentioned.
If you want to replicate the 'access your app with appcenter flow', you have be either logged in QBO online company file in same browser session or navigate to the app via blue dot menu from your application or run your application from localhost(.net) and then go to Appcenter and login there on same tab and then click on your app.
Since your desktop application is running, your code will be hit.
You will then get the second Auth screen only for authorizing your company file. After authorization your realm will be set in a cookie and in the code you can see its value. You can replicate this behavior via firebug and see the qbn.parentid cookie value has the realm after authorization is done.