Introduction
This document covers developer's documentation for CQG ID endpoints usage by app. CQG ID endpoints implements authentication and authorization with the industry standard protocol OAuth 2.0. It supports only explicit authorization flow with PKCE.
Related Documents
- OAuth 2.0 Specifications: https://tools.ietf.org/html/rfc6749
- OAuth for native apps: https://tools.ietf.org/html/rfc8252
- Proof key for code exchange: https://tools.ietf.org/html/rfc7636
- Code example of native app on windows: https://github.com/googlesamples/oauth-apps-for-windows
The basics
App registration
You must register application that uses the CQG ID endpoints by contacting CQG directly. The app registration process collects and assigns special values for your app.
At first you need to provide these values to CQG:
- Application name. This name will be shown on Authorization endpoint page during user's logon process. Can be omitted. In this case no application name will be shown.
- A Redirect URI (reply URL) that will be used by Authorization endpoint to provide authorization code and redirect user once your app successfully authorized.
- Application type: spa (browser single page application), native or webapp (server rendered web application).
- Whether refresh tokens functionality is needed.
Then CQG will provide unique values which identifies your app:
- A Client ID that uniquely identifies your app.
- Client secret (application password) which is used for authorization code exchange. For webapp application type only. Client Secret must be kept securely.
Redirect URI
Redirect URI must start with https. Example: https://yourcompany.com/auth.
For loopback technique, when native app listens for response on local server, http://127.0.0.1/ {specialAppPath} should be used.
Endpoints
CQG ID provides two endpoints for authorization flow:
- User authorization endpoint: https://login.cqg.com/oauth/v2/auth - endpoint for user sign in with credentials and providing access to resource for application with authorization code on behalf of this user
- Token endpoint: https://aserv.cqgone.com/oauth/v2/token - endpoint for retrieving access token to resource from authorization code or refresh token.
For testing and development purposes the following ones should be used:
Authorization flow
Native app flow
Basically, authorization flow contains the following steps:
-
Request an authorization code:
- After startup, native application opens browser with CQG User authorization endpoint with required query parameters.
- Application starts to listen on (redirect URI) loopback IP for HTTP request with user authorization result, containing authorization code or error.
- After user's successful sign on, CQG User authorization endpoint will answer to redirect URI with authorization code.
-
Request an access token:
- Application gets authorization code and does POST request to CQG Token endpoint with required parameters in order to exchange code to access token and optionally refresh token.
- Token endpoint answers with access token and optional refresh token.
-
Use the access token:
- Application opens connection with desired CQG API with given access token.
-
Refresh the access token:
- If alive refresh token exists, access token already used and application needs to open connection with CQG API again, it does POST request to CQG Token endpoint with refresh token and required parameters.
- Token endpoint answers with new access token and new refresh token.
Single page app flow
Single page application is executed only in browser. The flow is almost the same, with the differences only in:
-
Request an authorization code:
- After startup or by user action, SPA application redirects to CQG User authorization endpoint with required query parameters.
- After user's successful sign on, CQG User authorization endpoint redirects user back to redirect URI (SPA) with authorization code.
Next steps are the same with the only difference, they are executed right in the browser.
Web app flow
The flow is almost the same, with the only difference that web application isn't fully executed in browser, web app server renders pages and do redirect requests for browser.
Also, it does communication with Token Server and API on its side, in secure environment, so client secret can be used here.
Detailed flow
Request an authorization code
In order to authenticate/authorize user with our sign-in form, CQG User authorization endpoint must be opened in browser with the following required query parameters:
Parameter | Description |
---|---|
client_id | Client id, provided during client's app registration. |
client_version | Client app version. |
redirect_uri |
This parameter must match with one provided while client app registration. In case of native app and loopback IP technique with registered http://127.0.0.1/{path} as redirect_uri, http://127.0.0.1:{port}/{path} must be provided, on which app listens for authorization code, where {port} can be different for any request and is skipped in exact match with registered URI. |
response_type | Value "code" must be provided. |
scope |
Resource URIs and permissions for which app wants to get access token, white-space separated. Example: "wss://api.cqg.com" By default, no refresh token issued. In order to request it – "offline_access" permission also should be provided in scope. Example: "offline_access wss://api.cqg.com" |
state (optional) | Any string value that app uses to maintain state between user authorization request and the authorization server's response with authorization code. Generating random string will help against possible cross-site request forgery attack. |
code_challenge |
Encoded code_verifier that will be used as a server-side challenge during authorization code exchange. A code_verifier is a high-entropy cryptographic random string using the unreserved characters [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~", with a minimum length of 43 characters and a maximum length of 128 characters. code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) |
code_challenge_method | "S256" |
Example:
https://login.cqg.com/oauth/v2/auth?
client_id=23dfeab-23d7-80be-79bc-sadg343df3fe
&client_version=2.0
&response_type=code
&redirect_uri=http%3A%2F%2F127.0.0.1%3A3453%2Fcode
&scope=wss%3A%2F%2Fapi.cqg.com+offline_access
&code_challenge=GSDFrer334OWYzMzA3MTIAGdgsgASFNmVjNDE5YmEyZGRSGfasfdmZ2342MTQ1dgasdg3NDcxY2Nl
&code_challenge_method=S256
&state=12345
Successful response
CQG User authorization endpoint will respond to this address via GET method with this query parameters:
Parameter | Description |
---|---|
code | Authorization code, if user agreed and successfully signed in. |
state (optional) | Previously provided state via auth request. |
Example:
GET https://127.0.0.1/code?
code=fsASDfgsdFsdgssdGHBsadhfdhGuNHSUYBrq
&state=12345
Error response
In case of error endpoint will respond with the following parameters to redirect_uri:
Parameter | Description |
---|---|
error | Specific error code. |
error_description | Specific error description. |
The following error codes can be returned:
Error code | Error description |
---|---|
invalid_request | The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. |
unsupported_response_type | Allowed response types: code. |
access_denied | The resource owner or authorization server denied the authorization request. |
invalid_scope | The requested scope is invalid, unknown, or malformed. |
server_error | Internal server error. |
temporarily_unavailable | The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. |
In case of redirect_uri or/and cliend_id is invalid, error will be shown only in browser.
Request an access token
In order to exchange an authorization code for an access token, do POST request to CQG Token endpoint with the following parameters:
Parameter | Description |
---|---|
client_id | Client id, provided during client's app registration. |
client_secret |
Client secret, provided during client's app registration. Required only for webapp application type. |
redirect_uri | The same value used on previous step. |
grant_type | Value "authorization_code" must be provided. |
code | Actual authorization code, retrieved via redirect URI on previous step. |
code_verifier | Unique one-time code, sent in encoded way on the previous step. |
A code_verifier is a high-entropy cryptographic random string using the unreserved characters [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~", with a minimum length of 43 characters and a maximum length of 128 characters.
Example:
POST /token HTTP/1.1
Host: https://aserv.cqgone.com/oauth/v2
Content-Type: application/x-www-form-urlencoded
client_id=32523523324234
&code=fsASDfgsdFsdgssdGHBsadhfdhGuNHSUYBrq
&client_secret=ASFfefdf32432LFfjssdf&gsagGDSGsdgdsfdsfsdgSGD3wtwt23gGDSGsgsdgsd
&redirect_uri=http%3A%2F%2F127.0.0.1%3A3453%2Fcode
&grant_type=authorization_code
&code_verifier=GAGkFdsafdnsfjdsfFGAewgewgew
Successful response
Server will respond with JSON and following parameters:
Parameter | Description |
---|---|
access_token | Access token for requested API in scope. |
expires_in | Lifetime of token in seconds. |
refresh_token (optonal) | Refresh token in order to retrieve access token after given one is expired. Note: Only provided if offline_access scope was requested. |
refresh_token_expires_in (optional) | Lifetime of refresh token in seconds. Note: Only provided if offline_access scope was requested. |
scope | Given resources. |
token_type | "Bearer" value. |
error (in case of error) | See https://tools.ietf.org/html/rfc6749#section-5.2 |
error_description | (in case of error) |
Example:
{
"access_token": "LKHKLHsafHFDMBMNOWQBdfsd34234UzI1NiIsgsagg53252Znl0aEV1Q...",
"token_type": "Bearer",
"expires_in": 3599,
"scope": "wss%3A%2F%2Fapi.cqg.com
"refresh_token": "BwBBAAvPM1KaPlrEqGsfdsafGUT235sdGQWR4B5...",
"refresh_token_expires_in": 86400
}
Then client app can access requested resource with provided access token.
Error response
Parameter | Description |
---|---|
error | Error code |
error_description | Error description |
The following errors can be returned:
Error | Error Description |
---|---|
invalid_request |
Expected application/x-www-form-urlencoded request body. Missing required parameter '%1%'. Failed to parse application/x-www-form-urlencoded request body. |
unsupported_grant_type | Allowed grant types: authorization_code. |
invalid_grant |
Invalid authorization code. Invalid refresh token. Wrong client_id. Wrong client_secret. Wrong redirect_uri. Wrong code_verifier. Request from wrong IP address. Authorization code has expired. Refresh token expired. |
Refresh the access token
Access tokens are short lived, you need to refresh them after they expire to access resources again.
In order to exchange refresh token for an access token, do POST to token endpoint with the following parameters:
Parameter | Description |
---|---|
client_id | Client id, provided during client's app registration. |
client_secret | Client secret, provided during client's app registration. Required only for webapp application type. |
grant_type | Value "refresh_token" must be provided. |
refresh_token | Actual refresh token |
Successful response
Server will respond with JSON and following parameters:
Parameter Description access_token Access token for requested scope. expires_in Lifetime of token in seconds. scope Given resources. refresh_token New refresh token in order to retrieve access token. Previous used refresh token is automatically expired and can't be used twice. refresh_token_expires_in Lifetime of refresh token in seconds. token_type "Bearer" value.
Error response
See error response for initial access token acquire step.