Google oauth2.0 405 error - oauth

Im trying to use google oauth using the below link but get a 405 error,
Can you please let me know if the parameters are correct?
client_id = changed to a diff value
response_type = code
scope= openid%20email
redirecturl = given the value based on what I registered in console.developers.com
login_hint = my gmail id..
https://accounts.google.com/o/oauth2/token?
client_id=690178314820-85fvo4eq56se4mppdaf0pt6tnnjo552&
response_type=code&
scope=openid%20email&
redirect_uri=http://test.webfactional.com&
state=security_token%3D138r5719ru3e1%26url%3Dhttps://oa2cb.example.com/myHome&
login_hint=myemail#gmail.com
I made the above get requests in the browser..

There are a few steps to getting access to Google its easer for me to show you the full flow. My guess is you are stuck on step two because your not sending it as a post.
Step 1: Ask for access
https://accounts.google.com/o/oauth2/auth?client_id={clientid}.apps.googleusercontent.com&redirect_uri={From console}&scope=openid%20email&response_type=code
This just displays the window asking them to approve you. Once the user has approved access you get a one time Authentication Code.
Step 2: Exchange Authentication Code for AccessToken and RefreshToken. Note this needs to be sent as a HTTP POST not a HTTP Get.
https://accounts.google.com/o/oauth2/token
code={Authentication Code from step 1}&client_id={ClientId}.apps.googleusercontent.com&client_secret={ClientSecret}&redirect_uri=={From console}&grant_type=authorization_code
you should get a JSon string back looking something like this.
{
"access_token" : "ya29.1.AADtN_VSBMC2Ga2lhxsTKjVQ_ROco8VbD6h01aj4PcKHLm6qvHbNtn-_BIzXMw",
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : "1/J-3zPA8XR1o_cXebV9sDKn_f5MTqaFhKFxH-3PUPiJ4"
}
Now you can take that Access_token and use it to make your requests. But access tokens are only good for 1 hour and then they expire before that time you need to use the Refresh_token to get a new access token. Also if you are going to want to access your users data again you should save the refresh_token some place that will enable you to always access there data.
Step 3: Use Refreshtoken
https://accounts.google.com/o/oauth2/token
client_id={ClientId}.apps.googleusercontent.com&client_secret={ClientSecret}&refresh_token={RefreshToken from step 2}&grant_type=refresh_token
This time you will only get the Access token back, because your refreshtoken is good until the user removes authentication or you haven't used it for 6 months.
{
"access_token" : "ya29.1.AADtN_XK16As2ZHlScqOxGtntIlevNcasMSPwGiE3pe5ANZfrmJTcsI3ZtAjv4sDrPDRnQ",
"token_type" : "Bearer",
"expires_in" : 3600
}
You can find more detailed information on this here Google 3 Legged oauth2 flow

It seems you are using wrong api, you should use https://accounts.google.com/o/oauth2/auth instead of https://accounts.google.com/o/oauth2/token.
The reason you get error 405 is https://accounts.google.com/o/oauth2/token can only be called by POST, and it is to get token. You need to get authorization code first and then exchange it for a token.

Please pay attention for this /oauth2/v3/token and /oauth2/token
I do follow guide of google at this link
It show me following
obtain Authentication Code by /o/oauth2/auth => it work, the response as example in the guide
obtain access token by /oauth2/v3/token => it is error, the status code 405 is responsed
The correct must be /oauth2/token

Related

Request had invalid authentication credentials. Expected OAuth 2 access token error

