GPT Actions Error - "Auth URL, Token URL and API hostname must share a root domain"

I am getting this error for an API that has no scopes and has a different URL in the servers schema than is different than the url for the authorize and token…

Do this matter…what am I doing wrong? Thanks!

the urls cannot be different than the server url. If they do not match it will throw an error.

What’s an easy way to make the domains all the same - ive tried url shortners and more - I can’t authenticate because the URL server domain is different than the authorization and the token url…any ideas on how to make them all the same?

yes. I suggest (or what is working for me) is a server in the middle that passes the tokens.

I used Google Cloud Run personally. I initially tried on replit but kept running into issues. Google Cloud Run you can use dockers so it more functional.

You then add those endpoints. If you are just passing the through api calls it should be pretty simple.

I used the approach listed further up:

FastAPI is also troublesome on replit, but you could do this with flask I believe.

Your shcema should wind up looking something like this:

openapi: 3.0.0
info:
title: Contract Management API
description: API for managing contracts with Google Drive integration
version: 1.0.0
servers:

  • url: ‘https://yourserverurl
    paths:
    /generate-contract:
    post:
    summary: Generate a contract document.
    operationId: generateContract
    requestBody:
    required: true
    content:
    application/json:
    schema:
    $ref: ‘#/components/schemas/ContractData’
    responses:
    ‘200’:
    description: Contract generated successfully
    content:
    application/json:
    schema:
    type: object
    properties:
    contract:
    type: string
    google_doc_link:
    type: string
    ‘401’:
    description: Unauthorized
    ‘500’:
    description: Server error

components:
securitySchemes:
OAuth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: ‘https://yourserverurl/authorize
tokenUrl: ‘https://yourserverurl/token
scopes:
https://www.googleapis.com/auth/drive: Access Google Drive
https://www.googleapis.com/auth/documents: Access Google Docs
https://www.googleapis.com/auth/userinfo.email: Access user email
schemas:
ContractData:
type: object
properties:
State:
type: string
County:
type: string
AssignorName:
type: string
AssignorAddress:
type: string
AssigneeName:
type: string
AssigneeAddress:
type: string
EffectiveDate:
type: string
TaxNotification:
type: integer
TaxDifferencePaidWithin:
type: integer

Do keep in mind, the first time you authenticate you will get a redirect url only after you add the schema. You will need that redirect url.

This part is also important:
GOOGLE_CLIENT_ID = os.getenv(“GOOGLE_CLIENT_ID”)
GOOGLE_CLIENT_SECRET = os.getenv(“GOOGLE_CLIENT_SECRET”)
REDIRECT_URI = “https://yourserverurl/intermediate
CHATGPT_REDIRECT_URI = “https://chat.openai.com/aip/g-examplef71622343234/oauth/callback#you will get this after you authentiacate

SCOPE = “https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/documents https://www.googleapis.com/auth/userinfo.email

I am using google, so it will be different for you of course. But you should get the idea with this and the example I linked.

1 Like

one more thing, once you authenticate, if it gives you green and asks you to authenticate again (with the link) just ignore the second link and ask the question again. It will stop trying to ask you to authenticate again. Its a bug that cost me half a day lol

@tyler.schacht funny enough, the yahoo fantasy API is the exact reason I’m here. Did you ever manage to get this working?

Hey all - the reason that mismatched OAuth + actions endpoint domains aren’t allowed in GPTs today is that we don’t want someone intercepting “YOUR_GOOGLE_ACCESS_TOKEN” on “api.evil.com”.

That being said, we know that some valid APIs are hosted on a different domain than their auth URLs, so these exceptions are allowed (for instance Google Drive). I’ve gone ahead and added Yahoo to the list - hopefully that allows you to build again!

2 Likes

Thanks for the reply!

This is, however, still a limitation for my scenario, and probably many other scenarios. I have full ownership to my API’s code, but I’m using an Azure AD B2C tenant (that I own/control) as my identity provider.

That means that the auth and token URLs are on the format:
https://{my_b2c_tenant}.b2clogin.com/{my_b2c_tenant}.onmicrosoft.com/B2C_1_SUSI/oauth2/v2.0/authorize

while the API itself is available at this format:
https://{my_api_url}.com/api

The API is configured to only validate tokens coming from my B2C tenant. Do you have any recommendations for such scenarios?


