After your service completes its response to getDeviceAuthToken
, Sonos sets the SOAP header of the rest of the Sonos Music API calls to include a credentials
element. This element contains the information needed for your service to continue to authenticate the user for all Sonos API calls. Here are the credentials
header sub-elements relevant to authentication:
loginToken
— The authentication information for the user making the request. This includes the following sub-elements:
token
– The initial value is from the userauthToken
your service returned for thegetDeviceAuthToken
call made when authenticating the user. Your service manages thetoken
.key
– The initial value is from theprivateKey
your service returned in the samegetDeviceAuthToken
call. Your service manages thekey
.householdId
– The household ID associated with the user’s current Sonos system. This is the same value the Sonos app sends to your service in thegetAppLink
request.
For the complete list of credentials
sub-elements see the SOAP header section in SOAP requests and responses. The authentication API calls getAppLink
and getDeviceAuthToken
are the only calls that will not typically contain credentials. (If a Sonos player is in the process of upgrading the authentication mode, getDeviceAuthToken
includes credentials as described in Upgrade to OAuth.)
Validate the authentication token
Ensure the token
supplied is valid for this user. Initially, tokens are created by your authorization service and supplied in the authToken
during your service’s getDeviceAuthToken
processing. If the token
does not a match for this user, return a SOAP fault to indicate the account is not valid. Return the Client.LoginUnauthorized
faultcode
. In the faultstring
, add a log message for the Sonos app and player log files. Sonos displays this message in Sonos diagnostics sent by users for debugging and troubleshooting.
1 2 3 4 |
<[soap]:Fault> <faultcode>Client.LoginUnauthorized</faultcode> <faultstring>Log-Message</faultstring> </[soap]:Fault> |
As an option, you may also wish to use the householdId
to further validate the token but it this is not required. For example, you may choose to store the householdId
value and associate it with the token when it is generated. Then, your service can later check the stored householdId
against the value supplied in future API requests that use that token.
Refresh expired authentication tokens
To maintain session security, authentication tokens should have a short life. This section explains how to refresh tokens and to re-authenticate Sonos with your service without user interaction, providing for an uninterrupted user experience.
Sonos offers your service two different ways to refresh tokens. Generally, you can refresh tokens using a SOAP fault. If your service needs to refresh a token during an HTTP request, Sonos sends a refreshAuthToken
request to your service to update the token.
Note: Sonos players propagate new credentials to other Sonos players and Sonos apps, but Sonos apps do not. If your service refreshes a request from a Sonos app (indicated by a device name in the user-agent), you may need to honor the same refresh token when handling a token refresh request from Sonos players.
See Initialize refresh tokens to continue.
If you don’t use refresh tokens, require manual log in
If you do not implement refresh tokens, when the token
expires, return the Client.AuthTokenExpired
fault in response to getMetadata
and getMediaURI
to indicate the user must manually log in and authenticate again. In the faultstring
, add a log message for this fault code.
1 2 3 4 |
<[soap]:Fault> <faultcode>Client.AuthTokenExpired</faultcode> <faultstring>Log-Message</faultstring> </[soap]:Fault> |
You do not need to return this fault in response to getLastUpdate
or getMediaMetadata
. When the Sonos speaker makes sends a getMediaMetadata
request and it fails, it does not start playback. The user will also see that playback failed.
Initialize refresh tokens
To start using refresh tokens, your authorization service generates a private key and returns it in the privateKey
field of your getDeviceAuthToken
response along with an authorization token in authToken
. Your service needs to maintain an association between the user, the token, and the key. The private key represents the refresh token for this authorization token. You are free to use any format you wish for private keys using up to 2048 characters.
When a user later does something such as a browse request, Sonos includes both the token
and the key
in the header credentials of every API request, as shown below.
1 2 3 4 5 6 7 8 |
<ns:credentials> . . . <ns:loginToken> <ns:token>AUTH-TOKEN<ns:token> <ns:key>REFRESH-TOKEN</ns:key> <ns:householdId>HOUSEHOLD-ID</ns:householdId> </ns:loginToken> </ns:credentials> |
Refresh expired tokens using a SOAP fault
When your service receives an API request, do the following for refresh token processing:
Verify that the token
and key
in the API request header are valid for this user. If valid, processing is done. If the token
and key
are not valid, or if the token
in the API request header has expired, follow the steps below to refresh the authentication token.
- Generate a new authentication token.
- Return the
Client.TokenRefreshRequired
SOAP fault shown below for the current API request:
1234567891011121314<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.sonos.com/Services/1.1"><s:Body><s:Fault><faultcode>s:Client.TokenRefreshRequired</faultcode><faultstring>Log-Message</faultstring><detail><ns:refreshAuthTokenResult><ns:authToken>NEW_TOKEN</ns:authToken><ns:privateKey>REFRESH_TOKEN</ns:privateKey></ns:refreshAuthTokenResult></detail></s:Fault></s:Body></s:Envelope>- Include the new authentication token in
authToken
. - Include the refresh token in
privateKey
, even if your service has not changed it. You determine the refresh token policy, but you must return it even if it hasn’t changed.
- Include the new authentication token in
- This fault causes Sonos to update both the
token
andkey
credentials in the header for all subsequent API requests. - Sonos retries the initial API request with the new credentials.
If a token refresh fails, what you return will depend on what behavior you want.
Retry the token refresh process
Return a Server.ServiceUnknownError
error with a custom message that asks the user to try the action again in a few moments. See the Custom error messages section in Error handling for details. See Handle auth errors for details on errors specific to authentication.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.sonos.com/Services/1.1"> <soap:Body> <soap:Fault> <faultcode>Server.ServiceUnknownError</faultcode> <faultstring>Log-Message</faultstring> <detail> <ns:ExceptionInfo>Retry in a few moments. </ns:ExceptionInfo> <ns:SonosError>34</ns:SonosError> </detail> </soap:Fault> </soap:Body> </soap:Envelope> |
Make the user reauthorize
Return a Client.AuthTokenExpired
fault. This causes Sonos to give the user a prompt to re-authorize and go through the authorization process again.
1 2 3 4 5 6 7 8 |
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"> <soap-env:Body> <soap-env:Fault> <faultcode>Client.AuthTokenExpired</faultcode> <faultstring>Log-Message</faultstring> </soap-env:Fault> </soap-env:Body> </soap-env:Envelope> |
Refresh expired tokens with refreshAuthToken
Sonos calls refreshAuthToken
when an HTTP REST request returns a 401 error. The 401 error may indicate an expired authorization token. Your service should send a new authToken
and either the existing privateKey
or a new one in your response. Sonos will retry the original request using the authToken
from your response as the OAuth bearer token in an Authorization
header. Sonos will only retry the HTTP request once. If it fails again, Sonos will display a failure message. See REST request for details.
When an HTTP REST request returns a 401 error, the Sonos app sends a refreshAuthToken
request like the one shown below. There are no parameters, but Sonos sends the current authToken
and privateKey
in the header as the token
and key
elements respectively.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://www.sonos.com/Services/1.1"> <s:Header> <credentials> <loginToken> <token>12345678</token> <key>123456789</key> <householdId>Sonos_1234EJUN334GGPBMoESCwBABCD</householdId> </loginToken> <deviceId>B8-E9-37-BD-19-E2:2</deviceId> <deviceProvider>Sonos</deviceProvider> </credentials> </s:Header> <s:Body> <refreshAuthToken xmlns="http://www.sonos.com/Services/1.1"/> </s:Body> </s:Envelope> |
Your service should return a new authToken
in your response. You can choose to generate a new privateKey
or return the original one. Your service’s response should look something like the sample below. Sonos uses the authToken
and privateKey
that you send as the token
and key
values respectively in future SOAP requests. You can also return the userInfo
object if your service supports this capability. To simplify this sample, we have chosen not to show this object here.
1 2 3 4 5 6 7 8 9 10 |
<s:Envelope xmlns:ns="http://www.sonos.com/Services/1.1" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body> <ns:refreshAuthTokenResponse> <ns:refreshAuthTokenResult> <ns:authToken>1509120972472_3</ns:authToken> <ns:privateKey>633728174618</ns:privateKey> </ns:refreshAuthTokenResult> </ns:refreshAuthTokenResponse> </s:Body> </s:Envelope> |
When you don’t support refreshAuthToken
, listeners see the failure message and have to close the Info View window. Your service can use the SOAP fault method to refresh the token when their system sends another SMAPI request. For example, if the listener selects Info View or browses into a container.
If your service doesn’t support refresh tokens at all, the listener must manually log in and authenticate again.