I need to read and import google people contacts but I get the following error:
"Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project."
"status": "UNAUTHENTICATED"
This is the script (classic asp) I am using:
StrURL="https://people.googleapis.com/v1/people/get"
ApiKey="my api key"
Set objXMLHTTP = CreateObject("Msxml2.ServerXMLHTTP.6.0")
objXMLHTTP.Open "GET", StrURL, False
On Error Resume Next
objXMLHTTP.setRequestHeader "Authorization", "Bearer " & ApiKey
If Err.Number<>0 Then Response.Write "Error:" & Err.Description & "<br>"
On Error GoTo 0
objXMLHTTP.send
content = CStr(objXMLHTTP.ResponseText)
statuscode = objXMLHTTP.Status
How can I get the token using classic asp? Can anyone help me?
objXMLHTTP.setRequestHeader "Authorization", "Bearer " & ApiKey
You appear to be sending an api key. An api key is not a bearer token. Api keys only grant you access to public data, not private user data.
In order to access private user data you need to request authorization from that user to access that data that is done using Oauth2
Once you have been grated consent of the user to access their data you will have an access token. This access token can then be sent to the api in the authorization header.
I haven't used asp classic in years. These videos may help you understand how to make the authorization request.
Google 3 Legged OAuth2 Flow
How to create web app credetinals
Understanding oauth2 with curl

OAuth1 reject_token 401 unauthorized

Get Access Token request of OAuth1.0 only work once for Magento1.9 after being redirected back from Authorization URL. Next time when requesting for Access Token I get reject_token.
What I noticed there is difference in signature of both objects' signature.
Request 1(successful):
OAuth::Consumer.new(consumer_data)
OAuth::RequestToken.from_hash(some_hash)
request_token.get_access_token(oauth_verifier: 'asdfasdagbadbv')
with signature having
oauth_nonce=\"iIHmN7obLeONSitOxFFZQI71v0k4mAsEFLFen0Lw\",
oauth_signature=\"lwj0n1AK3VJLdaXHIWEOFlYp5qc%3D\"
Request 2(unsuccessful):
OAuth::Consumer.new(consumer_data)
OAuth::RequestToken.from_hash(some_hash)
request_token.get_access_token(oauth_verifier: 'asdfasdagbadbv')
with signature having
oauth_nonce=\"KciY4tiiPDu1u029Nbdu1C325svchfESTYV1l8mvw\",
oauth_signature=\"KciY4tiiPt5Du1u029Nbdu1CzCHzvc%3D\"
This may be or may not be the issue but this is the only difference I found so far in both requests.
Please someone help me in updating oauth_nonce and signature or devise some other solution.
The problem is in the second line.
request_token.get_access_token(oauth_verifier: 'asdfasdfa')
According to Auth documentation request token should be used one time. Request token expires once we use them. You are using expired request token in the second call which causes reject_token 401 unauthorized.
Solution
Actually, request tokens are used to generate Access Token. Access Tokens can be used multiple times. So what you need is to store Access Token somewhere, generated in first request_token.get_access_token(oauth_verifier: 'asdfasdfa') line. Then you can use saved access token in the reset of your API calls. The syntax of using access token is the following:
#consumer = OAuth::Consumer.new(...)
#token = OAuth::Token.new('ACCESS_TOKEN', 'ACCESS_TOKEN_SECRET') // saved access token and secret here
#consumer.request(:post, '/people', #token, {}, #person.to_xml, { 'Content-Type' => 'application/xml' })

Authentication session is not defined

I try to use Google Photos API to upload my images, base on the steps of the following link.
https://developers.google.com/photos/library/guides/upload-media
After following the Using OAuth 2.0 for Web Server Applications, I just get the Oauth2.0_token response(a JSON format with access_token, refresh_token...). However, after I put this token string with "Bearer " into request headers, the response is error 401, the error message is "code 16 Authentication session is not defined".
I cannot find any information to deal with it, thank for any help.
You probably have incorrect permissions. Make sure you request the token with the appropriate scope. For write-only access you need 'https://www.googleapis.com/auth/photoslibrary.appendonly'
src: https://developers.google.com/photos/library/guides/authentication-authorization#what-scopes
One reason this might be happening is that you initially authorized your user for read-only access. If you went through the authorization flow with a .readonly scope, your bearer token reflects that authorization (and the token is retained in your credentials file). If you change your scope but don't get a new auth token you will get this error when trying to upload. Simply redo the authorization flow with the new scope defined:
SCOPES = 'https://www.googleapis.com/auth/photoslibrary'
store = file.Storage('path_to_store')
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('google_credentials.json', SCOPES)
creds = tools.run_flow(flow, store)
and your store will be populated with a new token that can be used for uploading.
You say you "just get the Oauth2.0_token response(a JSON format with access_token, refresh_token...)" and "put this token string with "Bearer " into request headers".
Unfortunately documentation on this isn't super clear in a lot of places. What you are supposed to provide after "Bearer" is the "access_token" field only, not the entire JSON string with all the token fields in it. For reference, this is a single string of random looking characters which probably starts with "ya29." and is pretty long - in my case it's 170 characters.

