Authentication and Authorization

All Audiogum APIs require authorization for access - typically an OAuth2 bearer token to act on behalf of a user or device, but some APIs are secured with HTTP Basic authentication - typically to obtain the bearer token.

You will be issued with a client_id and client_secret for each device or app variant you require to access the APIs - for example the iOS version of your app will have a different set of keys to your Android version; your development versions will have different secrets to your production versions. This allows us to keep your data segregated and to secure your data by rotating keys in a granular way if needed.


User authentication

There are three steps involved in obtaining a bearer token to access APIs - this is modelled on an OAuth2 token grant_type.

  1. Show Authorization UI: The app shows a native sign-in (or registration) form allowing the user to enter their existing credentials, create a new account, or sign in with a federated authentication provider like Facebook or Google.
  2. Validation and Token Exchange:
    1. For users that opt to login using their email address, the app posts the email and password entered to /v1/tokens (for sign-in) or /v1/user (for registration) and will receive access tokens if the details are valid. It is assumed that the app does basic checks on the data - e.g. the email address is valid (e.g. using a Regular Expression) and that for registration, the password has been entered twice to check the user has typed correctly. The app should store this response as the token details returned will include the expiry time and a refresh_token to allow continued access on behalf of the user without the need to sign-in again - see Token Renewal.
    2. For users that opt to login using a federated authentication provider like Facebook, the app must acquire an access token or authorization code using the native client SDK of the federation provider. Once an authorization code or token has been acquired, for example from Facebook, login can be completed by posting to /v1/login/providers/facebook/complete. An Audiogum token can then be acquired via the /1.x/tokens resource using the grant type authorization_code.
    3. Note: The app should call /v1/config to get a list of federated login providers that should be implemented and displayed to the user. These vary by country (e.g. some login providers like QQ and Weibo may be present in China, but others like Facebook and Google may only be available outside China).
  3. Access Secured Resources: The app can then use the token to access the desired user APIs by sending the access_token in the Authorization header of each request - e.g. Authorization: Bearer v1::k0PWZsbtc46216yGHXKahQ==::ur5SojWb0r9ZNHYXDCSfqSUSR240ehpI...

App Authorization Flow sequence diagram

Authorization Flow (native)

More detailed examples of user login and registration can be found on the User Accounts page.


Device authentication

When there is no direct user involved - e.g. before a user has signed into an app or from a device that does not run in the context of a user, we offer "device authentication" based on an OAuth2 client_credentials grant_type. Device tokens have a restricted set of scopes available to them.

1) Obtain Token: POST a deviceid and scope secured with basic auth of client_id:client_secret to get an access_token along with an expiry period. Note that a refresh_token is not returned as there is no need, this call can be made again.

POST /v1/tokens
Content-Type: application/json
Authorization: Basic Y2xpZW50aWQ6Y2xpZW50c2VjcmV0
{
 "grant_type": "client_credentials",
 "scope": "read_device",
 "deviceid": "94d8fce730eb4c2d886b2c82a5b16c53"
}

2) Access Secured Resources: The device can then use the token to access the desired APIs by sending the access_token in the Authorization header of each request - e.g. Authorization: Bearer v1::k0PWZsbtc46216yGHXKahQ==::ur5SojWb0r9ZNHYXDCSfqSUSR240ehpI...

Device Authorization Flow sequence diagram

Authorization Flow (device)


Shadow account authentication

If you have an existing authentication and user account system of your own, the Audiogum platform supports "shadow accounts", i.e. we support the scenario where you do the user authentication and pass us a consistent, unique ID that represents your user within our platform. We anonymise the identifier passed to us for the user by consistently transforming it into a uuid internally - this allows you to choose from a range of identifiers - e.g. your user account ID, an email address, etc.

The authentication flow uses client_credentials, the same as device authentication, with an extra externaluserid parameter included.

Example call:

POST /v1/tokens
Content-Type: application/json
Authorization: Basic Y2xpZW50aWQ6Y2xpZW50c2VjcmV0
{
   "grant_type": "client_credentials",
   "scope": "read_device",
   "deviceid": "94d8fce730eb4c2d886b2c82a5b16c53",
   "externaluserid": "someuseridentifier"
}

Optionally, a countrycode field can be sent for the user in the above request. The country code is used to determine content service availability and popularity used to present content. If a country code is not sent, an IP mapping will be performed based on the calling client.

Note: if you are integrating from your cloud, the user will end up with the country of your cloud data centre rather than the end-user. To get around this, you can use the IP Mapping API from your clients to determine the countrycode to send.

Security considerations for shadow accounts

Shadow account authentication has been designed with cloud-to-cloud integration in mind, where your Audiogum client_id and client_secret are never shipped / exposed in a product or app. If you intend to integrate from a client device where the client_id and client_secret might be exposed, you should generate a secure, random externaluserid and store this alongside the user in your own backend system, then retrieve & use this whenever you need to obtain an Audiogum access_token.

Extended signing for shadow accounts

