Discord API - random "invalid code" error passing back generated OAuth2 code - oauth-2.0

I've successfully implemented Discord's OAuth2 flow using the authorization code grant type into my application. The end user navigates to Discord's OAuth2 link for my bot, authorizes its access, and Discord redirects them back to my site with a code querystring. The bot then exchanges this code for an access token by querying Discord's API. Documentation on this process is available here for reference.
However, roughly every 50-100 requests to the exchange endpoint, I receive a 403 with the error invalid_grant and the description Invalid "code" in request. Frankly, I don't understand how the code just provided by Discord's system is instantly invalid. The same user can complete the process again and no error is returned the second time.
Out of desperation, I tried toggling on the option in the Developers Dashboard named Requires OAuth2 Code Grant seeing that it said "if your application requires multiple scopes," but it made no effect. I've also tried endless debugging, but the circumstances under each occurrence are apparently random. Oddly enough, I can't find anyone with the same issue online.
Below is the request I'm making in Node.js using the superagent library. It matches the documentation and works perfectly, other than the response randomly being the error described.
superagent.post('https://discordapp.com/api/v6/oauth2/token')
.type('x-www-form-urlencoded')
.set('Content-Type', 'application/x-www-form-urlencoded')
.send({
client_id: process.env.BOT_ID,
client_secret: process.env.BOT_SECRET,
grant_type: 'authorization_code',
code,
redirect_uri: process.env.OAUTH2_REDIRECT_URI,
scope: 'identify guilds.join',
});
I can confirm that all variables match their expected values. The value of redirect_uri matches that of redirect_uri in the original URL used. code is the value of the code querystring returned through the OAuth2 flow.
What (if anything) am I doing wrong that's causing the error?
Update 1:
Discord has directed me to the API GitHub repo, and I found the issue closed here. Commented and will update here if I receive any helpful info or resolve the issue completely (hopefully the case).

Ran into the same issue using nodejs. Leaving here notes for prosperity:
On Node, if there is no explicit app.head() handler, the .post() handler receives all head requests
Several Android phones, upon being redirected from discord, first send a head request to the endpoint
Meaning:
The user authenticates on discord, then through the redirect back, does a head request. This pulls discord with the code, BUT directly afterwards it also does a post request, which will fail (as you already used the code once), and possibly un-authenticates the user.
Solution for my specific issue was an explicit .head handler for all callback endpoints, which basically just returned the same headers (a redirect) as the post one did, but without calling discord.
Hope this helps.

did you use the OAuth2 link to invite your bot to your server - with the correct permissions? If so, in your main.js file did you define the token?
I.e. bot.login(“YOUR_TOKEN_HERE”)
I would recommend not toggling the ‘Requires OAuth2 Code Grant’ as it is a pain to do anything with in the beginning.
Please let me know of any progress :)

Related

Missing authorization code error in Google OAuth2