Can't deploy an app to Intune store via graph API - DeviceManagementApps.ReadWrite.All is an invalid scope?

We want to enable uploading apps to the Intune store via an API.
I saw this example on GitHub, and want to do something similar in JS, so I've tried using the same REST calls.
The problem is, I can't seem to make the https://graph.microsoft.com/beta/deviceAppManagement/mobileApps request properly - I always get 401. When making the same request via the Graph API Explorer it works fine.
I tried fixing my permissions, and I'm kinda stuck getting the correct token.
I did the following steps with an admin account, on both the "common" and our own tennant:
Called the admin consent - https://login.microsoftonline.com/nativeflow.onmicrosoft.com/adminconsent?client_id=<ID>&redirect_uri=<URI>
Got authorization from the user - https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=<ID>&response_type=code&redirect_uri=<URI>&response_mode=query&scope=DeviceManagementApps.ReadWrite.All
POST request to get the actual token -
https://login.microsoftonline.com/nativeflow.onmicrosoft.com/oauth2/v2.0/token
with the following body:
client_id: <ID>
scope: https://graph.microsoft.com/.default
client_secret: <secret>
grant_type: client_credentials
requested_token_use: on_behalf_of
code: <The code I got in step 2>
I tried changing the scope in step 3 to https://graph.microsoft.com/DeviceManagementApps.ReadWrite.All or simply to DeviceManagementApps.ReadWrite.All, but it says that it's not a valid scope.
I got a token in step 3, but when I try calling the actual API I receive this error:
{
ErrorCode:"Forbidden",
Message:{
_version: 3,
Message: "An error has occurred - Operation ID (for customer support): 00000000-0000-0000-0000-000000000000 - Activity ID: 7b5c3841-976d-4509-b946-f7fdabd047d7 - Url: https://fef.msub02.manage.microsoft.com/StatelessAppMetadataFEService/deviceAppManagement/mobileApps?api-version=5018-05-02",
CustomApiErrorPhrase: "",
RetryAfter: null,
ErrorSourceService: "",
HttpHeaders: {"WWW-Authenticate":"Bearer realm=urn:intune:service,f0f3c450-59bf-4f0d-b1b2-0ef84ddfe3c7"}
},
Target:null,
Details:null,
InnerError:null,
InstanceAnnotations:[]
}
So yeah, I'm pretty much stuck. Anyone have any experience with it? I've tried making the calls in Postman, curl and via code, but nothing works.
Cheers :)
You have a couple issues going on:
You're using the Authorization Code Grant workflow but requesting Client Credentials.
The scope Device.ReadWrite.All is an application scope, it is only applicable to Client Credentials. It isn't a valid Delegated scope so it will return an error when you attempt to authenticate a user (aka delegate) using Device.ReadWrite.All.
Your body is using key:value but it should be using standard form encoding (key=value).
To get this working, you need to request a token without a user. This is done by skipping your 2nd step and moving directly to retrieving a token (body line-breaks are only for readability):
POST https://login.microsoftonline.com/nativeflow.onmicrosoft.com/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
client_id={id}
&client_secret={secret}
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&grant_type=client_credentials

Migrating from YouTube ClientLogin to OAuth 2.0

