---
updatedAt: 2026-03-19T19:38:31.000Z
agentTools:
  projectIndex: https://developers.miro.com/llms.txt
---

# Log in to a third-party service using OAuth

This guide teaches you to how to handle logging into a third-party service (Slack) using OAuth. The guide will teach you how to store user information using local storage.

If you're looking to integrate a Miro app with an external service, implementing OAuth is essential for secure API access.

## Goal

Learn how to authenticate with an external service using OAuth. This guide covers logging in, displaying the login status on the UI, and enabling logout functionality.

## Prerequisites

Before starting, ensure you have:

* A [Miro account](https://miro.com/signup/).
* [Logged in to Miro](https://miro.com/login/).
* A [Developer team](https://developers.miro.com/docs/the-developer-team) set up in your Miro account.
* [Node.js 14.15](https://nodejs.org/en/download/) or newer installed in your development environment.
* An app on a third-party service with an OAuth URL, Client ID, and Client Secret for authentication. This example uses a Slack app.

### Watch app demo

To grasp the app's flow, watch the demo on GitHub in the [app example demo section](https://github.com/miroapp/app-examples/tree/main/examples/3rd-party-oauth-login#-app-demo-sound-on). Once familiar with the flow, proceed to the next steps.

## Configuring environment variables

Navigate to the [.sample.env file](https://github.com/miroapp/app-examples/blob/main/examples/3rd-party-oauth-login/src/backend/.sample.env) and input your OAuth URL, corresponding to the third-party service login, Slack in this case.

### Retrieving Slack app credentials

For Slack's **Client ID** and **Client Secret**:

1. Access **Slack** > **Settings** > **Basic Information**.
2. Under **App Credentials**, note the **Client ID** and **Client Secret** and save them in your `.sample.env` file.

[block:image]
{
  "images": [
    {
      "image": [
        "https://files.readme.io/8112bb8-app-credentials.png",
        "",
        ""
      ],
      "align": "center",
      "sizing": "500px"
    }
  ]
}
[/block]

To obtain the **OAuth URL** from Slack:

1. Navigate to **Slack** > **Settings** > **Manage Distribution**.
2. Check all boxes.
3. In the **Share Your App with Any Workspace** section, copy the **Sharable URL**.
4. Use this URL as the **OAuth URL** in your `.sample.env` file.

[block:image]
{
  "images": [
    {
      "image": [
        "https://files.readme.io/8e2287c-share-your-app.png",
        "",
        ""
      ],
      "align": "center",
      "sizing": "500px"
    }
  ]
}
[/block]

Update your `.env` file with the OAuth URL and any required scopes on the OAuth and permissions page of the app settings. Rename `.sample.env` to `.env` and save the changes.

## Front-end overview

The app's front end mainly resides within the [app.js](https://github.com/miroapp/app-examples/blob/main/examples/3rd-party-oauth-login/src/app.js) file, with some HTML in the [app.html](https://github.com/miroapp/app-examples/blob/main/examples/3rd-party-oauth-login/app.html) file.

[block:image]
{
  "images": [
    {
      "image": [
        "https://files.readme.io/fb85933-third-party-oauth-login.png",
        "",
        ""
      ],
      "align": "center"
    }
  ]
}
[/block]

The app initializes by hiding the logout button and checking the login status using [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). Depending on the login status, it either shows the login or logout button.

The [startOAuthFlow](https://github.com/miroapp/app-examples/blob/main/examples/3rd-party-oauth-login/src/app.js#L67-L89) function activates upon clicking the "Login to 3rd party tool" button, fetching the OAuth URL from the back end and opening it. It then listens for a message from the back end indicating whether authentication was successful. If so, it sets the `isLoggedIn` property of `localStorage` to `true` and updates the UI to reflect the successful login.

[block:image]
{
  "images": [
    {
      "image": [
        "https://files.readme.io/752a0ea-Screenshot_2024-03-19_at_16.53.10.png",
        null,
        ""
      ],
      "align": "center"
    }
  ]
}
[/block]

## Back-end setup

The Node.js backend, found in [app.js](https://github.com/miroapp/app-examples/blob/main/examples/3rd-party-oauth-login/src/backend/app.js), requires running `npm install` before launching the server with `node app.js`. Run the front end and back end in separate terminal windows.

### Configuring redirect URLs

Since Slack requires `https://` redirect URLs, use ngrok to tunnel `http://localhost:4000`. Install ngrok (the free version suffices), start your server, and then run `ngrok http 4000` in another terminal.

[block:image]
{
  "images": [
    {
      "image": [
        "https://files.readme.io/77ec255-terminal.png",
        "",
        ""
      ],
      "align": "center"
    }
  ]
}
[/block]

Ngrok provides an HTTPS route, which you should add to your Slack App Settings as the redirect URL, appending `/redirect` to the end.

[block:image]
{
  "images": [
    {
      "image": [
        "https://files.readme.io/f259955-redirect-urls.png",
        "",
        ""
      ],
      "align": "center",
      "sizing": "500px"
    }
  ]
}
[/block]

### Understanding main logic

The back end has two primary routes: the [home route](https://github.com/miroapp/app-examples/blob/main/examples/3rd-party-oauth-login/src/backend/app.js#L22-L29) `/`, sending the OAuth URL to the front end, and the `/redirect` route, handling the OAuth logic. Upon successful OAuth flow completion, Slack sends a temporary code to the [redirect route](https://github.com/miroapp/app-examples/blob/main/examples/3rd-party-oauth-login/src/backend/app.js#L33-L85) `/redirect`, which exchanges the code for an access token using Slack's `oauth.v2.access` [endpoint](https://api.slack.com/methods/oauth.v2.access).

Successful authentication sends a `redirectSuccess: true` [message](https://github.com/miroapp/app-examples/blob/main/examples/3rd-party-oauth-login/src/backend/app.js#L63-L67) to the front end, closing the window after five seconds. Unsuccessful attempts send a `redirectSuccess: false` [message](https://github.com/miroapp/app-examples/blob/main/examples/3rd-party-oauth-login/src/backend/app.js#L72-L77).

Given that you set the correct redirect URL in your Slack App Settings, once you click "Allow" in the OAuth flow, Slack will send a temporary code to your [/redirect route](https://github.com/miroapp/app-examples/blob/main/examples/3rd-party-oauth-login/src/backend/app.js#L33-L85). In that route, check if the `statusCode` was `200`, and if it was then it means you have successfully finished the OAuth flow. You can then grab the code from the URL, and use the `https://slack.com/api/oauth.v2.access` [endpoint](https://api.slack.com/methods/oauth.v2.access) to exchange the code for an access token. Once you have the access token from the third-party service, you can start using the third-party APIs, as long as the scopes you have requested are sufficient.

## Conclusion

Now you understand how to login to a third-party service using OAuth within your Miro app. See the [full app-example on GitHub](https://github.com/miroapp/app-examples/tree/main/examples/3rd-party-oauth-login).

# Sibling pages

* [Use the browser developer tools with the Miro Web SDK](https://developers.miro.com/miro-ea/docs/use-the-developer-tools-with-the-miro-web-sdk.md)
* [Update and sync item properties](https://developers.miro.com/miro-ea/docs/update-and-sync-item-properties.md)
* [Add icon click to your app](https://developers.miro.com/miro-ea/docs/add-icon-click-to-your-app.md)
* [Add an icon to your app](https://developers.miro.com/miro-ea/docs/add-a-logo-to-your-app.md)
* [Add drag and drop to your app](https://developers.miro.com/miro-ea/docs/add-drag-and-drop-to-your-app.md)
* [Add permission scopes to your app](https://developers.miro.com/miro-ea/docs/add-permission-scopes-to-your-app.md)
* [Add search and filter to your app](https://developers.miro.com/miro-ea/docs/adding-search-and-filter-to-an-sdk-app.md)
* [Build a calendar app in Miro](https://developers.miro.com/miro-ea/docs/building-a-calendar-app-in-miro.md)
* [Convert sticky notes to shapes](https://developers.miro.com/miro-ea/docs/converting-sticky-notes-to-shapes.md)
* [Create mind map from CSV](https://developers.miro.com/miro-ea/docs/create-mind-map-from-csv.md)
* [Add custom actions to your app](https://developers.miro.com/miro-ea/docs/add-custom-actions-to-your-app.md)
* [Deploy a Miro app](https://developers.miro.com/miro-ea/docs/deploy-a-miro-app.md)
* [Enable 2-way sync between app cards and GitHub cards](https://developers.miro.com/miro-ea/docs/enable-2-way-sync-between-app-cards-and-github-cards.md)
* [Enable REST API authentication from Miro's Web SDK authorization](https://developers.miro.com/miro-ea/docs/enable_api_authentication_from_sdk_authorization.md)
* [Integrate a digital asset manager in Miro](https://developers.miro.com/miro-ea/docs/integrate-a-digital-asset-manager-in-miro.md)
* [Convert frame coordinates to board coordinates](https://developers.miro.com/miro-ea/docs/frame-coordinates-to-board-coordinates.md)
* [SVG app icon optimization guidelines](https://developers.miro.com/miro-ea/docs/svg-app-icon-optimization.md)
* [Upload images and SVGs as base64-encoded strings](https://developers.miro.com/miro-ea/docs/upload-images-and-svgs-as-base64-encoded-strings.md)
* [Connect the Miro Web SDK to a backend (Firebase)](https://developers.miro.com/miro-ea/docs/connect-the-miro-web-sdk-to-a-backend-firebase.md)
* [Video: Deploy a Next.js App on AWS Amplify](https://developers.miro.com/miro-ea/docs/video-deploy-a-nextjs-app-on-aws-amplify.md)
* [Video: Integrate OpenAI + Miro](https://developers.miro.com/miro-ea/docs/video-integrate-openai-miro.md)
* [Build collaborative app experiences](https://developers.miro.com/miro-ea/docs/build-collaborative-app-experiences.md)
* [Display banner/modal on a Miro board using DynamoDB](https://developers.miro.com/miro-ea/docs/display-bannermodal-on-a-miro-board-using-dynamodb.md)
* [Display banner/modal on a Miro board using AWS S3](https://developers.miro.com/miro-ea/docs/display-bannermodal-on-a-miro-board-using-aws-s3.md)