Microsoft Graph API error: The request does not contain a valid authentication token

Hello.

I’ve created a custom GPT that is meant to act as my personal assistant. It is meant to connect to my Microsoft data via the Microsoft Graph API. I’ve managed to successfully set up the function to at least allow me to sign into my Microsoft account and retrieve my user profile details. Unfortunately, that is where the fun stops for me.

This integration is meant to expand to include a wide variety of the Microsoft Graph API capabilities. But whenever I try to add and test any action that isn’t retrieving my account’s information, I get an error that says “The request does not contain a valid authentication token. Detailed error information: {0”.

I’ve asked ChatGPT for guidance but it seems to give me mixed information. For example, it suggests that I use the API Key Authentication type but it is required that I use the Oauth type for Microsoft Graph. So, I’m stuck.

Anything help would be greatly appreciated.

If you’d like to replicate my setup to troubleshoot for yourself, here is how I have everything configured.

1. As per Microsoft's instructions, within my Azure portal, under Microsoft Entra ID, I created a new app and acquired my Client ID and Client Secret.
	a. FYI: The app's Supported Account types are "All Microsoft Account Users".
	b. FYI: By default, the only scope in the app's API Permissions section is "Microsoft Graph: User.Read". You may have to add the "Notes.ReadWrite.All" permission as well.
	
2. Within the GPT editor, I set up Oauth authentication with the following configurations;
	a. Client ID: <Azure app's Client ID>
	b. Client Secret: Azure app's Client Secret Value (Not Secret ID string as this returns a "Missing Access Token" error)
	c. Authorization URL: https://login.microsoftonline.com/common/oauth2/v2.0/authorize
	d. Token URL: https://login.microsoftonline.com/common/oauth2/v2.0/token
	e. Scope: User.Read Notes.ReadWrite.All
	f. Token Exchange Method: Default (Post request)

3. I added the GPT's callback URL to the Redirect URI within my Azure app's Authentication settings.
	a. FYI: Each time you change the GPT's Client ID and Client Secret values, you must save and refresh the tab to get the updated callback URL.

4. I had GPT whip up some basic JSON and copy pasted it into the GPT's schema.
	a. FYI: Sometimes, adding a new JSON will also require you to save and refresh the tab to get the updated callback URL

Here is the JSON I have;

{
  "openapi": "3.1.0",
  "info": {
    "title": "A.D.A GPT Microsoft Graph Integration",
    "version": "1.0.0",
    "description": "This specification outlines the integration of A.D.A GPT with the Microsoft Graph API to access and manage the user's profile and OneNote data."
  },
  "servers": [
    {
      "url": "https://graph.microsoft.com/v1.0",
      "description": "Microsoft Graph API server"
    }
  ],
  "paths": {
    "/me": {
      "get": {
        "operationId": "getUserProfile",
        "summary": "Get User Profile",
        "description": "Retrieve the user's profile information from Microsoft Graph.",
        "responses": {
          "200": {
            "description": "Successful response with user profile data.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserProfile"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized request due to invalid or missing authentication token."
          },
          "403": {
            "description": "Forbidden request due to insufficient permissions."
          }
        }
      }
    },
    "/me/onenote/notebooks": {
      "get": {
        "operationId": "getOneNoteNotebooks",
        "summary": "Get OneNote Notebooks",
        "description": "Retrieve the user's OneNote notebooks.",
        "responses": {
          "200": {
            "description": "Successful response with OneNote notebooks data.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OneNoteNotebooks"
                }
              }
            }
          }
        }
      }
    },
    "/me/onenote/sections": {
      "get": {
        "operationId": "getOneNoteSections",
        "summary": "Get OneNote Sections",
        "description": "Retrieve the user's OneNote sections.",
        "responses": {
          "200": {
            "description": "Successful response with OneNote sections data.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OneNoteSections"
                }
              }
            }
          }
        }
      }
    },
    "/me/onenote/pages": {
      "get": {
        "operationId": "getOneNotePages",
        "summary": "Get OneNote Pages",
        "description": "Retrieve the user's OneNote pages.",
        "responses": {
          "200": {
            "description": "Successful response with OneNote pages data.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OneNotePages"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "OAuth2": {
        "type": "oauth2",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
            "tokenUrl": "https://login.microsoftonline.com/common/oauth2/v2.0/token",
            "scopes": {
              "User.Read": "Read user profile",
              "Notes.ReadWrite.All": "Read and write all OneNote content"
            }
          }
        }
      }
    },
    "schemas": {
      "UserProfile": {
        "type": "object",
        "properties": {
          "displayName": {
            "type": "string"
          },
          "mail": {
            "type": "string"
          }
        }
      },
      "OneNoteNotebooks": {
        "type": "object",
        "properties": {
          "value": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Notebook"
            }
          }
        }
      },
      "Notebook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
        }
      },
      "OneNoteSections": {
        "type": "object",
        "properties": {
        }
      },
      "OneNotePages": {
        "type": "object",
        "properties": {
        }
      }
    }
  },
  "security": [
    {
      "OAuth2": ["User.Read", "Notes.ReadWrite.All"]
    }
  ]
}

