OpenID+OAuth 2 Hybrid Protocol

Important!
Never provide your access_token, refresh_token or client_secret to a web browser or other end-user agent. Instead, maintain a separate session and persist this data in a location accessible only by your application (e.g. do not store the access_token in a cookie). Contact api-support@sparkapi.com for further guidance.
Confused?
Check out our OpenID+OAuth 2 Hybrid Flow example using just your web browser and curl or, if you prefer PHP, the 15 minute PHP app.

This protocol combines both OpenID and OAuth 2, and is the recommended flow for any application available from the appstore that requires access to API data.

  1. Hybrid Flow Walkthrough
  2. The Spark Hybrid Full Specification
  3. Single Logout

Hybrid Flow Walkthrough

The Spark Identity Provider (IdP) adds an extension to support OAuth 2.0 requests inside a single OpenID request. This is very similar to Google's draft of OAuth 1.0 in OpenID.

All OpenID requests must be made using HTTPS.

Openid_oauth2

The typical OpenID/OAuth 2 Hybrid flow with Spark API can be broken down into four steps:

  1. Obtaining User Authorization
  2. Token Exchange
  3. Requesting Data
  4. Refreshing Expired Sessions

Obtaining User Authorization

See also section 3 of the OAuth 2 spec.

Obtaining user authorization requires you to redirect the end-user to the appropriate endpoint with the required parameters provided. Once they have authorized your application, they will be redirected back to your redirect_uri with the access code provided in the URI.

API Endpoints:

SESSION ROLE Hybrid endpoint URI
IDX https://sparkplatform.com/openid
VOW Currently unsupported -- use OAuth 2
Private https://sparkplatform.com/openid

Parameters:

  • openid.spark.client_id: your unique client key.
  • openid.return_to: the URI that you'd like the OAuth endpoint to redirect to after successfully authenticating the user.
  • openid.spark.combined_flow: always true.
  • openid.spark.state: an optional parameter that will be returned to your return_to URI.

Read the The Spark Hybrid Full Specification below for a more detailed description on each parameter as well as additional optional parameters.

Example Request

https://sparkplatform.com/openid?openid.mode=checkid_setup&openid.return_to=http://example.com/consumer&openid.spark.client_id=1234&openid.spark.combined_flow=true
If the request is valid, the OpenID response will contain openid.spark.code. After receiving the OAuth 2 code, your consumer script can proceed with the OAuth 2 token exchange and OAuth 2 data request.

Example: Successful Response

http://example.com/consumer?openid.spark.code=5678&openid.mode=id_res
Note that OpenID responds with many more parameters, but these two are the most important for an OAuth 2 example

Example: Unsuccessful OAuth 2 Response

http://example.com/consumer?openid.mode=error&openid.error=The provided return_to URI does not match the registered URI
Notice that openid.mode is set to error and the openid.error parameter shows the openid.return_to request parameter was not correct.

Token Exchange

See also section 4.1.1 of the OAuth 2 spec.

After the end user has successfully authorized your application, you must exchange your access code for an access_token by POSTing the the following data to the https://sparkapi.com/v1/oauth2/grant resource:

Sample POST Request Body

{
  "client_id": "[client_id]",
  "client_secret":  "[client_secret]",
  "grant_type": "authorization_code",
  "code": "[code]",
  "redirect_uri": "[redirect_uri]"
}
Attribute Description
client_id This is your OAuth client ID provided by FBS.
client_secret This is your OAuth client secret provided by FBS.
grant_type This is always set to authorization_code .
code This is the value of the code obtained in step 1.
redirect_uri The value of the URI to which the user will be redirected upon completion. The domain must match that which is registered with FBS. (We encourage you to use HTTPS for your redirect URI.)

Sample Successful Response Body: HTTP status 200 (see also section 3.1 of the OAuth 2 spec)

{
  "access_token": "[access_token]",
  "refresh_token": "[refresh_token]",
  "expires_in":  86400
}

Sample Failed Response Body: HTTP status > 299 (see also section 3.2.1 of the OAuth 2 spec)

{
  "error": "[error_code]",
  "error_description": "Detailed message here"
}

