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.