Auth0 Home Blog Docs

Mysterious /oauth/token errors of "invalid grant" and "Invalid authorization code".



I’m hoping for a hint to send me in the right direction as a modify your node quickstart to return an access_token. I’ve captured the authorization code in the /callback route of index.js with

  passport.authenticate('auth0', {
    failureRedirect: '/failure'
  function(req, res) {
    req.session.authorization_code=req.query.code;  //capture hash fragment
    res.redirect(req.session.returnTo || '/user');

I then check that I still have the hash fragment in the session object in user.js, and then call the /oauth/token endpoint as per the API documentation, as shown here:

	console.log('user.js: req.session.authorization_code: '+req.session.authorization_code);
	var request = require("request");
	var options = { method: 'POST',
	url: '',
	headers: { 'content-type': 'application/json' },
	{ grant_type: 'authorization_code',
	client_id: 'L1KWXPiVU1nPuTrqKNWF6fXzZCP_TZY5',
	client_secret: CLIENT_SECRET,
	code: req.session.authorization_code,
	redirect_uri: 'http://localhost:3000/callback' },
	json: true };
	request(options, function (error, response, body) {
		if (error) throw new Error(error);
		console.log('get token: '+stringify(body, null, 4));

Unfortunately the contents of “body” are the error messages:

get token: {
    "error": "invalid_grant",
    "error_description": "Invalid authorization code"

Any suggestions as to why I am getting these error message? I’m certain I’m using the authorization code passed back to me when the user was authenticated.


Based on the information provided you’re storing the returned authorization code in session and then later performing the exchange. In general, I don’t see the reason for such a process as the code should be exchanged upon being received (in the callback) because otherwise you technically did not complete the full authentication flow. Having said that, unless you’re letting sufficient time to pass between the callback call and the call that actually exchanges the code then this by itself may not be the explanation of the issue (although authorization codes in general have a really short lifetime so do check this is indeed not the cause).

Assuming you’re trying to exchange the code within it’s valid lifetime then besides manually checking (through debug output) that the code that you’re trying to exchange is exactly the same issued to the client application I don’t have other hints at the problem. In addition, I could not reproduce it in my own tests so if you still don’t fine the source of the issue you may want to update the question with an HTTP trace of initial authorization code issuance and also of the subsequent code exchange that fails.


I am having the same problem. Keep in mind, the flow auth0Cordova has gets 1 access token. My application has 9 different audiences so I request access tokens when needed during the tokengetter process. On the desktop browser, we’ve had this working for a long time. Using PKCE, I keep getting invalid_grant.

I’m passing the code that came back from authorize and the verifier. I modified Auth0Cordova to handle this. So I send those along with the audience and scopes I am requesting.