So, in the step 3 when I try to make a ‘POST’ request to retrieve the access token I am sending all the given parameters i.e(client_id,client_secret) in the request body in json format. But then I am receiving 400 Bad Request. In response it also shows “Oauth error invalid_request: The authorization code was not found or was already used”.
Based on what I can see so far, the best I can recommend is to ensure that you’ve only POSTed with that code once. If you are absolutely certain you have only used the code once, since it’s good for one use only, then my next guess without knowing what mechanism you are making the request from is that the code itself is not actually making it into your request (or your request is malformed somehow).
It might help me if you could provide an x-request-id response header from a failing request, that will let me check logs and maybe see what might be happening there.
Hi Alex, I’m having the same issue, with some extra advice needed.
I am trying to authenticate an app with a shopify store. The first time I attempt to do this, the request for an access token is successful and so are subsequent requests to the shopify api with the access token, but if I make another request for an access token with the same authorization code I receive a 400 response saying the authorization code is missing or has already been used, but the documentation at https://help.shopify.com/en/api/getting-started/authentication/oauth/api-access-modes says that multiple requests with the same authorization code in offline access mode will return the same token, there is no mention of not being able to make more than one request for an access token with the same authorization code.
I’m trying to figure out what I need to do with the authorization code obtained when my app is initially installed vs the code received whenever a user visits the app since they both use the same authorization flow.
For a bit more context, I used the ‘Building a shopify app with node and express’ tutorial to build the authorization flow for my app and that works fine. By chance (since I can’t find it mentioned in the documentation anywhere) I noticed that every time a user visits the app in their shop admin area, shopify makes another call to my install url and follows the same authorization flow in the background as it does when first installed and retrieves a new authorization code each time (in offline access mode since online is not requested). Is this supposed to happen, and what should I do each time I get a new code (every time a user visits the app) and when should I request an online authorization code?
In my experience (and I suppose someone can easily verify this), if you go through OAuth for a previously installed user and exchange that code, their access token for your app actually remains the same.
I don’t think there’s any harm in sending an existing user through your permission URL each time, but in my case it would cause a redirect each time. What I came up with instead is when a user arrives at my app I do a quick GET request to my server to check if I already have a valid access token for them (like this) as well as charge ID for billing api. If yes, then I skip the permission URL and they just enter the app. If not, then route them to the permissionUrl and OAuth.
@nikhilshrigod how did you solve this issue i have the same problem. when i try to create a offline access token by using code it will show like this any idea it would be helpfull
if (!response[“APP_UNINSTALLED”].success) {
console.log( Failed to register APP_UNINSTALLED webhook: ${response.result}
);
}
// Redirect to app with shop parameter upon auth
res.redirect(/?shop=${session.shop}&host=${host});
} catch (e) {
switch (true) {
case e instanceof Shopify.Errors.InvalidOAuthError:
res.status(400);
res.send(e.message);
break;
case e instanceof Shopify.Errors.CookieNotFound:
case e instanceof Shopify.Errors.SessionNotFound:
// This is likely because the OAuth session cookie expired before the merchant approved the request
res.redirect(/auth?shop=${req.query.shop});
break;
default:
res.status(500);
res.send(e.message);
break;
}
}
});