Before you can authenticate with the OAuth server and make API requests, you must first create your app in our system:
When requesting a grant, you should choose only the scopes you plan on using. Users will be asked to approve the scopes you request access to. The following is a list of scopes which you can request access to:
| user.account:read | View your account information including email and username |
| user.account:write | Change your account information including email and username |
| user.apps:read | View apps owned by you |
| user.apps:write | Create or edit apps owned by you |
| user.devices:read | View devices logged in to your account |
| user.devices:write | Modify or revoke devices logged in to your account |
| user.library:read | View your music library |
| user.library:write | Edit your music library |
| user.queue:read | View any device's play queue |
| user.queue:write | Control any device's play queue |
| user.upload | Upload new files to your music library |
The OAuth server supports the following grant types and flows:
This is the most commonly used OAuth flow. In this flow, you will direct a user to the OAuth server for authentication and authorization. They will redirected back to your app. Your app will then request a token to complete authorization.
This is used when your app is running on a device that does not have a browser, such as a TV app. Your app will request a device code from the OAuth server. It will then present the supplied URL and user code, and optionally a QR code, which the user can follow on their phone, tablet, or computer browser to complete authorization. Your app will poll using the device code at the rate specified by the OAuth server until the user authorizes or the device code expires. Once the user has authorized the device code, the OAuth server will respond with a token and authorization is complete.
1. Generate a code_verifier and code_challenge on your app. A code_verifier is a cryptographically random set of characters between 43 and 128 in length. There are numerous ways to about about this, but here is one nodejs example from the Passport.js library source code:
const code_verifier = base64url(crypto.pseudoRandomBytes(32));
const code_challenge = crypto.createHash("sha256").update(code_verifier).digest();
You should store the code_verifier for the duration of the authorization process, as you will need to send it to the OAuth server again in step 4.
2. Generate a state. The state is a random string, up to 128 characters, which is used to help prevent CSRF (Cross-Site Request Forgery). You will compare this state against what the OAuth server sends back in step 4.
3. Direct user to open the OAuth authorization URL in their browser. Pass the state, code_challenge, scopes list (space-delimited), and client_id.
https://oauth.ibroadcast.com/authorize
?client_id=your_client_id
&state=<your_state>
&response_type=code
&code_challenge=<your_code_challenge>
&code_challenge_method=S256
&scope=<your_scopes>
4. Wait for the user to log in, authorize your app, and get redirected back to the Redirect URI you configured for your app. The result of the authorization request will be detailed in query parameters in the request made to your Redirect URI.
If authorization was successful, the query string will look like this:
?state=<your_state>&code=<authorization_code>
You must check that the state string received here is the same as the state string you originally passed to the authorize request. If it is not, this is an error and you should not proceed with requesting a token.
If authorization was not successful, the query string will look like this:
?error=<error_code>&error_description=<error message>
You should present any error messages received to the user so that they can try again. It is not recommended that you present users a custom or generic error message to replace any error messages received from the OAuth server as it becomes more difficult to debug when multiple errors have the same message.
5. Request a token from the OAuth server:
https://oauth.ibroadcast.com
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=<your_authorization_code>
&client_id=<your_client_id>
&redirect_uri=<your_redirect_uri>
&code_verifier=<your_code_verifier>
The OAuth server will respond with an access token, refresh token, and expiration, in the following JSON format:
{
access_token: <string>, // ~64 character token
token_type: "Bearer", // always "Bearer"
expires_in: <int>, // seconds
refresh_token: <string>, // ~64 character token
scope: [<string>] // array of scopes
}
Convert expires_in to a UTC timestamp and store the returned token object in non-volatile storage in your app. You will need to check the token expiration before any requests and refresh the token using refresh_token if it has expired.
1. Generate a code_verifier and code_challenge on your app. A code_verifier is a cryptographically random set of characters between 43 and 128 in length. There are numerous ways to about about this, but here is one nodejs example from the Passport.js library source code:
const code_verifier = base64url(crypto.pseudoRandomBytes(32));
const code_challenge = crypto.createHash("sha256").update(code_verifier).digest();
You should store the code_verifier for the duration of the authorization process, as you will need to send it to the OAuth server again in step 4.
2. Request a device code from the OAuth server:
https://oauth.ibroadcast.com/device/code
?client_id=<your_client_id>
&code_challenge=<your_code_challenge>
&code_challenge_method=S256
&scope=<your_scopes>
The OAuth server will respond with a device_code, user_code, verification_uri, verification_uri_complete, interval, and expires_in:
{
device_code: <string>, // ~64 character token
user_code: <string>, // code user must enter to authorize this app
verification_uri: <string>, // URI to display to user
verification_uri_complete: <string>, // URI which can be used to generate a QR code
interval: <int> // poll rate, seconds
expires_in: <int> // seconds relative to now
}
3. Poll for a token at the interval returned in step 2 until the server returns an error. If the server returns an error, discard the last stored device_code and request a new one.
https://oauth.ibroadcast.com
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=device_code
&device_code=<your_device_code>
&client_id=<your_client_id>
&code_verifier=<your_code_verifier>
If the server returns HTTP status code 400 with error of authorization_pending OR HTTP status code 429 with error of slow_down, you should keep polling. In the case of slow_down, decrease your polling rate to the interval returned in step 2.
When the user has authorized the request, the OAuth server will respond with an access token, refresh token, and expiration, in the following JSON format:
{
access_token: <string>, // ~64 character token
token_type: "Bearer", // always "Bearer"
expires_in: <int>, // seconds
refresh_token: <string>, // ~64 character token
scope: [<string>] // array of scopes
}
Convert expires_in to a UTC timestamp and store the returned token object in non-volatile storage in your app. You will need to check the token expiration before any requests and refresh the token using refresh_token if it has expired.
To refresh the access token once it expires, and receive a new token and refresh token:
https://oauth.ibroadcast.com
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token
&refresh_token=your_refresh_token
&client_id=your_client_id
&redirect_uri=your_redirect_uri
A token can be revoked and the user's session forcefully logged out by issuing a token revoke request:
https://oauth.ibroadcast.com
POST /revoke
Content-Type: application/x-www-form-urlencoded
refresh_token=your_refresh_token
&client_id=your_client_id
When issuing requests to the JSON API, you must include the bearer token in the Authorization header of requests:
Authorization: Bearer your_access_token
If an access token is no-longer valid, the JSON API will pass authenticated: false to the response body:
{
"result": false,
"authenticated": false
}
When this happens, you must attempt to refresh your token with the OAuth2 server, and if that fails you must reauthenticate to acquire a new token.