403 ERR_ACCESS_DENIED with invokeRemote from function

Hi community. I’m trying to build a forge app which requires to access a remote endpoint using invokeRemote from @forge/api but I’m getting the following response with 403 code:

<body id=ERR_ACCESS_DENIED>
<div id="titles">
<h1>ERROR</h1>
<h2>The requested URL could not be retrieved</h2>
</div>
<hr>

<div id="content">
<p>The following error was encountered while trying to retrieve the URL: <a href="my-broker.ddns.net:8442">my-broker.ddns.net:8442</a></p>

<blockquote id="error">
<p><b>Access Denied.</b></p>
</blockquote>

<p>Access control configuration prevents your request from being allowed at this time. Please contact your service provider if you feel this is incorrect.</p>

<p>Your cache administrator is <a href="mailto:webmaster">webmaster</a>.</p>
<br>
</div>

<hr>
<div id="footer">
<p>Generated Mon, 18 Aug 2025 15:50:21 GMT by ip-10-16-6-80 (squid)</p>
<!-- ERR_ACCESS_DENIED -->
</div>
</body>

This is my manifest file:

modules:
  jira:issuePanel:
    - key: forge-hello-world-app-hello-world-issue-panel
      resource: main
      resolver:
        function: resolver
      render: native
      title: forge-hello-world-app
      icon: https://developer.atlassian.com/platform/forge/images/icons/issue-panel-icon.svg
  function:
    - key: resolver
      handler: index.handler
remotes:
  - key: my-external-service
    baseUrl: https://my-broker.ddns.net:8442
    operations:
      - compute
    auth:
      appSystemToken:
        enabled: true
resources:
  - key: main
    path: src/frontend/index.jsx
app:
  runtime:
    name: nodejs22.x
    memoryMB: 256
    architecture: arm64
  id: ari:cloud:ecosystem::app/4c2ff75a-c618-4b55-8558-1e23de56749d
permissions:
  scopes:
    - read:app-user-token
    - read:app-system-token
    - read:jira-work

and this is the code:

import Resolver from '@forge/resolver';
import { invokeRemote } from '@forge/api';

const fetchRemoteEndpoint = async () => {
  const res = await invokeRemote('my-external-service', {
    path: '/myservice-path',
    method: 'GET',
    headers: {
      'Accept': 'application/json'
    }
  });
  if (!res.ok) {
    const text = await res.text();
    throw new Error(`invokeRemote failed: ${res.status} ${res.statusText} ${text}`);
  }
  const json = await res.json();
  return json;
};

My endpoint https://my-broker.ddns.net:8442/myservice-path is obviously publicly accessible from Internet (although faked here). Could anyone tell me what am I missing, please?

Hi, @RicardoHerrera .

How about using the default HTTPS port?

Using a non-standard port was causing the issue, indeed, Rax. I actually found this other post where they mention a couple of another valid ports: 80 8080 443 8443 8444 7990 8090 8085 8060. I’m using 8443 now and the 403 response is gone. However, I’m getting 502 now which is apparently caused because I’m using a self-signed certificate. Do you know how to avoid the trusted certificate checking for the developing phase?

Thanks in advance and for the previous response.

My last question has been answered here. A service like ngrok can be used.

2 Likes