This app is not authorized to play protected files. DRM video on iOS react native

{"code": null, "data": {"code": -11836, "message": "This app is not authorized to play protected files.", "underlyingError": {"code": -11836, "description": "Error Domain=AVFoundationErrorDomain Code=-11836 \"See -[AVPlayerItem errorLog] for 1 events\" UserInfo={NSLocalizedDescription=Cannot Open, NSUnderlyingError=0x600003381230 {Error Domain=AVFoundationErrorDomain Code=-11836 \"Cannot Open\" UserInfo={NSDescription=Cannot Open}}, NSDebugDescription=See -[AVPlayerItem errorLog] for 1 events, NSLocalizedFailureReason=This app is not authorized to play protected files.}", "domain": "AVFoundationErrorDomain", "localizedDescription": "Cannot Open"}}, "message": "Source Error. This app is not authorized to play protected files.", "name": "onSourceError", "timestamp": 1692293117.623472}

While playing DRM videos on iOS I am facing this error. The video is encoded via Pallycon. It works perfectly fine on Android.

const headers: Record<string, string> = {
        'pallycon-customdata-v2': pallyconToken,
        'Content-Type': 'application/octet-stream',
      };
fairplay: {
          licenseUrl: 'https://license.pallycon.com/ri/licenseManager.do',
          // FairPlay certificate. Required for iOS.
          certificateUrl:
            'https://license-global.pallycon.com/ri/fpsKeyManager.do?siteId=KL48',
          licenseRequestHeaders: headers,
          certificateRequestHeaders: headers,
          prepareContentId: function (cId) {
            return cId.substring(cId.indexOf('skd://') + 6);
          },
        },

Dear @developer , thanks for sharing this issue. This error indicate that the Fairplay certificate provided using certificateUrl is not correct or is not in expected format.

Looking at the content of certificate https://license-global.pallycon.com/ri/fpsKeyManager.do?siteId=KL48, it contains base64 encoded certificate string. Can you please try using FairplayConfig.prepareCertificate configuration to decode base64 string into Data object. Sharing a sample code snippet below. Please be aware that I have not tested below snippet with your asset but it provides a sample of how to use prepareCertificate to decode base64 certificate content and pass a data buffer to player.

fpsConfig.prepareCertificate = { (certificateData: Data) -> Data in
                guard let stringData = String(data: certificateData, encoding: .utf8),
                      let result = Data(base64Encoded: stringData) else {
                    return certificateData
                }
                return result
            }

Kindly try this and let me know if this worked or if you have any followup questions.

Could you please provide a solution for the bitmovin react native player? @lucky.goyal

I do not have a sample for React native but the principal remains same. Just configure prepareCertificate function in your fairplay: configuration(similar to prepareContentId function) and add code to convert the certificate data(function argument) from base64 string to a array buffer. For reference you can find similar configuration in javascript for Bitmovin web player at https://github.com/inka-pallycon/html5-player-drm-samples/blob/main/js/bitmovin-sample.js#L32-L42

Hope this helps.

This suggestion is not working, as the types and all are different in the react native sdk. I have done that implementation in web and that works but unable to do that in react native sdk. @lucky.goyal

Found this as log in XCode @lucky.goyal @hristo.yankov

2023-08-18 11:33:37.859858+0530 TagMango[98175:20945615] [assertion] Error acquiring assertion: <Error Domain=RBSServiceErrorDomain Code=1 "target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit" UserInfo={NSLocalizedFailureReason=target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit}>

Thanks for the update. Glad to hear that the web configuration works, this confirms that the config is correct. To enable us provide a working sample for React Native, we will need access to your test asset along with complete Fairplay configuration(including licenseRequestHeaders and certificateRequestHeaders). So please share the same with us. Please feel free to open a ticket to share the information or you can also DM the details.

Have sent you the details in dm @lucky.goyal

1 Like

Hi @developer , glad to hear that the playback works with latest shared configuration. Sharing required configuration below for other users who use Pallycon DRM with Bitmovin React native SDK for iOS. Below sample code uses a sample Pallycon DRM protected asset.

  1. Pallycon seems to provide 2 types of Fairplay certificate URLs. The one demonstrated in the sample below returns a base64 encoded certificate string. To use this one prepareCertificate configuration needs to be used to perform a base64 decode. The sample below uses react-native-base64 - npm module for base64 decoding but applications can use any base64 decoding code/module.

  2. The Fairplay key(CKC) returned by Pallycon server is base64 encoded string. So prepareLicense configuration needs to be used to perform a base64 decode.

  3. Finally, Pallycon seems to also provide an alternative Fairplay certificate URL of the form https://license-global.pallycon.com/ri/fpsCert.do?siteId=DEMO which returns the Fairplay certificate in raw binary form. In this case prepareCertificate configuration is NOT required to be used.

const headers: Record<string, string> = {
  'pallycon-customdata-v2': 'eyJrZXlfcm90YXRpb24iOmZhbHNlLCJyZXNwb25zZV9mb3JtYXQiOiJvcmlnaW5hbCIsInVzZXJfaWQiOiJ0ZXN0LXVzZXIiLCJkcm1fdHlwZSI6IkZhaXJQbGF5Iiwic2l0ZV9pZCI6IkRFTU8iLCJoYXNoIjoiY21NZkZPUExrakErbTVLZ3BKS09vVnVmRTVTc3hKdVlTUm1jUWM1dmlVUT0iLCJjaWQiOiJiaWdidWNrYnVubnkiLCJwb2xpY3kiOiJuNXgyOHVZbURkUENGaW1vTTNuR053PT0iLCJ0aW1lc3RhbXAiOiIyMDIxLTAxLTA2VDA5OjI0OjI4WiJ9',
  'Content-Type': 'application/octet-stream',
};

const source: SourceConfig = {
  url: 'https://contents.pallycon.com/bunny/hls/master.m3u8',
  type: SourceType.HLS,
  drmConfig: {
    fairplay: {
      licenseUrl: 'https://license-global.pallycon.com/ri/licenseManager.do',
      // FairPlay certificate. Required for iOS.
      certificateUrl:
          'https://license-global.pallycon.com/ri/fpsKeyManager.do?siteId=DEMO',
          //'https://license-global.pallycon.com/ri/fpsCert.do?siteId=DEMO',
      licenseRequestHeaders: headers,
      certificateRequestHeaders: headers,
      prepareContentId: function (cId) {
        console.log(
            '\n[PREPARE CONTENT ID]\ncontentId:',
            cId.slice(0, 256) + '...\n'
        );
        return cId.substring(cId.indexOf('skd://') + 6);
      },
      prepareCertificate: (certificate) => {
        console.log(
            '\n[PREPARE CERTIFICATE]\ncertificate:',
            certificate.slice(0, 256) + '...\n'
        );
   
        // code if using base64 encoded certificate content
        var raw = base64.decode(certificate);
        console.log(
            '\n[PREPARE CERTIFICATE]\ndecoded certificate:',
            raw.slice(0, 256) + '...\n'
        );
        return raw;
      },
      prepareLicense: (license) => {
        console.log(
            '\n[PREPARE LICENSE]\nlicense:',
            license.slice(0, 256) + '...\n'
        );

        var raw = base64.decode(license);
        console.log(
            '\n[PREPARE LICENCE]\ndecoded license:',
            raw.slice(0, 256) + '...\n'
        );
        return raw;
      }
    },
  },
};

This topic was automatically closed 60 minutes after the last reply. New replies are no longer allowed.