Requesting Data

See also section 5.1.1 of the OAuth 2 spec.

Once you have your access_token, you can request data by placing it in the Authorization header for each request:

Authorization: OAuth [access_token]
Note that, when using OAuth 2, all requests must be made over HTTPS.

Refreshing Expired Sessions

Access tokens expire after 24 hours, yet it would be undesirable to have to redirect end users to the OAuth 2 authorization flow once a day. The refresh flow is a remedy to this.

Sample Session Expired Response Header and Body

HTTP/1.1 401 Unauthorized
WWW-Authenticate: OAuth realm='Flexmls API', error='expired_token'
{
  "D": {
    "Success": false,
    "Message": "Session token has expired",
    "Code": 1020
  }
}
To refresh the access token, POST the following JSON data to the API's OAuth Access Token service at https://sparkapi.com/v1/oauth2/grant using HTTPS:

Sample POST Request Body

{
  "client_id": "[client_id]",
  "client_secret":  "[client_secret]",
  "grant_type": "refresh_token",
  "refresh_token": "[refresh_token]",
  "redirect_uri": "[redirect_uri]"
}
Parameter Description
client_id This is your OAuth client ID provided by FBS.
client_secret This is your OAuth client secret provided by FBS.
grant_type Set this to refresh_token .
refresh_token This is the value of the refresh token obtained from the initial access token grant.
redirect_uri The domain must match that which is registered with FBS, although a redirection does not occur when refreshing an access token.

Sample Successful Response Body: HTTP status 200 (see also section 3.1 of the OAuth 2 spec)

{
  "access_token": "example_new_access_token",
  "refresh_token": "example_new_refresh_token",
  "expires_in":  86400
}

Sample Failed Response Body: HTTP status > 299 (see also section 3.2.1 of the OAuth 2 spec)

{
  "error": "[error_code]",
  "error_description": "Detailed message here"
}
 

Full Specification

The Spark OAuth 2 extension for OpenID is not in the official OpenID standard. It's FBS's own extension, but it compares nicely with Google's OpenID draft of OAuth 1.0. Provide the required request parameters, and the OAuth 2 code will be returned in the OpenID response.

Request Parameters

  • openid.spark.client_id
  • (required) Specify the Spark OAuth 2 client key, provided by FBS.

  • openid.return_to
  • (required) This is the URI the IdP will redirect to after successful authentication and authorization. This must match the URI on record for your application.

  • openid.spark.combined_flow=true
  • (optional) This triggers the OAuth 2 hybrid protocol. If this is set, the openid.spark.client_id and openid.return_to URI are checked against the database records for your application. If the application is authorized, an OAuth 2 code is passed back with the response in the openid.spark.code value.

  • openid.spark.state
  • (optional) If your application needs to save session information through the hybrid flow, set this parameter to any string. This is similar to the OAuth2 state parameter. This value will be populated in the response parameter openid.spark.state. See the PHP example above.

  • openid.ns.spark=http://sparkplatform.com/extensions/spark/1.0
  • (auto-detected) The OpenID specifications require that every extension register a namespace alias, referenced to a URI that uniquely identifies the protocol. If you specify the openid.spark.client_id parameter, the Spark IdP will fill this in for you.

Response Parameters

  • openid.ns.spark=http://sparkplatform.com/extensions/spark/1.0
  • This identifies the Spark extension as the openid.spark alias. Mostly used in OpenID clients to detect the extension protocol

  • openid.spark.code
  • The OAuth 2 code, if the request was successful. Proceed on with the OAuth 2 token exchange and OAuth 2 data request.

  • openid.spark.state
  • If a state was given in the request, this will contain the same value.

Single Log Out

Spark Platform provides a single log out service that can be accessed directly from the Spark Bar. If your application does not use the Spark Bar, you can initiate this flow manually by directing the user to the following URI:

https://sparkplatform.com/openid/logout

The Single Logout process destroys the existing cookie at our OpenID endpoint, requiring the user to reauthenticate the next time they are directed to the endpoint. It also destroys custom sessions for other applications built on the Spark Platform, so long as those applications have specified a Single Logout URI in the Spark Store.