Shadow account authentication can be extended with an additional signing process. The additional signing provides added protection by introducing a new shared secret that is never transmitted over the wire. We call this secret the 'Extended shadow accounts secret', and you need to talk to us to get one. This new secret is associated with your client_id/client_secret pair, and once we modify your configuration, only clients that have an extended shadow accounts secret will be able to use shadow account authentication.

To sign your requests, three new fields are added:

timestamp is the current unix timestamp (seconds since the epoch of January 1970 00:00:00 UTC)

nonce is a random string, used only once (a new nonce should be generated for each signed request)

signature is an HMAC-SHA256, using plaintext externaluserid + ":" + timestamp + ":" nonce and your shadow accounts extended secret as the key

For example, to sign a request for the external user id "someuseridentifier", we get the current unix timestamp of 1568833805, generate a random nonce of "392419347", then combine these into a string like:

"someuseridentifier:1568833805:392419347"

now we create a signature value like:

hmac_sha256("someuseridentifier:1568833805:392419347", "<extended shadow accounts secret>")

the result is a request that looks like:

POST /v1/tokens
Content-Type: application/json
Authorization: Basic Y2xpZW50aWQ6Y2xpZW50c2VjcmV0
{
   "grant_type": "client_credentials",
   "scope": "read_device",
   "deviceid": "94d8fce730eb4c2d886b2c82a5b16c53",
   "externaluserid": "someuseridentifier",
   "timestamp": 1568833805,
   "nonce": "392419347",
   "signature": "7949dbadf0fec2a087ccd7c3cbe622c6f86f25c59b83a5ff11047ff78b6aa0c8"
}

To verify your implementation is correct, you can use an online HMAC-SHA256 generator or use OpenSSL via the command line:

echo -n "someuseridentifier:1568833805:392419347" | openssl dgst -sha256 -hmac "<extended shadow accounts secret>"

The signature your client implementation generates should match the output shown by these tools.

If you're interested in activating extended signing for shadow account token requests just ask your Audiogum account manager.


Scopes

The Audiogum API supports the follow OAuth2 scopes that are required when requesting access tokens. The following aliases are available to simplify access and should be used for forward-compatibility:

all gives all user and device API scopes.

device-all gives all device API scopes.

userdevice-all gives all user scopes for delegation to a device with delegated tokens.

ScopeDescription
admin_apilogsAdmin read-only access to view API access logs
admin_deviceadminAdmin access to update and delete devices
admin_deviceviewAdmin read-only access to view devices
admin_firmwareAdmin access to add, update and delete firmware information
admin_releasesAdmin access to add, update and delete app release information
admin_secretsviewAdmin read-only access to clientids and secrets
admin_supportAdmin access to add, update and delete support information
admin_useradminAdmin access to update and delete users
admin_userviewAdmin read-only access to view users
delegateOnly users can delegate, this scope is never used but differentiates 'all' from 'userdevice-all'
playlistingGenerate a one-off playlist
read_deviceRead device details
read_devicediscoveryGet devices for a user with remotecontrol tokens
read_playlistsRead playlists
read_releaseRead app release details
read_usercatalogRead user catalog (user-auth required)
read_userprofileRead user profile (user-auth)
searchSearch for audio
signinBasic access
speechUnderstand spoken instructions, search, create playlists and control a speaker
write_deviceWrite device details
write_eventsSend analytics events
write_playlistsWrite user playlists (user-auth required)
write_sampleStore audio samples (for example for wakeword storage)
write_usercatalogWrite user catalog (user-auth required)
write_userprofileWrite user profile (user-auth required)

Device authentication

curl -vX POST --header 'Content-Type: application/json' --header 'Authorization: Basic <clientid:secret as base64>' -d '{ \
   "deviceid": "<deviceid>", \
   "scope": "device-all", \
   "grant_type": "client_credentials" \
 }' 'https://api.audiogum.com/v1/tokens'

Refreshing Tokens

Access tokens have a limited lifetime. The expiry time (expires_in) is provided in the response body alongside the token itself. Once a token has expired any request made that uses it will fail with an HTTP 401 response.

In the case of user authentication tokens, also provided in the token response body is a refresh_token. This can be used to request a new access token without the user having to re-approve access. This enables the API to manage token lifetimes more effectively and improves security by making it easier to revoke access tokens where an app is found to be misusing data or if the user decides they no longer wish to allow an app to access their data.

To use the refresh_token to obtain a new token, POST to /v1/tokens secured with basic auth client_id:client_secret including the refresh_token in the body as shown.

POST /v1/tokens
Content-Type: application/json
Authorization: Basic Y2xpZW50aWQ6Y2xpZW50c2VjcmV0
{
   "grant_type": "refresh_token",
   "refresh_token": "v1::vA/YkIi..."
}

The response will contain new access_token, refresh_token and expires_in values to replace previous.

Note that refresh_token is not required for device authentication tokens because the device may request a new token without any user-provided secrets.


Content Service User authentication

For details on linking content service accounts, see Content Services Authentication.


User Web-based authentication

We also support an OAuth2 web-based flow - typically these would be for tooling - start the authentication with the authorize API.