Any guidance would be greatly appreciated.

I just tested my implentation and seems to work.

https://chat.openai.com/g/g-6QzJ0XxVC-ms-co-pilot

{
  "openapi": "3.0.0",
  "info": {
    "title": "Microsoft Graph API Example",
    "version": "1.0"
  },
  "servers": [
    {
      "url": "https://graph.microsoft.com/v1.0"
    }
  ],
  "paths": {
    "/me": {
      "get": {
        "operationId": "getUserProfile",
        "summary": "Get current user profile",
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserProfile"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": []
          }
        ]
      }
    },
    "/me/messages": {
      "get": {
        "operationId": "getUserEmails",
        "summary": "Get user's email messages",
        "parameters": [
          {
            "name": "$top",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 10
            },
            "description": "Number of emails to return per page."
          },
          {
            "name": "$skip",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Number of emails to skip."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "value": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/UserEmails"
                      }
                    },
                    "@odata.nextLink": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": []
          }
        ]
      }
    },
    "/me/sendMail": {
      "post": {
        "operationId": "sendUserEmail",
        "summary": "Send an email message",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendMail"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Email sent successfully"
          }
        },
        "security": [
          {
            "OAuth2": []
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "UserProfile": {
        "type": "object",
        "properties": {
          "displayName": {
            "type": "string"
          },
          "mail": {
            "type": "string"
          }
        }
      },
      "UserEmails": {
        "type": "object",
        "properties": {
          "subject": {
            "type": "string"
          },
          "sender": {
            "type": "object",
            "properties": {
              "emailAddress": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "address": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "bodyPreview": {
            "type": "string"
          },
          "receivedDateTime": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SendMail": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "object",
            "required": [
              "subject",
              "body",
              "toRecipients"
            ],
            "properties": {
              "subject": {
                "type": "string"
              },
              "body": {
                "type": "object",
                "properties": {
                  "contentType": {
                    "type": "string",
                    "enum": [
                      "text",
                      "HTML"
                    ],
                    "default": "text"
                  },
                  "content": {
                    "type": "string"
                  }
                }
              },
              "toRecipients": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "emailAddress"
                  ],
                  "properties": {
                    "emailAddress": {
                      "type": "object",
                      "required": [
                        "address"
                      ],
                      "properties": {
                        "address": {
                          "type": "string",
                          "format": "email"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "OAuth2": {
        "type": "oauth2",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
            "tokenUrl": "https://login.microsoftonline.com/common/oauth2/v2.0/token",
            "scopes": {
              "User.Read": "Read user profile",
              "Mail.Read": "Read user's mail",
              "Mail.ReadWrite": "Read and write access to user's mail",
              "Mail.Send": "Send mail as a user",
              "Calendars.Read": "Read user's calendar",
              "Calendars.ReadWrite": "Read and write access to user's calendar"
            }
          }
        }
      }
    }
  }
}

Scope:
Calendars.Read Calendars.ReadWrite Mail.Read Mail.ReadWrite User.Read Mail.Send

Hello @ruv

Thanks for responding. I copy pasted your JSON and tried to run it. Originally, I encountered the same issue. I could sign into my Microsoft account but I could not run the other actions.

So I went into my app’s Azure settings, under API permissions, and I enabled admin consent for all the API calls. Then I ran the test again.

Although it originally kicked back a “too large” error, it proceeded to run anyway and retrieve my last 3 emails, so I suppose it works.

I am going to try and add the calls for OneNote to see if I could get those working as well.

How have you configure your callback URL on the Azure AD or Entra side?

Has anyone had success with this recently? I’m trying to setup a GPT assistant as well that can access Graph and Business Central APIs. Thanks

Yes, I’ve been able to get this to work well for Email, Calendar and OneDrive/Sharepoint files.

Here’s the YAML that I’m using and the permissions are Calendars.Read Calendars.ReadWrite Contacts.Read Files.Read Files.Read.All Mail.Read Mail.ReadWrite Mail.Send Notes.Read Notes.Read.All Notes.ReadWrite Notes.ReadWrite.All Presence.Read Presence.ReadWrite Sites.Read.All User.Read

openapi: 3.1.0
info:
  title: Microsoft Graph API Example
  version: "1.0"
servers:
  - url: https://graph.microsoft.com/v1.0
paths:
  /me:
    get:
      operationId: getUserProfile
      summary: Get current user profile
      responses:
        "200":
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserProfile"
      security:
        - OAuth2: []
  /me/messages:
    get:
      operationId: getUserEmails
      summary: Get user's email messages
      parameters:
        - name: $top
          in: query
          required: false
          schema:
            type: integer
            default: 10
          description: Number of emails to return per page.
        - name: $skip
          in: query
          required: false
          schema:
            type: integer
            default: 0
          description: Number of emails to skip.
        - name: $search
          in: query
          required: false
          schema:
            type: string
          description: >
            Search query to filter the messages. Some examples of searchable properties include: - `from:`: Filters
            messages by sender's email address. - `subject:`: Filters messages by subject line. - `body:`: Filters
            messages by content in the body. - `to:`: Filters messages by recipient's email address. Example usage:
            `$search="from:john.doe@example.com subject:meeting"`
      responses:
        "200":
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  value:
                    type: array
                    items:
                      $ref: "#/components/schemas/UserEmails"
      security:
        - OAuth2: []
  /me/sendMail:
    post:
      operationId: sendUserEmail
      summary: Send an email message
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SendMail"
      responses:
        "202":
          description: Email sent successfully
      security:
        - OAuth2: []
  /me/events:
    get:
      operationId: getUserEvents
      summary: Get user's events
      parameters:
        - name: $top
          in: query
          required: false
          schema:
            type: integer
            default: 10
          description: Number of events to return per page.
        - name: $skip
          in: query
          required: false
          schema:
            type: integer
            default: 0
          description: Number of events to skip.
        - name: $filter
          in: query
          required: false
          schema:
            type: string
          description: >
            Filter query to filter the events. Some examples of filterable properties include: - `start/dateTime`:
            Filters events by start date and time. - `end/dateTime`: Filters events by end date and time. - `subject`:
            Filters events by subject. Example usage: `$filter=start/dateTime ge '2023-01-01T00:00:00Z' and end/dateTime
            le '2023-01-31T23:59:59Z'`
      responses:
        "200":
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  value:
                    type: array
                    items:
                      $ref: "#/components/schemas/UserEvents"
      security:
        - OAuth2: []
    post:
      operationId: createUserEvent
      summary: Create a new event
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateEvent"
      responses:
        "201":
          description: Event created successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserEvents"
      security:
        - OAuth2: []
  /search/query:
    post:
      operationId: searchQuery
      summary: Search across Outlook, calendar events, SharePoint, and OneDrive
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SearchRequest"
      responses:
        "200":
          description: Successful response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SearchResponse"
      security:
        - OAuth2: []
components:
  schemas:
    UserProfile:
      type: object
      properties:
        displayName:
          type: string
        mail:
          type: string
    UserEmails:
      type: object
      properties:
        subject:
          type: string
        sender:
          type: object
          properties:
            emailAddress:
              type: object
              properties:
                name:
                  type: string
                address:
                  type: string
        bodyPreview:
          type: string
        receivedDateTime:
          type: string
          format: date-time
    UserEvents:
      type: object
      properties:
        subject:
          type: string
        organizer:
          type: object
          properties:
            emailAddress:
              type: object
              properties:
                name:
                  type: string
                address:
                  type: string
        start:
          type: object
          properties:
            dateTime:
              type: string
              format: date-time
            timeZone:
              type: string
        end:
          type: object
          properties:
            dateTime:
              type: string
              format: date-time
            timeZone:
              type: string
    CreateEvent:
      type: object
      properties:
        subject:
          type: string
        body:
          type: object
          properties:
            contentType:
              type: string
              enum:
                - text
                - HTML
            content:
              type: string
        start:
          type: object
          properties:
            dateTime:
              type: string
              format: date-time
            timeZone:
              type: string
        end:
          type: object
          properties:
            dateTime:
              type: string
              format: date-time
            timeZone:
              type: string
        location:
          type: object
          properties:
            displayName:
              type: string
        attendees:
          type: array
          items:
            type: object
            properties:
              emailAddress:
                type: object
                properties:
                  address:
                    type: string
                    format: email
                  name:
                    type: string
              type:
                type: string
                enum:
                  - required
                  - optional
                  - resource
    SearchRequest:
      type: object
      properties:
        requests:
          type: array
          items:
            type: object
            properties:
              entityTypes:
                type: array
                items:
                  type: string
                  enum:
                    - message
                    - event
                    - driveItem
                    - listItem
              query:
                type: object
                properties:
                  queryString:
                    type: string
              from:
                type: integer
                description: Starting point of the search results
              size:
                type: integer
                description: Number of results to return
    SearchResponse:
      type: object
      properties:
        value:
          type: array
          items:
            type: object
            properties:
              hitsContainers:
                type: array
                items:
                  type: object
                  properties:
                    hits:
                      type: array
                      items:
                        type: object
                        properties:
                          _id:
                            type: string
                          summary:
                            type: string
                          _score:
                            type: number
                          _source:
                            type: object
                            properties:
                              createdDateTime:
                                type: string
                                format: date-time
                              lastModifiedDateTime:
                                type: string
                                format: date-time
    SendMail:
      type: object
      properties:
        message:
          type: object
          properties:
            subject:
              type: string
            body:
              type: object
              properties:
                contentType:
                  type: string
                  enum:
                    - text
                    - HTML
                content:
                  type: string
            toRecipients:
              type: array
              items:
                type: object
                properties:
                  emailAddress:
                    type: object
                    properties:
                      address:
                        type: string
                        format: email
        saveToSentItems:
          type: boolean
          default: true
  securitySchemes:
    OAuth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/authorize
          tokenUrl: https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token
          scopes:
            User.Read: Read user profile
            Mail.Read: Read user's mail
            Mail.ReadWrite: Read and write access to user's mail
            Mail.Send: Send mail as a user
            Calendars.Read: Read user's calendar
            Calendars.ReadWrite: Read and write access to user's calendar

Thanks for the help! I was able to get the GPT to work. I think I had copied the secret id incorrectly.

I do get an error when I ask it to “show list of ten recent emails”:

“There seems to be an issue retrieving a large number of emails at once. Let’s try retrieving the most recent emails one more time with a smaller batch size.”

What queries are you using to help you manage email inbox?

I’m glad there was more traffic with this thread. It gave me further insight. I may revisit my little GPT project in the future.

I’d also like to connect OneNote to a GPT to give a full documented knowledge. That should be fun.

Glad to hear it’s working for you! This seems to be a limitation with ChatGPT itself and the max size response it’s able to process which honestly seems to be pretty low which is frustrating.

I think there’s a couple ways to skirt that issue:

  1. Teach it to use pagination so that it makes several smaller requests.
  2. When running queries I think we could have the MS Graph API omit certain fields in its response like the entire email body. That way you could have it give you a summary of subject, sample body, etc and then if you’re interested in a specific email have it go and fetch the body.

Hopefully they increase the max response limit soon!