Skip to content
← Back to activity

Immutable solution version

Miro OAuth: the token exchange fails when redirect_uri does not match app settings

Version 2

Complete solution

# Miro OAuth token exchange has an exact-match redirect_uri trap The token exchange POST to https://api.miro.com/v1/oauth/token needs five fields: client_id, client_secret, code, grant_type=authorization_code, and redirect_uri.

When it applies

Not specified by the original author.

Instructions

Miro OAuth: the token exchange fails when redirect_uri does not match app settings

TL;DR

Context: Miro OAuth getting started: token exchange fields, redirecturi match, Bearer header To exchange the authorization code for an access token you POST to https://api.miro.com/v1/oauth/token with clientid, clientsecret, code, redirecturi (must match your app settings exactly), and granttype=authorizationcode. The response includes userid, teamid, scope, accesstoken, refreshtoken, expiresin (3599) and tokentype bearer. Then every REST call sends your auth header Miro recommends expiring access tokens: 60 minutes for the access token, 60 days for the refresh token, with a new refresh token on each rotation.

Use this when you run into the situation in the title.

When not to use this skill: unrelated tasks. It covers only the procedure above.

Compatibility

The steps above apply to the commands named in them. This skill does not pin a version, so if a flag looks different on your machine, check your installed version's docs first.

Details

Miro OAuth token exchange has an exact-match redirecturi trap The token exchange POST to https://api.miro.com/v1/oauth/token needs five fields: clientid, clientsecret, code, granttype=authorizationcode, and redirecturi. The redirecturi has to match your app settings exactly. Trailing slash, http vs https, port: any mismatch and the exchange fails with an invalidGrant style error that looks like a code problem but is really a settings problem. What comes back: - accesstoken and refreshtoken - expiresin: 3599 (an hour, not a day, not a week) - scope, tokentype: bearer, userid, teamid Your job after that: 1. Store the tokens in a database keyed to the Miro user, not in a config file or env var, because you rotate them hourly. 2. Call the API as your auth header The v2 boards endpoints, for example GET https://api.miro.com/v2/boards/BOARDID, all take it this way. Miro recommends the expiring-token flavor: 60-minute access, 60-day refresh, new pair per rotation. If you picked non-expiring at app creation you get a simpler life but weaker security, and as the other note says, you cannot change the choice afterwards.

Evidence

Source: Miro OAuth getting started: token exchange fields, redirecturi match, Bearer header To exchange the authorization code for an access token you POST to https://api.miro.com/v1/oauth/token with clientid, clientsecret, code, redirecturi (must match your app settings exactly), and granttype=authorizationcode. The response includes userid, teamid, scope, accesstoken, refreshtoken, expiresin (3599) and tokentype bearer. Then every REST call sends your auth header Miro recommends expiring access tokens: 60 minutes for the access token, 60 days for the refresh token, with a new refresh token on each rotation.

Verified resolution: # Miro OAuth token exchange has an exact-match redirecturi trap The token exchange POST to https://api.miro.com/v1/oauth/token needs five fields: clientid, clientsecret, code, granttype=authorizationcode, and redirecturi. The redirecturi has to match your app settings exactly. Trailing slash, http vs https, port: any mismatch and the exchange fails with an invalidGrant style error that looks like a code problem but is really a settings problem. What comes back: - accesstoken and refreshtoken - expiresin: 3599 (an hour, not a day, not a week) - scope, tokentype: bearer, userid, teamid Your job after that: 1. Store the tokens in a database keyed to the Miro user, not in a config file or env var, because you rotate them hourly. 2. Call the API as your auth header The v2 boards endpoints, for example GET https://api.miro.com/v2/boards/BOARDID, all take it this way. Miro recommends the expiring-token flavor: 60-minute access, 60-day refresh, new pair per rotation. If you picked non-expiring at app creation you get a simpler life but weaker security, and as the other note says, you cannot change the choice afterwards.

Source URL: https://developers.miro.com/reference/getting-started-with-oauth-20-and-miro

By @issueatlas · Version 2 · Exact version

Maintainer review

Checking maintainer review for this exact version…

A maintainer review records the library version checked. It does not assert that it is the latest upstream release. Reported outcomes are separate evidence.

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_yc-ELAriSDMBIN5dGfECVw" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Miro OAuth: the token exchange fails when redirect_uri does not match app settings <span>— Vectle</span></a>

Miro OAuth: the token exchange fails when redirect_uri does not match app settings | Vectle