Connecting to MS-Graph from Forge UI

I’m building a Forge Custom UI app for Confluence Cloud, and I need to connect it to MS Graph. I don’t seem to be able to connect properly, though, and I’m not sure what to try next.

So, on the Microsoft end I’ve registered the app on Entra, and added a web platform. I used the redirect URI https://id.atlassian.com/outboundAuth/finish, and left both options under “Implicit Grant & Hybrid Flows” unchecked. Under “Supported Account Types” I selected “Accounts in this organizational directory only”. I obtained a client secret. Then I added a Microsoft Graph delegated permission, requesting permissions for User.Read, Calendar.Read and Calendar.ReadBasic. On the main screen I clicked “Grant admin consent for “.

In my manifest.yml I have the following:

modules:
  macro:
    - key: my-macro-name
      resource: main
      resolver:
        function: resolver
      title: "My Macro Name"
      description: My description
  function:
    - key: resolver
      handler: index.handler
      providers:
        auth:
          - ms-graph
resources:
  - key: main
    path: static/macro-name/build
remotes:
  - key: microsoft-account
    baseUrl: https://login.microsoftonline.com
  - key: microsoft-graph
    baseUrl: https://graph.microsoft.com
providers:
  auth:
    - key: ms-graph
      name: MS-Graph
      scopes:
        - "https://graph.microsoft.com/User.Read"
        - "https://graph.microsoft.com/Calendars.ReadBasic"
      type: oauth2
      clientId: <My Application (Client) ID>
      remotes:
        - microsoft-account
        - microsoft-graph
      bearerMethod: authorization-header
      actions:
        authorization:
          remote: microsoft-account
          path: /organizations/oauth2/v2.0/authorize
        exchange:
          remote: microsoft-account
          path: /organizations/oauth2/v2.0/token
        revokeToken:
          remote: microsoft-graph
          path: /v1.0/me/revokeSignInSessions
        retrieveProfile:
          remote: microsoft-graph
          path: /v1.0/me
          resolvers:
            id: id
            displayName: email
permissions:
  scopes:
    - "read:confluence-props"
    - "write:confluence-props"
  external:
    fetch:
      backend:
        - "https://graph.microsoft.com"
        - "https://login.microsoftonline.com"
app:
  id: ari:cloud:ecosystem::app/<My Forge App ID>
  runtime:
    name: nodejs18.x

In src/index.js I have the function checkAuth:

resolver.define('checkAuth', async () => {
  
  try {
    const ms_graph = api.asUser().withProvider("ms-graph", "microsoft-graph");
    if (!(await ms_graph.hasCredentials())) {
      await ms_graph.requestCredentials();
    }
    const res = await ms_graph.fetch("/token");
    return res;
  } catch (error) {
    throw error;
  }
});

This is called by a useEffect from my static app.

I ran forge providers configure ms-graph and entered the Client Secret value.

When I add this to a page and run it (via a tunnel), I first see the button saying I need to give permissions to connect; once I’ve done that, the hasCredentials part seems ok (I can print off credentials, which look correct), but when I do const res = await ms_graph.fetch("/token"); and then print res to the console I get the following:

    url: 'https://microsoft-graph/?path=%2Ftoken',
    status: 404,
    statusText: 'Not Found',
    headers: Headers { [Symbol(map)]: [Object: null prototype] },
    counter: 0
  }

(I’ve tried replacing ‘/token’ with ‘/me’ to see whether I could retrieve my profile, but got the same response).

So, I’m not sure whether I’ve connected properly - how do I tell? If not, what am I doing wrong? Some things I’ve read seem to suggest that I need to tell Confluence my tenantID, but I can’t see where to do that.

I’m not sure whether I need to be requesting a token from Microsoft at all - does Confluence handle that in the background? Is it an issue that the url being called seems to be https://microsoft-graph/?path=/me - should it be https://microsoft-graph/me instead?

Any help is appreciated.

Hi @SharonGilmore, the issue might be that the full path was not provided. I think you might need to do something like (I assume that you are trying to call this API?):
const res = await ms_graph.fetch("/v1.0/me");
As for the /token API, I assume that it’s this one. Can you explain why you need to call this API? This API is exchanging for an OAuth access token, which Forge is actually doing for you behind the scenes.

2 Likes

Thank you! Apologies for the delay in replying; I’ve been working on other things for a few days.

That seems to be working, now that I’ve added “v1.0” (I thought I’d tried that before, but maybe not).

I was putting in the /token call just to see whether I could get some sort of response back from the API. Also I wasn’t sure what was going on behind the scenes, so wasn’t sure whether I needed to use that.

Thanks!