KIMB-technologies/Radio-API

Authentication for token-protected stream

SpeedyGoneZales opened this issue · 4 comments

I'm trying to get my Roberts 94i (based on the Silicon Frontier Venice 6.5 platform, firmware ir-mmi-FS2026-0500-0515-Stream94i_V2.14.35c.EX86167-V1.04), working with BBC Radio streams (again).
NB: BBC now uses MPEG-DASH, standard, Mozilla Developer Guide.

BBC streams use token-authenticated URLs, which means entering such a URL into favorites works only while the token is valid (a couple of days). After that, a new token is needed.

Packet capture reveals the following:

  1. Radio obtains an preliminary token by querying
    roberts.wifiradiofrontier.com/setupapp/Roberts/asp/BrowseXML/loginXML.asp?token=0

  2. Preliminary token is returned in an XML
    <EncryptedToken>3a3f5ac48a1dab4e</EncryptedToken>

  3. Radio requests stream URL
    roberts.wifiradiofrontier.com/setupapp/Roberts/asp/BrowseXML/Search.asp?sSearchtype=3&Search=1022963300812989&mac=df5a6f351be63ed3a85ea39f2aa9fd8a&dlang=eng&fver=8&ven=rob29

  4. MPD is returned:

    <?xml version="1.0" encoding="utf-8"?>
    <MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:dvb="urn:dvb:dash:dash-extensions:2014-1"
      xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
      type="dynamic" availabilityStartTime="1969-12-31T23:59:44Z"
      minimumUpdatePeriod="PT6H" timeShiftBufferDepth="PT6H" maxSegmentDuration="PT7S" minBufferTime="PT3.200S"
      profiles="urn:dvb:dash:profile:dvb-dash:2014,urn:dvb:dash:profile:dvb-dash:isoff-ext-live:2014"
      publishTime="2023-09-04T15:44:11">
        <UTCTiming schemeIdUri="urn:mpeg:dash:utc:http-iso:2014" value="http://time.akamai.com/?iso" />
        <BaseURL dvb:priority="1" dvb:weight="1" serviceLocation="cf">http://as-dash-ww.live.cf.md.bbci.co.uk/pool_904/live/ww/bbc_radio_fourfm/bbc_radio_fourfm.isml/dash/</BaseURL>
        <Period id="1" start="PT0S">
        <AdaptationSet group="1" contentType="audio" lang="en" minBandwidth="48000" maxBandwidth="96000"
                       segmentAlignment="true" audioSamplingRate="48000" mimeType="audio/mp4" codecs="mp4a.40.5" startWithSAP="1">
            <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
            <Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
            <SegmentTemplate timescale="48000" initialization="bbc_radio_fourfm-$RepresentationID$.dash"
                           media="bbc_radio_fourfm-$RepresentationID$-$Number$.m4s" startNumber="1" duration="307200"/>
            <Representation id="audio=48000" bandwidth="48000"/>
            <Representation id="audio=96000" bandwidth="96000"/>
        </AdaptationSet>
      </Period>
    </MPD>
    
  5. Radio then sends this:
    redirect.airable.io/1807976396573832

  6. Which returns:
    http://open.live.bbc.co.uk/mediaselector/6/redir/version/2.0/mediaset/audio-syndication/proto/http/transferformat/dash/vpid/bbc_radio_fourfm?jwt_auth=eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjIiLCJpc3MiOiJ1ay5jby5iYmNfcmFkaW9zcGkiLCJhYWYiOnRydWV9.eyJzdWIiOiJjb20uYWlyYWJsZW5vdyIsImF1ZCI6ImJiY3JhZGlvIiwiY3ZpZHMiOlsidXJuOmJiYzpwaXBzOnBpZDpiYmNfcmFkaW9fZm91cmZtIl0sImlzcyI6InVrLmNvLmJiY19yYWRpb3NwaSIsImlhdCI6MTcwNjQ1OTU2NSwidmVyIjoxLCJleHAiOjE3MDY2MzIzNjV9.C1fdKHvoKgYxgtJEavBk-EfsatmeFTsrCHNqJTvUYfDb8ylgs3lQDaAtCoIHoneGQq5iUBBmdwmOrUYNAk_T5w

  7. Radio then sends the above URL, which returns a slightly different MPD:

    <?xml version="1.0" encoding="utf-8"?>
    <MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:dvb="urn:dvb:dash:dash-extensions:2014-1"
      xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
      type="dynamic" availabilityStartTime="1969-12-31T23:59:44Z"
      minimumUpdatePeriod="PT6H" timeShiftBufferDepth="PT6H" maxSegmentDuration="PT7S" minBufferTime="PT3.200S"
      profiles="urn:dvb:dash:profile:dvb-dash:2014,urn:dvb:dash:profile:dvb-dash:isoff-ext-live:2014"
      publishTime="2023-09-04T15:44:11">
        <UTCTiming schemeIdUri="urn:mpeg:dash:utc:http-iso:2014" value="http://time.akamai.com/?iso" />
        <BaseURL dvb:priority="1" dvb:weight="1" serviceLocation="ak">http://as-dash-ww-live.akamaized.net/pool_904/live/ww/bbc_radio_fourfm/bbc_radio_fourfm.isml/dash/</BaseURL>
        <Period id="1" start="PT0S">
        <AdaptationSet group="1" contentType="audio" lang="en" minBandwidth="48000" maxBandwidth="96000"
                       segmentAlignment="true" audioSamplingRate="48000" mimeType="audio/mp4" codecs="mp4a.40.5" startWithSAP="1">
            <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
            <Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
            <SegmentTemplate timescale="48000" initialization="bbc_radio_fourfm-$RepresentationID$.dash"
                           media="bbc_radio_fourfm-$RepresentationID$-$Number$.m4s" startNumber="1" duration="307200"/>
            <Representation id="audio=48000" bandwidth="48000"/>
            <Representation id="audio=96000" bandwidth="96000"/>
        </AdaptationSet>
      </Period>
    </MPD>
    
  8. Radio then requests:
    open.live.bbc.co.uk/mediaselector/6/redir/version/2.0/mediaset/audio-syndication/proto/http/transferformat/dash/vpid/bbc_radio_fourfm?jwt_auth=eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjIiLCJpc3MiOiJ1ay5jby5iYmNfcmFkaW9zcGkiLCJhYWYiOnRydWV9.eyJzdWIiOiJjb20uYWlyYWJsZW5vdyIsImF1ZCI6ImJiY3JhZGlvIiwiY3ZpZHMiOlsidXJuOmJiYzpwaXBzOnBpZDpiYmNfcmFkaW9fZm91cmZtIl0sImlzcyI6InVrLmNvLmJiY19yYWRpb3NwaSIsImlhdCI6MTcwNjQ1OTU2NSwidmVyIjoxLCJleHAiOjE3MDY2MzIzNjV9.C1fdKHvoKgYxgtJEavBk-EfsatmeFTsrCHNqJTvUYfDb8ylgs3lQDaAtCoIHoneGQq5iUBBmdwmOrUYNAk_T5w

  9. Which finally returns a playable stream URL:
    http://a.files.bbci.co.uk/ms6/live/344XXXXX-XXXX-XXXX-XXXX-XXXXXXXXXA4B/audio/simulcast/dash/uk/pc_hd_abr_v2/cf/bbc_radio_fourfm.mpd (token redacted)