Minor question on the side: is there any plan to increase the allowed number of actions/operations, or will 30 be the maximum for the foreseeable future?

I guess in this situation the only solution would be using a proxy, that exposes the action to GPT but handles the OAuth dance…

Would you be able to include this scenario as well:

Authorise URL: https://app.vssps.visualstudio.com/oauth2/authorize
Access Token URL: https://app.vssps.visualstudio.com/oauth2/token
Server URL: https://dev.azure.com/{organisationID}/{projectID}

Where organisation and project ID are passed in via YAML as part of the schema.

The irony of these proxy solutions is that they actually introduce a security vulnerability vector into the process. I’m guessing the “spirit” of the matching domains was to increase security, but in practice it is falling apart.

1 Like

Hi, thanks for helping out. Can you also allow Azure AD?

https://login.microsoftonline.com/{tenatnID}/oauth2/v2.0/authorize

https://login.microsoftonline.com/{tenatnID}/oauth2/v2.0/token

1 Like

Can you also add AWS Cognito to your whitelist please?

I’m doing something similar in Flask, but I keep getting an error that I’m not returning JSON:

0, message='Attempt to decode JSON with unexpected mimetype: text/html; charset=utf-8', url=URL('https://oauth-gpt-huey.replit.app/authorize')

Here are the endpoints I used in my Flask app to try to get this working:

# OAuth Configuration
oauth = OAuth(app)
google = oauth.register(
    name='google',
    client_id=os.environ['CLIENT_ID'],  # Replace with your client ID
    client_secret=os.
    environ['CLIENT_SECRET'],  # Replace with your client secret
    access_token_url='https://accounts.google.com/o/oauth2/token',
    access_token_params=None,
    authorize_url='https://accounts.google.com/o/oauth2/auth',
    authorize_params=None,
    api_base_url='https://www.googleapis.com/oauth2/v2/userinfo',
    client_kwargs={'scope': 'email'},
)


@app.route('/login')
def login():
  # Generate a unique state value for CSRF protection
  state = request.args.get('state', uuid.uuid4().hex)
  callback_url = request.args.get('redirect_uri', '')
  session['oauth_state'] = state
  session['callback_url'] = callback_url

  redirect_uri = url_for('authorize', _external=True)
  return google.authorize_redirect(redirect_uri=redirect_uri, state=state)


@app.route('/authorize')
def authorize():
  try:
    # Retrieve state from session and compare with state in request args
    expected_state = session.get('oauth_state', '')
    request_state = request.args.get('state', '')
    callback_url = session.get('callback_url', '')
    code = request.args.get('code', '')

    if not request_state or expected_state != request_state:
      return jsonify({"error":
                      "State mismatch or missing state parameter."}), 400

    # Include the state in the callback URL as a query parameter
    callback_url = f"{callback_url}?state={request_state}&code={code}"

    return redirect(callback_url)
  except Exception as e:
    app.logger.error(f"Error in /authorize: {e}")
    return jsonify({"error": str(e)}), 500


@app.route('/token')
def token():
  try:
    token_info = google.authorize_access_token()

    return jsonify({
        "access_token": token_info.get("access_token"),
        "token_type":
        "bearer",  # Usually, the type is Bearer, but confirm with your OAuth provider
        "refresh_token": token_info.get("refresh_token"),
        "expires_in": token_info.get("expires_in")
    }), 200
  except Exception as e:
    return jsonify({"error": str(e)}), 500

Hi @BoyangNiu. I just wanted to see if there’s been any movement on this.

I receive the following error after the redirect to chatGPT:

0, message=‘Attempt to decode JSON with unexpected mimetype: text/html; charset=utf-8’, url=URL(‘****/token’)

Any idea what I might do wrong?

Were you ever able to figure out a solution for this? I wasn’t hoping to use AD B2C for auth on my GPT, but can’t figure out a way around this domain matching issue.

I made this way harder than it needed to be. I just deployed custom domain names with Azure Front Door so all good now.

1 Like

I never found a proper solution to this, thanks for the update!

I’ll check out Azure Front Door myself, but if you have any further details on how you did it, it would be much appreciated.

Would it be possible to add the Google OAuth endpoints to the exception list @BoyangNiu please? This is preventing us from being able to set up and use a custom GPT action