MusicKit web 403 error issue

Hello!

I am currently working on a react.js application that is integrating with the MusicKit v3 library. I have followed the documentation to generate a JWT for MusicKit and add the library to my application.

Using my token I am able to successfully retrieve song information from the Apple Music API, but I am having trouble with authentication.

When I call music.authorize() and successfully go through the Apple sign in popup, I am receiving the following 403 error:

https://play.itunes.apple.com/WebObjects/MZPlay.woa/wa/webPlayerLogout 403 musickit.js:44 Uncaught (in promise) AUTHORIZATION_ERROR: Unauthorized

After stepping through the music kit API and login popup with breakpoints, I am seeing that the music user token is null, despite the login popup succeeding and returning a proper token/response:

{"isAppleMusicSubscriber":"true","musicUserToken":"Ak4ItOgRRRG2y6xgA/OeWQPK0RqPQ/esAJkRN0B/Ua/AWLT52tLhd2TfzMK6uhH+Nczvd7wjYDM1UewG/NledKtimwlrR+s5tdQPk/FG28zqhBqXZ12q6LC516w8ELZDwv5T61kV8xiJ1KSO1q4pGi01JO7SuPMtOqB/QsycYj+xNnrYUEwlP5tm/zxfg7bWmvuWMwfUruYR+A1U9FdXZsdIITVmxCjiHg8ro9xXRzl6Txhsag\u003d\u003d","cid":"REDACTED","itre":"REDACTED","supported":"REDACTED"}

I have tested my application with multiple Apple Music users who have paid subscriptions. All accounts are receiving this same error.

I have tried regenerating my JWT token multiple times following various guides. My latest attempt used the following node library and parameters:

var jwt = require('jsonwebtoken');
var fs = require('fs');

var privateKey = fs.readFileSync('./AuthKey_MYKEY.p8');

let now = new Date();
let nextMonth = new Date(now.getFullYear(), now.getMonth() + 1, now.getDate());
let nowEpoch = Math.round(now.getTime() / 1000); // number of seconds since Epoch, in UTC
let nextMonthEpoch = Math.round(nextMonth.getTime() / 1000); // number of seconds since Epoch, in UTC

var payload = {
    iss: 'REDACTED', // TEAM ID
    iat: nowEpoch,
    exp: nextMonthEpoch
};

var options = {
    algorithm: 'ES256',
    header: {
        alg: 'ES256',
        kid: 'REDACTED' // KEY ID
    }
};

jwt.sign(payload, privateKey, options, function(error, token) {
    console.log(error);
    console.log(token);
});

I have a valid App Identifier created with the MusicKit App Service enabled.

I am stuck! I have no other ideas on the possible root cause here. Is there something I am missing? I have a mobile app currently in Test Flight - does this app need to be released to the app store? I am out of guesses!

Any support here would be greatly appreciated!

Thank you for your time.

Patrick

  • For those who are running in to similar error in Django, you need to explicitly set SECURE_REFERRER_POLICY in settings.py. Django's default referrer-policy is "same-origin", so give something like SECURE_REFERRER_POLICY = "no-referrer-when-downgrade" or SECURE_REFERRER_POLICY = "strict-origin-when-cross-origin".

Add a Comment

Accepted Reply

To anyone encountering an issue similar to this, the issue is your referrer-policy settings. I'm using strapi which uses helmetjs out of the box. My referrer-policy was configured to "no-referrer" by default, but setting it to "origin" fixed this auth issue.

Replies

Hi there,

I have the same issue. Were you able to resolve?

What fixed it for me was that my site was not hosted -- I was testing it out locally this entire time.

I used Github's free hosting and I don't get error 403 anymore. I think authorize() requires a site URL to generate a music user token, and not a local path on your hard drive

I see this issue both on localhost and my remote server where I generate the key, so I think my issue is different. Thank you for the reply though!

Similar Issue... We are developing an app that also uses MusicKit. We're able to connect to the Apple service, search and play music, but things go off the rails with a 403 error when we try to get individual user information such as playlists. It seems to be somewhat random, but if you navigate to Apple Music > Account Info and edit "Apps with Access" and remove your app entry, (to try and create a new one..) a new one never seems to be generated even though the requests for access are successful and tokens are returned. Dead in the water as well...

Hi did you ever end up finding a solution to this?

I never found a solution. I migrated to musickit v1, but auth is still not working for my app. I'm not sure if it's somehow related to using reactjs for my front end. Any help is appreciated!

To anyone encountering an issue similar to this, the issue is your referrer-policy settings. I'm using strapi which uses helmetjs out of the box. My referrer-policy was configured to "no-referrer" by default, but setting it to "origin" fixed this auth issue.

This is what's working for me on Chrome.

Just getting started so the code isn't exactly pretty. I have the music kit stuff in a class, but have altered the code here to hopefully make sense without that context.

/* token creation */

import jwt from 'jsonwebtoken'

const private_key = fs.readFileSync('apple_private_key.p8').toString()
const team_id = process.env.APPLE_TEAM_ID;
const key_id = process.env.APPLE_KEY_ID;

const token = jwt.sign({}, private_key, {
    algorithm: 'ES256',
    expiresIn: '180d',
    issuer: team_id,
    header: {
        alg: 'ES256',
        kid: key_id
    }
})
/* token use */

/* Wait for MusicKit to be available. This is just for now. Clean up in future. */
const MK = await new Promise((resolve, reject) => {
    const mkInterval = setInterval(() => {
         if (window.MusicKit) {
             clearInterval(mkInterval)
             resolve(window.MusicKit)
         }
    }, 500)

    setTimeout(() => {
        clearInterval(mkInterval)
        reject(new Error("MusicKit not detected"))
    }, 5000)
})

await MK.configure({
    developerToken: token
    app: {
        name: app_name
    }
})

const instance = MK.getInstance()

const authorizeUser = async () => {
    try {
        const user = await instance?.authorize()
        console.log({ user })
    } catch (err) {
        console.error("Authorization Error:", err)
    }
}