Attempting to authenticate using Google on iOS with backend server, code used to work with older google client libraries.
$client = new Google_Client();
$oauth2 = new Google_Service_Oauth2($client);
$client->setApplicationName('MyApp');
$client->setClientId($google_config["clientId"]);
$client->setClientSecret($google_config["clientSecret"]);
$client->setRedirectUri("");
$client->setDeveloperKey($google_config["developerKey"]));
Log::error("Google/authcode", $request->get('token'));
if (! isset($_SESSION['access_token'])) {
try {
$client->authenticate($request->get('token'));
} .... THROWS exception: Error fetching OAuth2 access token, message: 'invalid_grant:
Attempting to validate token against:
https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=
https://www.googleapis.com/oauth2/v2/tokeninfo?id_token=
https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=
all work successfully shows that token is valid.
EDIT:
JUST FOUND OUT after adding verifyIdToken call, that:
Invalid issuer, https://accounts.google.com != accounts.google.com seems like this is why I am getting a failure. I am guessing that iOS sdk vs PHP is setting things up differently? Or perhaps this is not relevant and is assumed that it is not authorization of the server from iOS device. Since if I keep changing things on server side code i.e. chang OAUTH2_ISSUER to be https://accounts.google.com, I would get wrong recipient error, which makes sense since I am using tokenid obtained by iOS client to authorize server.
Older version of iOS app works fine as well. But token is completely different although validates just fine as well.
Any help is greatly appreciated.
I think I misunderstood documentation. In order to authorize server one needs to pass googleUser.serverAuthCode from
- (void)signIn:(GIDSignIn *)signIn didSignInForUser:(GIDGoogleUser *)googleUser
withError:(NSError *)error { ....
If only validating backend server with authorized on iOS side user googleUser.authentication.accessToken to the server which in turn would need to be validated or parsed on the server to get email and other data.
Related
I'm currently developing an Single Page Application (SPA) that is attempting to implement EPIC's Standalone Launch with Dynamic Registration. I am currently stuck on the step that requires the SPA to register itself at the https://fhir.epic.com/interconnect-fhir-oauth/oauth2/register endpoint with a JSON Web Key Set. Every time I do this, I get a response back:
{
"error": "invalid_client_metadata",
"error_description": null
}
The request I'm sending looks like the following:
POST https://fhir.epic.com/interconnect-fhir-oauth/oauth2/register
Content-type: application/json
Authorization: Bearer <redacted>
{
"software_id":"<sandbox-id>",
"jwks":{
"keys":[
{
"e":"AQAB",
"kty":"RSA",
"n":"tK2-...<redacted>...Q93sc",
"kid":"1"
}
]
}
}
I'm generating private/public key pairs using WebCrypto and I've verified that the JWKS of the public key I'm sending over is valid (I have tested signing and verifying jwt's using WebCrypto and validated them on jwt.io)
I've created a minimal reproduction repo on github that shows this issue. I've also deployed that repo so you can see the issue yourself.
To walk through the steps, I've been able to successfully do the following:
1: Request an Authorization Code
2: Exchange the Authorization Code for an Access Token
I am currently stuck on specifically using the Access Token and registering my SPA via the /oauth2/register endpoint. I know that the Access Token I'm receiving back is valid as I can access other protected FHIR endpoints using it. I've tried making the request both in a browser and in Postman, neither seem to work.
I am starting to wonder if anyone has ever been able to successfully register using the dynamic registration endpoint before? Searching google and stack overflow for this specific issue returns nothing.
Couple of things to try:
In web-crypto.ts, you have the hash in the config set like this: hash: "SHA-384". Per the docs, it seems it should be this instead: hash: { name: "SHA-384" }.
If that doesn't work, try bumping down the key length to 2048.
Also, this isn't causing your issue but fyi that your scope parameter in the /authorize call is invalid. Valid scopes are openid and fhirUser (can include both separated by a space).
The issue I’m facing is I’m trying to manually get the token from the API for the sake of automation. What I did is I configured IdentitySever to grant token on user credentials it worked fine when request has been sent via OAuth UI:
I’m getting the following request/response (viewed in console):
Now the issue is that I’m sending the exact same request but manually, but it fails:
I'm getting 'invalid_client' error instead of Token
I'm not overriding IResourceOwnerPasswordValidator so I'm using default implementation.
Anything else that I’m missing? Does UI do something else under the hood? Did I miss something?
The requests are identical, I copied over clients, passwords etc in case anything is different.
I’ve also tried to do the token request via get+query string, but same result
I tried changing the clientid, clientsecret, but no luck so far
There's a typo in your manual request. It should be 'client_secret' but not 'cliend_secret'.
OAuth2 doesn't understand this field and as a result of this, it assumes that you didn't pass the secret of the client in the request and thus it throws an 'invalid_client' error.
I have been successfully using Google API (via HTTP/REST, as well as using the .NET client library) with a Google Service Account to access the files in Google Drive.
Recently, I am exploring the Fusion Tables. I am able to use the API with user authorization via a web application. However, when I try to access it using Google Service Account under the same project, it failed with the below error, whenever I have https://www.googleapis.com/auth/fusiontables in the scope:
https:// www.googleapis.com/oauth2/v3/token
HTTP 401
{"error": "unauthorized_client", "error_description": "Unauthorized client or scope in request." }
The error goes away, when I remove https:// www.googleapis.com/auth/fusiontables and the same code block works fine with https://www.googleapis.com/auth/drive and other scopes.
I have checked and confirmed the "Fusion Tables API" is already enabled for my project at Google Developers Console. (Otherwise, my user authorization via a web application would not be working at the first place.)
Is there anything which I could have missed out? Any help would be greatly appreciated.
I just come across this:
Google drive service account and "Unauthorized client or scope in request"
Even though it does not seems to be related at the first glance, it is indeed the same issue.
Problem resolved after removing User = svcAcct, from the below code block.
ServiceAccountCredential credential;
credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(svcAcct) {
// User = svcAcct, *** removed ***
Scopes = new System.Collections.Generic.List<string>(scopes.Split(' '))
}.FromCertificate(certificate)
);
Hence, here is the general advise:
DO NOT call ServiceAccountCredential.Initializer with User = svcAcct unnecessarily.
Only do this when you are trying to impersonating a difference user
(with the condition that the appropriate setup has been correctly done
in Google Apps Admin Console).
Even though it may not produce any error under certain cases, there
are some unexpected behaviors when including an email address of the
service account itself in the JWT claim set as the value of the "sub"
field.
I use this script:
https://developers.google.com/youtube/v3/code_samples/php#resumable_uploads
to upload videos to youtube. Everything works fine, but next day I have error:
An client error occurred: The OAuth 2.0 access token has expired, and a refresh token is not available. Refresh tokens are not returned for responses that were auto-approved.
I looked at some tips on how to fix this but I did not succeed. I am new to programming. Please help me fix this error.
You need to set the access type to offline which allows you to refresh the access token so you can authenticate the app without the user having to give authorization again.
Check the docs.
I can't test this now, but try the following. This isn't ideal though, you should be persisting the token somewhere.
// After "$client->setRedirectUri($redirect);" add:
$client->setAccessType('offline');
// After "$client->setAccessToken($_SESSION['token']);" add:
if ($client->isAccessTokenExpired()) {
$currentTokenData = json_decode($_SESSION['token']);
if (isset($currentTokenData->refresh_token)) {
$client->refreshToken($currentTokenData->refresh_token);
}
}
I know same question has been asked many times but even after following each and every post as well trying various suggestions, I am still facing invalid_request error.
I am able to get code successfully from Google API and when I am trying to access accessToken , I am getting this error and HTTP code being sent from Google API is 400.
I have already tried and compared my data with oauthplayground and seems everything is same
Following data is being sent from my Application to Google API
https://accounts.google.com/o/oauth2/auth?
scope=openid+profile+email
&response_type=code
&redirect_uri=http%3A%2F%2Fsavealifetoday.org%2Fblood_donors%2FoAuthCallBackAction%3Fservice_provider_name%3D
&approval_prompt=force
&client_id=193214746340-ea0nq5alpst82n2fno13s9j21pn4f4pf.apps.googleusercontent.com
Access Token URL
https://accounts.google.com/o/oauth2/token?
scope=openid+profile+email
&client_secret=***********
&grant_type=authorization_code
&redirect_uri=http%3A%2F%2Fsavealifetoday.org%2Fblood_donors%2FoAuthCallBackAction%3Fservice_provider_name%3D
&code=4%2F8veoAnihzkao58oWvZaRShn5nhYg.0to7Or-lHPwRXE-sT2ZLcbTblHXFhgI
&client_id=193214746340-ea0nq5alpst82n2fno13s9j21pn4f4pf.apps.googleusercontent.com
But When Application is trying to fetch data over the network, I am getting exception
SEVERE: Error while fetching access token for Google..
OAuthProblemException{error='invalid_request', description='null', uri='null', state='null', scope='null', redirectUri='null', responseStatus=0, parameters={}}
I am using URLConnectionClient to establish network connection
Go through the OAuth flow using the OAuth playground https://developers.google.com/oauthplayground/.
Then compare what is being sent with your own.
Note that it needs to be an HTTP POST. The code you posted looks like a GET.
Also, your redirect URL looks a little odd. Is that exactly the same URL that you registered in the API console? This is isn't your current error, but will probably become your next one ;-)
It seems that you forgot to send 'state' parameter here (it is mandatory!):
https://accounts.google.com/o/oauth2/auth?
scope=openid+profile+email
&response_type=code
&redirect_uri=http%3A%2F%2Fsavealifetoday.org%2Fblood_donors%2FoAuthCallBackAction%3Fservice_provider_name%3D
&approval_prompt=force
&client_id=193214746340-ea0nq5alpst82n2fno13s9j21pn4f4pf.apps.googleusercontent.com
In Java code you can generate it in a way like this:
String state = new BigInteger(130, new SecureRandom()).toString(32);
So you request should look like this:
https://accounts.google.com/o/oauth2/auth?
scope=openid+profile+email
&response_type=code
&redirect_uri=http%3A%2F%2Fsavealifetoday.org%2Fblood_donors%2FoAuthCallBackAction%3Fservice_provider_name%3D
&approval_prompt=force
&client_id=193214746340-ea0nq5alpst82n2fno13s9j21pn4f4pf.apps.googleusercontent.com
&state= {insert_here_generated_state}
And also I don't know if it is necessary to send a 'scope' parameter in "Access Token URL".