I'm stuck with an issue while trying to use Google's OAuth2 php lib. On the server side, after I instantiate an OAuth2 object I redirect the user to Google's sign in page, after which they hopefully grant permissions based on the scopes (the APIs I declared for use in the OAuth2) I declared. Now here's my issue: after the user grants permission I get redirected to the redirectUri I specified during the instantiation of OAuth2. This redirectUri contains as params state, code, and scope k-v pairs. I always get a "Missing authorization code" if I don't send back the value code to server and set it as a property of the OAuth2 object. However, if I send back the value of code to the server and set it as a property of the OAuth2 object I get a
"Client error: POST https://www.googleapis.com/oauth2/v4/token
resulted in a 400 bad request response. Error: "invalid_grant"`
So, I'm at lost here. I should mention that I actually managed to make 2 authorized calls to Google Ad Manager (the scope I declared) using the same flow I described above, but after that I keep getting the same 2 errors as above.
Does anybody know what's going on? I must be missing something but I can't see what. I'm using this guide so it's not really convoluted or complicated code but I just can't get it to work somehow. https://github.com/googleads/googleads-php-lib/wiki/API-access-on-behalf-of-your-clients-(web-flow)

Issue with invalid_grant error with Google Oauth2

Cheers everybody,
we have been deeply reading google documentation on exchanging access_token from google in order our (delphi)desktop application to SSO with google from server side. Here is the payload we send first look like:
https://accounts.google.com/o/oauth2/v2/auth?client_id=1000217514248-t1lojs6f8ed7l9ocrpbm98leahtum8n1.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&response_type=code&state=E1DF2FBA-0A66-4D69-B594-5EB8F7828AF7&scope=openid+profile&include_granted_scopes=true&code_challenge=C832DA50-E55A-499D-89B8-493BB4123C94&login_hint=test#Speelkriebel.be
Normally after this it redirects me to login in to our test user and after this according to the documentation we send a POST request to the end point token in order to get the access_token and refresh_token...: 'https://oauth2.googleapis.com/token
with the following parameters, the 'code' is generated we also send it as follow:
client_id=1000217514248-t1lojs6f8ed7l9ocrpbm98leahtum8n1.apps.googleusercontent.com
grant_type=authorization_code
client_secret=******
code= 4/1AY0e-g4GlavO38PI5Oo3vq04Pc4lMWN77et-02UiVWOsT-IyRQnU1lq19qo
redirect_uri = urn:ietf:wg:oauth:2.0:oob
The response is always
{
"error_description": "Missing code verifier.",
"error": "invalid_grant"
}
We have tried to send the client secret id also, Does it have to do with our code_challenge ? are the end points url and initial url okay? What are we missing? We are using CEF4Delphi as "browser like experience in order for the user to type in their google credentials. We have been reading this: https://developers.google.com/identity/protocols/oauth2/web-server#offline
We were also trying the playground :https://developers.google.com/oauthplayground/
we were sending the initial url in a chrome which generated a "code" and in the playground we inserted the code, and still got the same error of missing code verifier.
Thanks Guys
You seam to have URL encoded a lot of the values try not doing that. Also try using the basic call, before you start adding everything else. It should help you figure out which one of those extra parameters you are sending that's causing your issues.
https://accounts.google.com/o/oauth2/auth?client_id={clientid}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=profile&response_type=code
Also make sure that the client id is from an installed / other type client
This may also help Google 3 Legged OAuth2 Flow
For installed apps, the code challenge and verifier are parameters for enhancing the security of the OAuth flow through PKCE [1].
There is additional documentation about generating a code challenge and verifier here [2].
[1] https://www.rfc-editor.org/rfc/rfc7636
[2] https://developers.google.com/identity/protocols/oauth2/native-app#step1-code-verifier

Google's OpenID Connect says: OAuth 2 parameters can only have a single value: client_id

As part of the OpenID Connect (OAuth2 for Login), my application is supposed to request an access token, given a one-time authorization code, via the endpoint https://www.googleapis.com/oauth2/v3/token. According to documentation, this request needs 5 parameters passed to it, client_id among them. That is exactly what my application does, using the Perl module Net::OAuth2.
Everything has been working fine for several months, but today I was notified that it stopped working. No updates were made to the application code nor the libraries used by it.
The message my application now receives from the server when calling the token endpoint is this, in a 400 error response:
OAuth 2 parameters can only have a single value: client_id
A Google search suggests nobody has ever seen this message before, or lived to tell the tale. There doesn't seem to be a general issue with Google's OpenID Connect (other services based on it are working flawlessly), and the imminent shutdown of the old login protocol doesn't seem relevant.
More testing: removing all parameters except client_id causes this error message:
Required parameter is missing: grant_type
Supplying only client_id and grant_type produces the original error message again.
Does anyone have an idea what's going on here?
Google changed this behavior few days ago, so any OAuth2 library using Basic Auth headers AND body request parameters will start to see messages like
OAuth 2 parameters can only have a single value: client_id
or
OAuth 2 parameters can only have a single value: client_secret
So, you must now do NOT use both (the Auth headers and body request parameters) at the same time to send credentials to Google.
And according RFC 6749, the preferable way to send credentials is through Auth headers (thanks #JanKrüger for alert me about this).
Got the same error. It seems the problem is that NET::OAuth2 sets the authorization header when exchanging authorization code for access token. If you remove this header everything works fine.
Check the get_access_token method in Net::OAuth2::Profile::WebServer module. The authorization header includes client_id:client_secret base64-encoded string. Apparently Google now treats this duplication as an error.
The right way of fixing this is to set the secrets_in_params parameter when creating Net::OAuth2::Profile::WebServer object. Look in the Net::OAuth2::Profile documentation for more details.

Generating Linkedin Access Token

I have been trying with the simple REST Client as well as the REST Plugin for Mozilla. I am getting
"HTTP/1.1 401 Unauthorized" response with
"{"error":"unauthorized_client","error_description":"the client is not authorized"}" in the body.
I have been successful in getting the auth code, and the below is the POST request for access token, (Scope is r_fullprofile)
https://www.linkedin.com/uas/oauth2/accessToken?grant_type=authorization_code&code=AQTQeBxBzbU2aNWaQM6Ff3Z3bUd8Gyg10W9G2DdqXgWiP0q7-M55c5PLtppP7Ni3Y-6A9C8yDkj9K4VfJ7QkRUFjuV-3AknA5jAahpsFJv3wYfr8XD8&redirect_uri=https://www.google.com&client_id=75wl6j5zndvfkp&client_secret=secret
The redirect_uri=https://www.google.com is the one used for getting auth code as well.
Do we need to perform any URL encoding before making the POST request?
When I log into the linked in to my app, it has the below tokens,
OAuth User Token: c3ae4cee-1b23-xxx-9d2a-206f578dee4d
OAuth User Secret: 76bc48cc-c94f-xxx-bf9d-a663f7003383
I am not sure where it is used. we are using API & secret key to get auth code.
Thanks in Advance.
This is a 2-step process.
First, go to:
https://www.linkedin.com/uas/oauth2/authorization?response_type=code&client_id=YOUR-API-ID&scope=r_basicprofile&state=STATE&redirect_uri=YOUR-ENCODED-REDIRECT-URI
Then, within 10 secs of receiving the response, go to:
https://www.linkedin.com/uas/oauth2/accessToken?grant_type=authorization_code&redirect_uri=YOUR-ENCODED-REDIRECT-URI&client_id=YOUR-API-ID&client_secret=YOUR-API-ID&code=THE-CODE-OBTAINED-IN-FIRST-STEP
The response of the second request will have the actual access token you need to use.
When I followed the two steps I faced an issue where I got an error as
{"errorCode":0,"message":"Access to posting shares denied","requestId":"TYWULO2WPZ","status":403,"timestamp":1497353538016}
So I had to remove the &scope=r_basicprofile since it was preventing reading all the Default Application Permissions
I faced a similar problem and the problem was with the initial authorization code. You should mention the scope=rw_company_admin or whatever it is that you want to authorize to while doing the initial redirect URL call. Something like this -
https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=your_client_id&redirect_uri=https%3A%2F%2Fwww.google.com/&state=12345&scope=rw_company_admin%20r_emailaddress%20w_share%20r_basicprofile

When authenticating with oAuth and youtube, always get error : invalid_grant on 2nd auth attempt, why?

As of yesterday, my application is able to authenticate with google (youtube) via oAuth 2.0 the first time no problem but the 2nd time (re-authentication, same app + same user), when I exchange the requestToken for an accessToken I get an error:
error : invalid_grant
I'm using:
grant_type = authorization_code
like they suggest. What used to happen, before 2 days ago, was on re-authentication the web page would say 'you've already authenticated with this application before, would you like to grant it access again?'. What has changed or what could I be doing wrong?
I found a way to fix this (at least for us). When redirecting to the accounts.google.com/o/oauth2/auth url, we had to add both approval_prompt=force and access_type=offline. If one was missing, we got no refresh token.
This url documents all of the parameters, but says nothing about the refresh token: http://code.google.com/apis/accounts/docs/OAuth2WebServer.html
I think I may have found the answer here:
https://groups.google.com/forum/#!searchin/oauth2-dev/invalid_grant/oauth2-dev/eaOa6THER0k/z4eO-taUFxgJ
The problem was that that the "code" parameter that you need to send needs to be encoded. It will work when you set the approval_prompt to force because the return code contains URL-safe characters. However, this is not the case for the return code upon a second authorization request.
For me this fixed it, I hope it does for you as well.

Resources