Skip to main content

OAuth for Music APIs: How to Authenticate Users Across 12 Streaming Services

Published on June 19, 2026

OAuth for Music APIs: How to Authenticate Users Across 12 Streaming Services

Why Music API Authentication Is Harder Than You Think

Quick answer: Each streaming service uses its own OAuth 2.0 implementation with different token lifetimes, scope formats, refresh behaviors, and error responses. Building a multi-service music app means maintaining 12 separate auth flows that break in 12 different ways.

Authentication against a single music API is straightforward. You register an app, redirect the user, exchange an authorization code for tokens, and store them. The problem starts when your product needs to support more than one service.

Here is what actually differs across services:

  • Token expiry windows range from 30 minutes to 12 months. Some services do not document their expiry at all.
  • Refresh token behavior varies wildly. Some services issue long-lived refresh tokens. Others expire them after a single use and return a new one with each refresh. A few services do not support refresh tokens at all, requiring full re-authorization.
  • Scope formats are inconsistent. One service uses space-delimited strings (user-read-private user-library-read). Another uses comma-separated lists. A third uses URL-style scopes.
  • Error responses follow no shared standard. A 401 from one service means "token expired." A 401 from another means "invalid client ID." The error payloads are structured differently every time.
  • Rate limiting on auth endpoints catches most developers off guard. Some services throttle token refresh requests separately from API calls, and hitting that limit locks your users out temporarily.

If you have ever built a multi-service integration, you know the auth layer alone can take weeks. The MusicAPI unified integration guide covers the broader architecture challenge, but authentication deserves its own deep treatment.

OAuth 2.0 Flows Across Major Streaming Services

Quick answer: All 12 services that support user authentication use OAuth 2.0 Authorization Code flow, but their implementations diverge on redirect URI validation, PKCE support, token exchange endpoints, and required headers.

The Authorization Code flow follows the same general pattern everywhere:

  1. Redirect the user to the service's authorization URL with your client ID, scopes, and redirect URI.
  2. The user approves access.
  3. The service redirects back to your app with an authorization code.
  4. Your backend exchanges that code for an access token (and sometimes a refresh token).

That four-step pattern looks simple. The complexity hides in the details.

Redirect URI validation

Some services require exact-match redirect URIs registered in their developer portal. Others allow wildcard subdomains. A few support localhost for development but reject it in production. If your redirect URI does not match exactly what the service expects, the auth flow fails silently or throws a cryptic error.

PKCE (Proof Key for Code Exchange)

PKCE adds a code_verifier and code_challenge to prevent authorization code interception attacks. Some services require PKCE for public clients (mobile and SPA apps). Others support it optionally. A few do not support it at all. If you are building a cross-platform app, you need to know which services need PKCE and which ones reject it.

Token exchange differences

The token exchange step should be a simple POST request. In practice:

  • Some services require client_id and client_secret in the request body.
  • Others require them as a Base64-encoded Authorization: Basic header.
  • A few accept both but return different response formats depending on which method you use.
  • One service requires a custom content type header instead of application/x-www-form-urlencoded.

For a broader look at how these services compare beyond authentication, see the future of music API integration.

Token Refresh, Expiry, and Edge Cases by Service

Quick answer: Token refresh is where multi-service auth gets painful. Expiry times, refresh token rotation policies, and failure modes differ across every platform. Some services silently expire refresh tokens after 7 days of inactivity, others rotate them on every use, and a few require complete re-authorization.

Common edge cases that will break your app

Silent token invalidation: Some services revoke tokens when the user changes their password or revokes access from their account settings. Your stored tokens stop working with no webhook or notification. The only way to detect this is to handle 401 responses gracefully and trigger re-authentication.

Refresh token rotation: Several services issue a new refresh token with every token refresh request. If your app fails to store the new refresh token (because of a network error, a crash, or a race condition between concurrent requests), you lose access permanently. You need atomic token storage with retry logic.

Scope downgrade on refresh: At least two services return a narrower set of scopes when you refresh a token compared to the original authorization. If your app checks scopes at runtime, this mismatch causes unexpected permission errors.

Clock skew issues: Token expiry is based on timestamps. If your server's clock drifts by even 30 seconds, you may try to use expired tokens or refresh tokens too early (which some services treat as suspicious behavior). Always refresh proactively, at least 60 seconds before expiry.

Concurrent refresh requests: If two threads in your app try to refresh the same token simultaneously, the second request may fail because the first already consumed the refresh token. You need a mutex or queue for token refresh operations.

The operational cost

Every one of these edge cases requires its own error handling, retry logic, and monitoring. Multiply that by 12 services, and you are looking at a substantial chunk of your engineering time spent on auth maintenance rather than product development.

MusicAPI handles all of this behind a single OAuth flow. Token refresh, rotation, scope management, and error recovery happen automatically. You authenticate the user once through MusicAPI's auth initialization, and MusicAPI keeps the session alive across all connected services. Check out the authorization docs to see how this works under the hood.

