[Python] Onshape API OAuth2 "invalid_grant" Error with ngrok Redirect URI

Discussão em 'Python' iniciado por Stack, Julho 9, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to integrate the Onshape API using OAuth2 authorization code flow but get a "invalid_grant", "Invalid authorization code" error when requesting an access token. I use a Flask application with ngrok for tunneling. The redirect_uri is verified but the issue persists. Details are below.

    Setup:

    • Flask app running locally
    • Ngrok tunneling (free tier)
    • redirect_uri set to ngrok tunneling URL in both Flask and Onshape Developer Portal.

    Flow:

    • User authorizes via Onshape authorization URL.
    • Receive authorization code within a few seconds.
    • Send token request to Onshape token endpoint with standard OAuth2 parameters.
    • Receive 400 Bad Request with "invalid_grant", "Invalid authorization code".

    Environment: Python 3.11, Flask, ngrok 3.23.3, Onshape API.

    Tried fixing by verifying redirect_uri, testing with Postman, removing PKCE, and ensuring quick token requests, but the error remains.

    Relevant code (Python):

    from flask import Flask, request, redirect
    import requests
    import logging
    import os
    from dotenv import load_dotenv

    logging.basicConfig(level=logging.DEBUG)
    logger = logging.getLogger(__name__)

    load_dotenv()
    CLIENT_ID = os.getenv("ONSHAPE_CLIENT_ID")
    CLIENT_SECRET = os.getenv("ONSHAPE_CLIENT_SECRET").strip()
    REDIRECT_URI = "https://ad55-86-58-66-165.ngrok-free.app/oauthRedirect"

    app = Flask(__name__)

    access_token = None

    def get_access_token(code):
    global access_token
    token_url = "https://cad.onshape.com/oauth/token"
    headers = {"Content-Type": "application/x-www-form-urlencoded"}
    data = {
    "grant_type": "authorization_code",
    "code": code,
    "redirect_uri": REDIRECT_URI,
    "client_id": CLIENT_ID,
    "client_secret": CLIENT_SECRET
    }
    logger.debug(f"Requesting token with data: {data}")
    response = requests.post(token_url, headers=headers, data=data, timeout=10)
    logger.debug(f"Token response: {response.status_code} - {response.text}")
    if response.status_code == 200:
    access_token = response.json()["access_token"]
    logger.debug(f"Access token obtained: {access_token}")
    return access_token
    logger.error(f"Token request failed: {response.text}")
    return None

    @app.route('/authorize')
    def authorize():
    auth_url = f"https://cad.onshape.com/oauth/authorize?response_type=code&client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&scope=OAuth2Read OAuth2Write"
    logger.debug(f"Redirecting to auth URL: {auth_url}")
    return redirect(auth_url)

    @app.route('/oauthRedirect')
    def oauth_redirect():
    code = request.args.get('code')
    logger.debug(f"Received authorization code: {code}")
    if not code:
    return "Authorization failed. No code received.", 400
    token = get_access_token(code)
    if not token:
    return "Failed to obtain access token. Check logs for details.", 500
    return f"Authorization successful! Token obtained. You can close this window and return to the app. Token: {token}"


    Logs:

    DEBUG:__main__:Received authorization code: QZbnOvsHQUXXXVERVsUImTxr
    DEBUG:__main__:Requesting token with data: {'grant_type': 'authorization_code', 'code': 'QZbnOvsHQUXXXVERVsUImTxr', 'redirect_uri': 'https://ad55-86-58-66-165.ngrok-free.app/oauthRedirect', 'client_id': '3MW5AMQMQJEO3MQMVL57K56PNOOXDS4YI72J74I=', 'client_secret': 'B5X676JUGZEUJGIBNFW6TRPUVN354GQYCVHD5JQOTMI5PWIPOVCQ===='}
    DEBUG:urllib3.connectionpool:https://cad.onshape.com:443 "POST /oauth/token HTTP/1.1" 400 85
    DEBUG:__main__:Token response: 400 - {
    "error" : "invalid_grant",
    "error_description" : "Invalid authorization code"
    }
    ERROR:__main__:Token request failed: {
    "error" : "invalid_grant",
    "error_description" : "Invalid authorization code"
    }​

    Postman test with same parameters gives the same 400 response.

    Question: Has anyone encountered this issue with Onshape API or similar OAuth2 setups using ngrok? Could the ngrok free tier subdomain be the cause? Suggestions for fixing the invalid_grant error or alternative tunneling (e.g., localtunnel, Cloudflare Tunnel) are welcome!

    Continue reading...

Compartilhe esta Página