Read the statement by Michael Teeuw here.
MMM-NowPlayingOnSpotify: surviving Spotify's 6-month refresh-token expiry (a maintained fork)
-
Hi all,
if you use MMM-NowPlayingOnSpotify (raywo’s lovely “now playing” module), there’s a
change coming from Spotify that will quietly break it — and I wanted to share both the
problem and a fix.The problem
Spotify announced that, starting 20 July 2026, user refresh tokens will expire after 6
months (blog (https://developer.spotify.com/blog/2026-06-18-refresh-token-expiration)).
Until now those tokens were effectively permanent, so the module just stored one and
kept minting access tokens forever. Once a refresh token expires, Spotify returns an
invalid_grant error, and the app is expected to discard it and send the user through
the sign-in flow again.The original module doesn’t handle that case: it logs the error and silently falls back
to the “nothing is playing” logo. So one day your mirror would just… stop showing
songs, with no hint why — while hammering the API once per second with a dead token.First attempt: the polite way
I opened an issue on the original repo to flag it. Unfortunately the project has been
unmaintained for ~6 years, and there was no response. So rather than let everyone’s
module quietly die this summer, I forked it and did the work.The fix: a fork with proper token handling
👉 https://github.com/rkorell/MMM-NowPlayingOnSpotify (v2.0.0)
What it does now:
- Detects invalid_grant, stops retrying, and shows a clear red re-authorization banner
on the mirror instead of pretending nothing’s playing. - Proactive warning ~2 weeks before the hard expiry (a smaller banner above the cover
art) — the music keeps playing, so it’s never a surprise outage. - Self-managed token store (tokens.json, git-ignored) instead of tokens in config.js,
so rotated/renewed tokens are actually persisted. You only keep clientID, clientSecret
and redirectURI in your config now. - Integrated re-authorization: the module runs a tiny local auth server; you
re-authorize from a browser and it recovers in-process, no restart. - Under the hood: a full refactor to native fetch/http — the deprecated request/express
dependencies are gone, so it’s now zero runtime dependencies — plus a proper backend
poll loop and English/German translations.
One wrinkle worth knowing (loopback + SSH tunnel)
Spotify only accepts http redirect URIs for loopback addresses now — a LAN IP or
hostname over http is rejected at runtime as insecure, and localhost isn’t allowed
either. So the redirect URI is http://127.0.0.1:8888/callback. Since a mirror is
headless, the easiest way to re-authorize from your laptop is a one-line SSH tunnel:ssh -L 8888:127.0.0.1:8888 pi@<mirror-ip>…then open http://127.0.0.1:8888 in your laptop’s browser. Full details are in the
README.Happy to help anyone getting it running, and a big thank-you to raywo for the original
module that many of us have enjoyed for years. - Detects invalid_grant, stops retrying, and shows a clear red re-authorization banner
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login