Auth Requirements Across 12 Music Streaming Services

Quick answer: The table below compares OAuth version, token expiry, refresh token support, and required scopes across all 12 streaming services that support user authentication through MusicAPI.

ServiceOAuth VersionToken ExpiryRefresh TokenRefresh Token RotationTypical Scopes Required
SpotifyOAuth 2.01 hourYesNouser-read-private, user-library-read, playlist-modify-public
Apple MusicOAuth 2.0 + JWT6 months (developer token)N/A (developer token model)N/AMusicKit access
YouTubeOAuth 2.01 hourYesNoyoutube.readonly, youtube.force-ssl
TidalOAuth 2.024 hoursYesYes (single-use)user-read, playlists-read, playlists-write
Amazon MusicOAuth 2.0 (LWA)1 hourYesNoamazon_music:access
DeezerOAuth 2.0 (simplified)No expiryNoN/Abasic_access, manage_library, listening_history
SoundCloudOAuth 2.01 hourYesYesnon-expiring (single scope)
NapsterOAuth 2.024 hoursYesNoN/A (single access level)
QobuzOAuth 2.0VariesYesNoN/A (app-level access)
BoomplayOAuth 2.0VariesYesNoStandard read/write
AudiomackOAuth 2.01 hourYesNoStandard read/write
AudiusOAuth 2.0Session-basedNoN/ARead access (decentralized)

Key takeaways from this table:

  • Token expiry ranges from 1 hour to "no expiry." Your token management logic needs to handle all of these cases.
  • Refresh token rotation (where the refresh token itself changes on each use) requires atomic storage updates. Services with rotation will lock you out if you lose a refresh token.
  • Scope formats are not standardized. Some services use fine-grained scopes; others grant blanket access with a single scope.
  • One service uses a JWT-based developer token model instead of traditional OAuth user tokens, which requires a completely different implementation path.

You can explore each service's user profile endpoint to see the data available after authentication: Napster user profiles, Apple Music user profiles, and more across all supported services.

Code Example: One Auth Flow for All Services with MusicAPI

Quick answer: MusicAPI replaces 12 separate OAuth implementations with a single redirect-based flow. Initialize auth with one URL, handle one callback format, and get a unified user identifier that works across all services. No per-service token management required.

Here is how the entire authentication flow works with MusicAPI:

Step 1: Initialize authentication

Redirect your user to MusicAPI's authentication page. You can let them choose their service, or pre-select one:

// Generic: let the user pick their streaming service
const authUrl = `https://connect.musicapi.com/auth/{yourAccountSlug}?returnUrl=${encodeURIComponent('https://yourapp.com/callback')}`;

// Pre-select a specific service
const spotifyAuthUrl = `https://connect.musicapi.com/auth/{yourAccountSlug}?returnUrl=${encodeURIComponent('https://yourapp.com/callback')}&musicService=spotify`;

// With a unique ID for polling auth status
const authWithPolling = `https://connect.musicapi.com/auth/{yourAccountSlug}?returnUrl=${encodeURIComponent('https://yourapp.com/callback')}&uniqueId=${crypto.randomUUID()}`;

// Redirect the user
window.location.href = authUrl;

That is it for initialization. No client IDs per service. No scope strings to look up. No PKCE configuration. One URL pattern for all 12 services. See the full initialization docs for additional parameters.

Step 2: Handle the callback

After the user authenticates, MusicAPI redirects to your returnUrl with a base64-encoded data64 parameter:

// Express.js callback handler
app.get('/callback', async (req, res) => {
  const data = JSON.parse(
    Buffer.from(req.query.data64, 'base64').toString('utf-8')
  );

  // data.authModel.uuid: use this to fetch user info
  // data.authModel.status: 'success' or 'error'
  // data.integrationUserUUID: unique user identifier
  // data.integration.type: which service they connected (e.g., 'spotify')

  if (data.authModel.status === 'success') {
    // Fetch the authenticated user's profile
    const userInfo = await fetch(
      `https://api.musicapi.com/app/integrations/${data.authModel.uuid}`,
      { headers: { 'Content-Type': 'application/json' } }
    );

    const profile = await userInfo.json();
    // profile.integrationUser contains: name, email, imageUrl, country
    // Store profile.integrationUser and data.authModel.uuid in your database

    res.redirect('/dashboard');
  } else {
    res.redirect('/auth-error');
  }
});

The callback format is identical regardless of which streaming service the user picked. Full callback reference: authentication callback docs.

Step 3: Access original tokens (optional)

If you need the service's raw access token for direct API calls, request it from your backend:

// Backend only: requires your Client Secret
const response = await fetch(
  `https://api.musicapi.com/public/integrations/user/${integrationUserUUID}`,
  {
    headers: {
      'Authorization': `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`,
      'Content-Type': 'application/json; charset=utf-8'
    }
  }
);

