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.
There are three steps involved in obtaining a bearer token to access APIs - this is modelled on an OAuth2 token
grant_type.
/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./v1/login/providers/facebook/complete
. An Audiogum token can then be acquired via the /1.x/tokens
resource using the grant type authorization_code
./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).access_token
in the Authorization header of each request - e.g. Authorization: Bearer v1::k0PWZsbtc46216yGHXKahQ==::ur5SojWb0r9ZNHYXDCSfqSUSR240ehpI...
More detailed examples of user login and registration can be found on the User Accounts page.
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...
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.
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
.
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.
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.
Scope | Description |
---|---|
admin_apilogs | Admin read-only access to view API access logs |
admin_deviceadmin | Admin access to update and delete devices |
admin_deviceview | Admin read-only access to view devices |
admin_firmware | Admin access to add, update and delete firmware information |
admin_releases | Admin access to add, update and delete app release information |
admin_secretsview | Admin read-only access to clientids and secrets |
admin_support | Admin access to add, update and delete support information |
admin_useradmin | Admin access to update and delete users |
admin_userview | Admin read-only access to view users |
delegate | Only users can delegate, this scope is never used but differentiates 'all' from 'userdevice-all' |
playlisting | Generate a one-off playlist |
read_device | Read device details |
read_devicediscovery | Get devices for a user with remotecontrol tokens |
read_playlists | Read playlists |
read_release | Read app release details |
read_usercatalog | Read user catalog (user-auth required) |
read_userprofile | Read user profile (user-auth) |
search | Search for audio |
signin | Basic access |
speech | Understand spoken instructions, search, create playlists and control a speaker |
write_device | Write device details |
write_events | Send analytics events |
write_playlists | Write user playlists (user-auth required) |
write_sample | Store audio samples (for example for wakeword storage) |
write_usercatalog | Write user catalog (user-auth required) |
write_userprofile | Write user profile (user-auth required) |
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'
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.
For details on linking content service accounts, see Content Services Authentication.
We also support an OAuth2 web-based flow - typically these would be for tooling - start the authentication with the authorize API.