Search code examples
sonos

Sonos authentication when requesting a stream


Apologies, in advance, that this question is probably too vague to be admitted into the cannon of good StackOverflow questions. However it does reflect the current state of my knowledge of this domain.

Sonos provides the ability for a 3rd Party Service to offer Sonos users access to a music service. This I understand, and the documentation provided by Sonos is comprehensive.

However, we have the scenario of Service Provider A who provides users with the following services:

  1. Access to streaming radio (for which A has the rights and can provide the stream)
  2. Access to on demand / catch-up content (for which A has the rights and can provide the stream)
  3. Ability to create playlists of music played within 1 & 2 (for which A does not have the rights, and instead provides the stream via one or more 3rd Party music services that the user has an account with).

This works perfectly well in the context of A's own apps - which include integrations with 3rd party music services who provide the stream for content that comes under 3 (i.e. if you are a user of A, then while you can create playlists, if you want to actually play a track from the playlist then need an account with a service provider who has the rights to that particular track).

However, I am struggling to reason about this in the context of Sonos.

If, as a user of A, I have the following container:

Container1

  • item1 ('podcast' belonging to Service A)
  • item2 (song, belonging to Service B)

I am registered with both Service A and Service B, and both Service A & Service B are available separately on Sonos and both use DeviceLink for authentication (lets for the purposes of this example assume that Service B is Spotify).

If the user requests the container, adds item1 to their queue and then presses play, the Player will request the streaming uri from Service A, and Service A will return it in the format:

http://service-a.uri/some-file

The player will then perform a GET request on this uri, and the item will start playing.

However, if the user adds item2 to their queue and then presses play, Service A will return a streaming uri belonging to Service B like this:

http://service-b.uri/some-file

In this case, how is authentication handled?

The user is authenticated as follows:

Within Service A:

  • To Service A
  • To Service B, via Service B's API.

Within Sonos:

  • To Service A
  • To Service B

However, Sonos is going to send Service A's credentials to Service B, and thus the stream will fail (because why would it know that Service A has a pre-existing relationship with Service B whereby Service A users consume content from Service B, if said user already has an account with Service B).

So there is no way to achieve what I am looking to do in the context of Sonos, or am I fundamentally misunderstanding something here?


Solution

  • That is a really great question.

    For streaming Sonos requests the uri with the getMediaUri request. This uri is then used to stream the content. If uri returned as a result of this request is streamable then there should not be an issue. It is possible to include headers that should be sent with the uri request and that can also be used if some additional authentication is required. (For example passing an authentication token to Service B). However the requirement here is the Service A would have everything it needs to properly pass this information to Sonos so that Sonos can include it in its request to Service B.

    For security reasons Sonos does not currently have a way to pass Service Bs authentication token or information to Service A; nor is there a way for the Sonos player to know that a url it is requesting which was provided by Service A is actually intended for Service B. There is also no way for the player to inform Service A that the user also has Service B installed.

    This is something we have thought about and will consider providing a mechanism to support this in the future.