Native/Desktop Authentication Flow

Register your application

First, register your client application with MediaCore.

You’ll need to know your client_id later in the process, so be sure to store them somewhere safe. (There is no client_secret for native applications because it would be impossible to keep it secret.)

You’ll also need to configure the redirect URIs for this client. When a user authorizes your client, they will be redirected to one of these URIs with the pertinent details.

Opening a browser window

Because this OAuth flow is web-based, native applications must be capable of opening a browser window. MediaCore depends on there being a browser session in order to support log in via MediaCore’s various SSO integrations.

The preferred solution is to embed a browser window in the native application. This allows the user to log themselves into MediaCore and consent to your authorization request without having to leave your application.

The alternate solution is to use the default system browser to open the authorization consent page. This user experience is less than ideal because, if an error occurs, the user may be left stranded in the browser and they must manually navigate back to your application.

Choosing a redirect_uri

When the authorization request completes, the user is redirected back to the client application via a redirect_uri where the client can process the result. Native applications can choose one of two redirect_uri values:

http://localhost/

If your application can start a local web server for the duration of the authorization flow, MediaCore can redirect the user to the local server with the authorization result included in the query string. This is the recommended approach whenever possible.

It is not necessary (nor advisable) for the web server to be externally accessible, it only has to be accessible to the user. Also, any port on localhost may be specified in the query string of the authorization request.

urn:ietf:wg:oauth:2.0:oob

This species an “out of band” callback. With this value, MediaCore will redirect the user to a special authorization result page that supports two use cases:

  1. If your application can detect changes to the title bar of the browser window, the result of authorization request can be retrieved automatically. MediaCore sets the document title and that is typically available in the title bar of the browser window.

    If the authorization request was approved, the title will look like this:

    Success code=SplxlOBeZQQYbYS6WxSbIA&state=xyz

    If the authorization request was denied or failed, the title will look like this:

    Denied error=access_denied&error_description=Something+went+wrong&state=xyz

    Once your application has detected the change to the document title and successfully retrieved the code, the browser window can be closed automatically if possible.

    When using this approach, it is important to limit the state parameter to a reasonable length to reduce the chance of truncation. We suggest no more than 10 characters.

  2. As a fallback solution, the authorization code will also be printed to the screen so that the user can manually copy and paste it into the client application.

Request authorization

When your client application needs to make API calls on behalf of an end-user, you must direct the user to the authorization endpoint in a browser window.

Once the user reaches this endpoint, two things happen:

  1. The user will be asked to log in, if they aren’t already.

  2. The user will be shown an authorization consent form, with the option to either approve or deny the authorization request.

    On this page, MediaCore will clearly show the user:

    • what application is requesting to access our API on their behalf;
    • what permissions the client has requested (via the scope); and
    • whether the application has requested longer-term “offline” access, meaning that the application can continue to access the API on the user’s behalf without the user having to re-authorize in the future (also via the scope).

There are a number of parameters that should be set when redirecting to the authorization endpoint.

Query parameters:

  • response_type – Must be set to code.
  • client_id – Your client ID that was assigned when you registered your application.
  • redirect_uri – The callback URL where the user should be redirected once they have approved or denied your authorization request. This must exactly match one of the redirect_uris that you configured when registering your client application, except when you specify http://localhost any port may be given.
  • scope (optional) – The permissions to request from the end-user. See Scopes for a list of supported values.
  • state – An unguessable random string that will be mirrored back to the client in the redirect response. The client must store this value so that it can verify that the same state is passed back in the redirect URI, thereby mitigating CSRF attacks.

Example Request:

In order to request authorization, your application should issue the user a redirect response like this:

HTTP/1.1 302 Found
Location: https://pacificu.mediacore.tv/api2/oauth/authorize?
  response_type=code&
  client_id=s6BhdRkqt3&
  redirect_uri=http%3A%2F%2Flocalhost%2Fcb&
  scope=one%20two&
  state=xyz

Handle the response

Once the user submits the authorization form, they are sent back to the redirect_uri (specified in the last step) using a 302 Found redirect. Everything you need to know will be included in the query string.

Verify the response

If this request is valid, the redirect URI will include the same state query parameter as was provided in the last step. The client must verify that the same state that was sent in the authorization request has been mirrored back in this response.

If the state does not match, no further processing of this request should occur, and the client must show a stock error message to the user. Do not trust any of the request parameters.

If authorization was granted

To check if the authorization request was approved, look for a code parameter in the query string.

Query parameters:

  • code – A temporary authorization code that your client can exchange for an access_token in the next step.
  • state – This is expected to be the same state value that the client passed in the query string of the authorization request. This must be verified!

Example request:

When authorization has been granted, the user will be redirected to the specified callback URL, from which you can extract the necessary information.