JWT decoded as follows:

    Header:
    {
      "alg": "ES256",
      "typ": "JWT",
      "kid": "2",
      "iss": "uk.co.bbc_radiospi",
      "aaf": true
    }
    Payload:
    {
      "sub": "com.airablenow",
      "aud": "bbcradio",
      "cvids": [
        "urn:bbc:pips:pid:bbc_radio_fourfm"
      ],
      "iss": "uk.co.bbc_radiospi",
      "iat": 1706459565,
      "ver": 1,
      "exp": 1706632365
    }

(valid for two days).

Now I know I never signed into anything, nor was there another mechanism to register the radio somewhere.
In other words, whatever the authentication mechanism is, it must rely on knowable properties the radio can transmit, e.g. the User-Agent FS L IR/0.1, or possibly the MAC (starting with 00:22:61), although I couldn't find that in any of the packets.

Can we replicate this authentication mechanism to get a valid token, and rotate that as needed?

Hi,

the <EncryptedToken>3a3f5ac48a1dab4e</EncryptedToken> is always the same and also returned by Radio-API (https://github.com/KIMB-technologies/Radio-API/blob/master/php/index.php#L30C38-L30C54). As far as I know, this token is used by the radio to validate that it connected to a working api server.

Did you test to set one of the following urls for the station:

  • http://shim-pri.wifiradiofrontier.com/vtuner/radio/1022963300812989/play/de_8_rob29?
  • http://redirect.airable.io/1807976396573832

The requests/ responses before these urls seem to be equal to the ones sent by Radio-APIs.

1807976396573832 seems to be the ID of BBC used by Silicone Frontier. I then assume that http://redirect.airable.io/1807976396573832 does the token generation on the server side and redirects to the correct token/ streaming url each time it gets a request.

Thanks for your response.
So far, using both http://redirect.airable.io/1807976396573832 and also http://a.files.bbci.co.uk/ms6/live/344XXXXX-XXXX-XXXX-XXXX-XXXXXXXXXA4B/audio/simulcast/dash/uk/pc_hd_abr_v2/cf/bbc_radio_fourfm.mpd still work.
I expected they would expire in line with the JWT, but that doesn't seem to be the case.

Hi,
as long as these links work, I would not make any changes to Radio-API.
If such links do not exist any more, we will need to consider it again.

Fair!
I guess what is needed is a kind of service that handles authentication and provides a redirect from the source URL.
This could be a service different to Radio-API all together.