const userData = await response.json();
// userData.authData.accessToken: the service's raw access token
// userData.authDataExpiresAt: expiry timestamp in milliseconds

See the original auth tokens documentation for the one-time-token approach for frontend access.

What you did not have to build

With MusicAPI handling authentication, you skipped:

  • 12 separate OAuth client registrations and configurations
  • Per-service scope management and format differences
  • Token refresh logic for 12 different expiry windows
  • Refresh token rotation handling and atomic storage
  • PKCE implementation for services that require it
  • Error handling for 12 different error response formats
  • Monitoring and alerting for auth failures across services

For the full list of features available after authentication, check the supported features matrix and available endpoints.

Storing and Managing Tokens Securely

Quick answer: When using MusicAPI, you store one identifier per user (the authModel.uuid or integrationUserUUID) instead of raw tokens. If you are managing tokens directly, encrypt at rest, use short-lived access tokens, and never expose refresh tokens to the client.

If you use MusicAPI

Your token storage simplifies to a single database column: the integrationUserUUID returned during authentication callback. MusicAPI manages the underlying access and refresh tokens for each service. You never see or store raw streaming service tokens unless you explicitly request them through the original auth tokens endpoint.

Keep the authModel.uuid secure. Anyone with this identifier can retrieve user data through MusicAPI's API. Treat it with the same care you would treat a session token.

If you manage tokens directly

For teams that need to store raw service tokens (retrieved via MusicAPI's original token endpoint or obtained directly from services):

Encrypt tokens at rest. Use AES-256 or your cloud provider's KMS. Never store raw access or refresh tokens in plaintext; not in your database, not in environment variables, not in logs.

Separate access and refresh token storage. Store refresh tokens in a higher-security tier than access tokens. If an attacker compromises your access token store, they get tokens that expire in minutes or hours. If they get refresh tokens, they have persistent access.

Implement token refresh as a background job. Do not refresh tokens synchronously during user requests. Run a background worker that refreshes tokens 60 to 120 seconds before they expire. This prevents latency spikes and handles services with strict rate limits on auth endpoints.

Use a mutex for refresh operations. Only one process should refresh a given user's token at a time. Use a distributed lock (Redis, database advisory lock, or similar) to prevent concurrent refresh requests from invalidating each other.

Rotate encryption keys. If your token encryption key is compromised, you need to re-encrypt all stored tokens with a new key. Build this capability before you need it.

Audit token access. Log every token retrieval and refresh operation with the requesting service, user ID, and timestamp. This helps you detect unauthorized access and debug auth failures.

FAQ

How does OAuth work for music streaming APIs?

Each music streaming service implements OAuth 2.0 with its own authorization endpoint, token endpoint, scope format, and token lifetime. Your app redirects users to the service's authorization page, receives an authorization code on callback, and exchanges it for access and refresh tokens. The implementation details differ significantly per service, which is why tools like MusicAPI exist to unify them.

Do all music streaming services use OAuth 2.0?

All 12 services that support authenticated user access use some variant of OAuth 2.0, but the implementations differ. Most follow the standard Authorization Code flow. One service uses JWT-based developer tokens instead of traditional user OAuth tokens. A few use simplified OAuth flows without refresh tokens. Check the supported music services page for the current list.

How do I handle token refresh across multiple music services?

Each service has different token expiry times (1 hour to 12 months), and some rotate refresh tokens on every use. You need per-service refresh logic, atomic token storage, and error handling for each service's failure modes. MusicAPI automates this entirely: authenticate once through the unified auth flow, and MusicAPI handles all token lifecycle management behind the scenes.

What scopes do I need for music API authentication?

Scope requirements vary by service and by what data you need. Most services require at least a read-profile scope. Playlist access, library read/write, and playback control each require additional scopes. Some services use a single blanket scope while others have granular permission strings. MusicAPI manages scope negotiation for you based on the features you need.

Can I authenticate users with multiple music services simultaneously?

Yes. Each user can connect multiple streaming accounts. With MusicAPI, each service connection produces its own integrationUserUUID. Store all of them against the same user in your database. The authentication callback tells you which service was connected via the integration.type field.

How do I handle authentication errors across different music APIs?

Each service returns errors in different formats and uses HTTP status codes inconsistently. A 401 might mean "expired token" on one service and "invalid client" on another. MusicAPI normalizes these errors through a consistent callback format: check authModel.status for success or error, and use the included error message for debugging. See the rate limiting docs for handling throttled auth requests.

Is MusicAPI free to use for authentication?

MusicAPI offers a free trial to get started. Check the pricing page for details on plans and usage limits. You can also contact the team for enterprise plans or custom requirements.


Ready to skip months of OAuth and SDK work? Start your free MusicAPI trial and connect all 12 streaming services with one unified API. Get started with the authentication docs and have your first user connected in minutes.