Google OAuth consent form won't let me submit for verification - google-oauth

I have a project in Google Cloud Platform that uses OAuth 2.0 and a few scopes from Google. All was working well until recently when I noticed my users were seeing "App is not verified" when logging in with Google.
Visiting the OAuth consent form at https://console.cloud.google.com/apis/credentials/consent, I could see that it wanted me to enter new privacy and terms & conditions URLs, which I did. But clicking on Submit For Verification and going through the subsequent popup resulted in no feedback.
Looking in devtools, I could see that the call to the submitReview endpoint was resulting in this:
{
"error": {
"code": 400,
"message": "Request contains an invalid argument.",
"status": "INVALID_ARGUMENT"
}
}
The request body sent by the Google form was:
{"brandId":"XXXXXXXXXXXXXX","scopeRationale":"My rationale was here","additionalInfo":"","contactEmail":"email#domain.com","pendingScopes":[]}
Note that pendingScopes was actually empty (I'm not requesting any new scopes).
Any ideas?

If you've never been to the new OAuth consent screen configuration before, you need to add all the scopes your app is requesting: https://support.google.com/cloud/answer/6158849?hl=en#userconsent

Related

How to authenticate Google Sheets API using OAuth 2.0 from Postman/PowerAutomate(MS Flow)?

I am new to Google Suit. As part of a requirement, we are trying to access Google Sheets from Microsoft Flows (Power Automate) using HTTP call. I have the details to access Google Sheets API such as client_id, client_secret and redirect_uri. It would be if any thoughts on the approach to achieve the authentication with the above details.
Scenario: We have some Google Sheets which holds data to be READ and WRITE Back.
I have tried calling Google Token API with below details, but getting an error
Error 400: invalid_request
Required parameter is missing: response_type
Our main goal is to bypass user consent and authenticate Google APIs using client id and secret and perform the required actions on the data.
Steps performed to authenticate the Google API
Method: Get
URL: https://accounts.google.com/o/oauth2/auth
Headers:
{
"client_id": "xxxxxxxxxxx-xxxxx0r0e4oe1dllujkiejtm7ii42jqk.apps.googleusercontent.com",
"redirect_uri": "https://console.cloud.google.com",
"response_type": "code",
"scope": "https://www.googleapis.com/auth/spreadsheets",
"access_type": "offline",
"prompt": "none"
}
I am following https://developers.google.com/identity/protocols/oauth2/web-server#httprest as a reference.
Your formatting the request wrong. The first call is a http get you just place it in a browser window
https://accounts.google.com/o/oauth2/auth?client_id={clientid}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope={scopes comma separated}&response_type=code
It will display the consent screen to the user. All parameters form a query string. They are not sent as headers there is nothing in the docs that says it should be sent as headers.
Useful links:
Google 3 Legged OAuth2 Flow
Understanding Google OAuth 2.0 with curl
The Discovery document

Login with Auth0 was successful but still a 401 'access denied' is returned?

I managed to get Auth0 somewhat working for my Vue.js app. The Quickstart Guide was straight forward.
So what happened is that I managed to use the login functionality and was prompted with the Auth0 Login dialog. I used my google account to do a quick-login. That also worked. My google account was now visible as a new user in my Auth0 Dashboard.
However after the login I was returned to my Vue.js app but the authorization was not successful it seems.
The network tab tells me the following:
{"error":"access_denied","error_description":"Unauthorized"}
I was wondering if I have to give the user some roles or permissions before he is considered as 'authorized'? My impression was that this will be true by default and only restricted if I start defining roles in the Auth0 Dashboard.
Please enlighten me!
PS: I am using the non-implict login dialog provided by Auth0 while I am working on a SPA. I read that might cause troubles?
PS 2:
And the Raw Data of the 'Failed Exchange' Log:
{
"date": "2020-08-24T10:43:52.005Z",
"type": "feacft",
"description": "Unauthorized",
"connection_id": "",
"client_id": "<Client_ID>",
"client_name": null,
"ip": "85.197.56.111",
"user_agent": "Chrome 83.0.4103 / Linux 0.0.0",
"details": {
"code": "*************T8a"
},
"hostname": "alemanni-game.eu.auth0.com",
"user_id": "",
"user_name": "",
"log_id": "90020200824104353383000015217913666506642073534760747026",
"_id": "90020200824104353383000015217913666506642073534760747026",
"isMobile": false
}
I had this issue and was finally able to find out the cause of this issue. I came across this question while I was searching for the solution to this problem but it hadn't been answered. As I was able to solve the problem, so I decided to answer this question.
In my case, the problem was that the token endpoint was returning the status code of 401 with unauthorized/access denied error and this seems to be the problem in your case too.
Problem was because of the incorrect value of "Token Endpoint Authentication Method" in the application settings.
In the case of single page applications, its value should be "None" but it was incorrectly set to "POST".
It seems that we cannot change its value, so I just created a new application and selected "Single Page Web Applications" as the application type. This solved the issue.

invalidAudienceUri error when list files in OneDrive for Business

My Registered Application uses the REST API to synchronize files with "OneDrive for Business". It worked for a year, but recently, my customer reported an error when syncing with "OneDrive for Business". It responds with an error when my app lists or uploads files to it.
For example, listing files in "OneDrive for Business":
https://mydomain-my.sharepoint.com/_api/v2.0/me/drive/items/root/children?select=id,name,size,deleted,folder,file,parentReference,lastModifiedDateTime
"OneDrive for Business" returns the following error:
{
"error": {
"innerError": {
"code":"invalidAudienceUri"
},
"code": "unauthenticated",
"message": "Invalid audience Uri 'https://api.office.com/discovery/'."
}
}
My application has logged correctly into "OneDrive for Business" by OAuth2 and added the authentication header correctly.
Could someone tell me what the cause of the error, how to avoid the problem?
From the hint of Brad, I have resolved the problem, but may not a beautiful way.
Here is the program steps to resolve the problem: (Sorry I have omitted the links, because I can not put too many links)
Show the OAuth2 consent dialogbox, let the user allow the application to access the OneDrive for Business, obtain the Authentication Token (AuthToken).
Use the AuthToken to get the AccessToken and RefreshToken of discovery API. Here is the help of discovery API.
Use the above AccessToken to access discovery API to get the resource URI of your account. The result is like "htts://yourdomain-my.sharepoint.com/";
Show the OAuth2 consent dialogbox AGAIN, let the user allow the application to access the OneDrive for Business, obtain the Authentication Token (AuthToken2).
Use the AuthToken2 to get the AccessToken2 and RefreshToken2 of "htts://yourdomain-my.sharepoint.com/".
Access your "OneDrive for Business" resource by AccessToken2 and RefreshToken2.
Old OneDrive for Business API need not Step4 and Step5, just use AccessToken and RefreshToken to access the resources, but new APIs need Step4 and Step5.

Exchanging code for access token fails when using Sign in with Google in Dropbox

We have an application that uses Dropbox API. When the user goes through the Dropbox OAuth 2 flow and signs-in using their email address and password, all works fine and we get the access_token. However, when the user uses the "Sign in with Google" flow in the Dropbox authorization dialog, we get back code which we then try to exchange for access token but the request fails with {"error_description": "code doesn't exist or has expired", "error": "invalid_grant"}.
Here's the steps we use:
1.
var dbx = new Dropbox.Dropbox({ clientId: clientId });
var authUrl = dbx.getAuthenticationUrl('https://www.dropbox.com/1/oauth2/redirect_receiver');
This gives us url https://www.dropbox.com/oauth2/authorize?response_type=token&client_id=...&redirect_uri=https://www.dropbox.com/1/oauth2/redirect_receiver.
2.
Open authUrl in a popup.
3.
User uses "Sign in with Google"
4.
We get a redirect to the URL below that contains the code:
https://www.dropbox.com/google/authcallback?state=...&code=...&scope=...
Now trying to exchange the code for access token with POST to https://api.dropboxapi.com/oauth2/token gives us:
{"error_description": "code doesn't exist or has expired", "error": "invalid_grant"}
The problem here is that, given the use of the Google Sign In flow, there are actually two OAuth authorization flow instances occurring; the Google Sign In flow is nested inside the Dropbox app authorization flow. Your app doesn't actually need to know about this though.
That https://www.dropbox.com/google/authcallback URL is Dropbox's redirect URL for the Google Sign In flow, and accordingly the code given there is for the Google OAuth flow, not the Dropbox OAuth flow. Attempting to use it for the Dropbox OAuth 2 flow will accordingly fail as you've seen (since it actually came from Google, not Dropbox).
You should have your app wait until your own redirect URL (in your shared code, https://www.dropbox.com/1/oauth2/redirect_receiver) is accessed, and only then take the code from there and exchange it for a Dropbox access token.

Google Purchase Status API HTTPS request

I am currently researching a way to use the Google Purchase Status API with just HTTP request calls, and I have hit a brick wall. I have an app setup with Google Play, and ownership of the Google Console account.
Basically, I just would like to check the status of a user's purchase on my server. The only information I should be using is the purchase token, product ID, and product package.
I have followed all the documentation on doing this at developer.android.com/google/play/billing/gp-purchase-status-api.html
The HTTPS request call I am attempting to make is this (product names and real strings substituted):
googleapis.com/androidpublisher/v1.1/applications/(com.product.myproduct)/inapp/(com.product.myproduct.product1)/purchases/(myproductpurchasestring)?access_token=(myaccesstokenstring)
and my response is always this:
{
"error": {
"errors": [
{
"domain": "androidpublisher",
"reason": "developerDoesNotOwnApplication",
"message": "This developer account does not own the application."
}
],
"code": 401,
"message": "This developer account does not own the application."
}
}
When polling my access token through this http request call:
googleapis.com/oauth2/v1/tokeninfo?access_token=(myaccesstokenstring)
this is my response:
{
"issued_to": "12345.apps.googleusercontent.com",
"audience": "12345.apps.googleusercontent.com",
"scope": "https://www.googleapis.com/auth/androidpublisher",
"expires_in": 3319,
"access_type": "offline"
}
So according to the documentation at https://developers.google.com/accounts/docs/OAuth2#webserver, I need to:
Authorise myself and retrieve a refreshable access token that is generated from 'Client ID for web applications' in the API access section of the Google API Console. I have done this.
Utilise this access token for google API calls in either of 2 ways: appending the string to the HTTP header 'Authorization', or as part of the HTTPS request itself with the property access_token=(mytokenstring). This part does not work for me, I always get an unauthorised message.
My question I guess would be: is it possible to use a simple HTTPS request call (without external library support) to retrieve the status of a purchased item without user interaction on backend servers?
I would really appreciate any help, most of the other threads are about how to go about getting a refresh token, but I have covered that already.
ok, I figured out my own problem with the help of a colleague. Basically, my access token was being generated under an account which wasn't linked to the project in any way. It would be safest to use the owner of the project's google account when generating the access token.
Phew!