GET /cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz HTTP/1.1
Host: localhost

Once you have verified the response and you have the code, you can proceed to Exchange the code for an access_token.

If authorization was denied

To check if the authorization request was denied or failed for some reason, check for an error parameter in the query string.

Query parameters:

  • error – An error code defined by the OAuth2 specification.
  • error_description – A human readable error message suitable for displaying to users. (Remember to escape this string if injecting it into an HTML document.)
  • state – This is expected to be the same state value that the client passed in the query string of the authorization request. This must be verified!

Example request:

When authorization has been denied, the user will be redirected to the specified callback URL, from which you can extract the necessary information.

GET /cb?error=access_denied&error_description=Something+went+wrong&state=xyz HTTP/1.1
Host: localhost

If an error occurred, this process stops and you must show an error message to the user.

Exchange the code for an access_token

Once you have an authorization code, you can exchange it for an access_token by making a direct request from your application to the MediaCore API.

Token Request

Json Parameters:

  • grant_type – Must be authorization_code.
  • code – The code from the previous step.
  • redirect_uri – The redirect_uri that you specified in the original authorization request. If this does not match exactly, the access_token will not be given.
  • client_id – Your client ID that was assigned when you registered your application.

Example request:

POST /api2/oauth/access_token HTTP/1.1
Host: pacificu.mediacore.tv
Content-Type: application/json

{
  "grant_type": "authorization_code",
  "code": "SplxlOBeZQQYbYS6WxSbIA",
  "redirect_uri": "http:/localhost/",
  "client_id": "ff20303a-ed9c-4337-8016-9319bfa02a1b"
}

Note

This request may also use application/x-www-form-urlencoded as the Content-Type.

Token Response

If the exchange request succeeds, the response will include your access_token and some related metadata.

Response parameters:

  • token_type – This will be set to Bearer.
  • access_token – The token that you can use to authenticate API requests.
  • expires_in – The number of seconds that the access_token will continue to be valid.
  • refresh_token – A token that can be exchanged for a new access_token once the access_token has expired.
  • scope – The authorized permissions. Note that this may differ from the requested scope, because we may allow the user to grant only some of the requested permissions.

Example response:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
  "token_type": "Bearer",
  "access_token": "2YotnFZFEjr1zCsicMWpAA",
  "expires_in": 3600,
  "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
  "scope": "[...]"
}

Send API requests

Now that you have an access_token, your client can make API calls on behalf of the user.

To send an API request on behalf of the user, pass their access_token via the Authentication header. For example:

GET /api2/users/me HTTP/1.1
Host: pacificu.mediacore.tv
Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA

When an access_token expires

If you try to make an API request with an access_token that has expired or been revoked, you will receive a 401 Unauthorized response, similar to this:

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
  "message": "Bad credentials"
}

To recover from this error, your application should request a new access_token and then repeat the request.

There are two ways to request a new token:

  1. Repeat the authorization flow. This is only an option if the user is still actively using your application, because you must be able to redirect the user back to the authorization page.
  2. Exchange a refresh_token for a new access_token. See Using refresh tokens for further details.

Using refresh tokens

Refresh tokens should be used when your application needs to be able to make API calls on behalf of a user even after that user is no longer online and actively using your application. This use case is called offline access.

For native apps, a refresh_token will always accompany the access_token that your application receives in Exchange the code for an access_token. You must store this refresh_token some place safe!

Refresh Request

Json Parameters:

  • grant_type – Must be refresh_token.
  • refresh_token – The refresh_token you have received.
  • client_id – Your client ID that was assigned when you registered your application.

Example request:

POST /api2/oauth/access_token HTTP/1.1
Host: pacificu.mediacore.tv
Content-Type: application/json

{
  "grant_type": "refresh_token",
  "refresh_token": "tGzv5JOkF0XG5Qx2TlKWIA",
  "client_id": "ff20303a-ed9c-4337-8016-9319bfa02a1b"
}

Refresh Response

If the refresh request succeeds, the response will include your new access_token.

Response parameters:

  • token_type – This will be set to bearer.
  • access_token – The token that you can use to authenticate API requests.
  • expires_in – The number of seconds that the access_token will continue to be valid.
  • refresh_token – A new refresh_token that supercedes the one used in this request.
  • scope – The authorized permissions. Note that this may differ from the requested scope, because we may allow the user to grant only some of the requested permissions.

Example response:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
  "token_type": "Bearer",
  "access_token": "VbcNSIuLuKml4bvmGOlfwb",
  "expires_in": 3600,
  "refresh_token": "ABJiRQJZtA6v3pBJinBhWm",
  "scope": "[...]"
}

Now that you have a new access_token, you can continue making API requests on behalf of the user.