I have an app that uploads Video to YouTube to a specific YouTube channel (meaning, not to any individual user's channel, but to a single channel, for which I have the Username and Password).
In the ClientLogin my server-side process provided YouTube with the U/P and everything moved ahead. However, that's being deprecated and I'm looking to upgrade to OAuth 2.0 (as per their recommendation), however, the documentation insists on there being a redirect URI, for when the user has logged in. It doesn't seem to explain how to bypass the user login (since the user has nothing to log into, or any credentials to log in *with... the app is designed to take their video and upload it to OUR channel). So, what I need is to bypass the user being asked anything, and for YouTube to simply take my channel credentials and give me back the token for me to do the upload with.
I realize that this is a totally standard and non-controversial procedure, so I *MUST be missing something obvious, but I just can't suss out what that is.
So, my question is, how do I skip the user dialog-> redirect and just provide youtube with credentials for it to accept and then upload my video in OAuth 2.0?
What I'm really after is to do follow the DirectUpload approach here:
https://developers.google.com/youtube/2.0/developers_guide_protocol#AuthSub_Authentication_Flow
And to have retrieved the user Token silently behind the scenes.
TIA
There really is no way (that I've found) to completely bypass visiting an external page to authorize the OAuth2.0 access.
The closest I have come is to create an "Installed Application" project on code.google.com/apis/console and use the device methodology.
You will receive a Client ID and Client Secret. These will be used later.
Ideally you would generate a developer key, though I don't believe this to be required at this time, through code.google.com/apis/youtube/dashboard/
I use JSON notation for headers and responses, it should be easy to adapt to your language of choice.
First make a POST request to accounts.google.com/o/oauth2/device/code with the headers
{
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': post_data.length,
'X-GData-Key': 'key=YOUR_DEVELOPER_KEY'
}
and the data containing:
{
client_id: 'YOUR_CLIENT_ID',
scope: 'https://gdata.youtube.com'
}
where YOUR_CLIENT_ID is the client ID you obtained for the google apis project you set up earlier.
You will get a response like this:
{
"device_code" : "4/Pj8m71w5XuEMTT0ZwOJVgvlTfF4Q",
"user_code" : "5wtw67wm",
"verification_url" : "http://www.google.com/device",
"expires_in" : 1800,
"interval" : 5
}
If you don't visit www.google.com/device (defined by the "verification_url" field) within 30 minutes (1800 seconds per the "expires_in" response field), you will have to perform this first request again.
On the www.google.com/device page, you will be asked to login if you aren't already and then enter the verification code (defined by the "user_code" response field). You will be presented with a request to authorize the application and a list of permissions the app is requesting.
You want to store (at least temporarily) the value for the "device_code" field. This will be used when requesting an access token and refresh token.
Now that the permission has been granted, we can request an access/refresh token pair. This only needs to happen once provided you store the refresh token.
To request the access/refresh token pair you must make a POST request to accounts.google.com/o/oauth2/token with the headers
{
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': post_data.length,
'X-GData-Key': 'key=YOUR_DEVELOPER_KEY'
}
and the data
{
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
code: 'YOUR_DEVICE_CODE',
grant_type: 'http://oauth.net/grant_type/device/1.0'
}
The response will look like this
{
"access_token" : "YOUR_ACCESS_TOKEN",
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : "YOUR_REFRESH_TOKEN"
}
This specifies that the access token expires in 3600 seconds (60 minutes) and what your current access token is and what the refresh token is.
You want to store the access token for use with your current session and the refresh token for future sessions.
When making an API request, you will want to include the access token in the Authorization header field as well as including the developer key as we have been all along.
For uploading a video, I used these headers:
{
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'X-GData-Key': 'key=YOUR_DEVELOPER_KEY',
'Slug': 'video.mp4',
'Content-Type': 'multipart/related; boundary="f897a6d"',
'Content-Length': post_length,
'Connection': 'close'
}
You can refresh your access token at any time, not just when the old one expires. To refresh your access token, you make a POST request to accounts.google.com/o/oauth2/token with the headers
{
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': post_data.length,
'X-GData-Key': 'key=YOUR_DEVELOPER_KEY'
}
and the data
{
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
refresh_token: 'YOUR_REFRESH_TOKEN',
grant_type: 'refresh_token'
}
You will get a response like this
{
"access_token" : "YOUR_NEW_ACCESS_TOKEN",
"token_type" : "Bearer",
"expires_in" : 3600
}
where YOUR_NEW_ACCESS_TOKEN is the new token for you to use in your future requests.

Resources