OpenAPI

Native apps should use the Authorization Code Grant (RFC 6749) with Proof Key for Code Exchange (RFC 7636).

Below is a guide to get started using this authorization flow.

Your OpenAPI Application

When an application is created for you on OpenAPI, you will receive the following application details:


NameDescriptionExample
AppUrl

A URL uniquely representing your app.

http://localhost/mytestapp
AuthenticationUrl
The URL of the Saxo Bank authentication & authorization server.
https://sim.logonvalidation.net/
AppKey
The Application key identifying your application.
1234-5678-9101
AppSecret
The Application "secret" identifying your application.
abcdefghijklmn
OpenApiBaseUrl
Base URL for calling OpenAPI REST endpoints.
https://gateway.saxobank.com/sim/openapi/


These can be mapped to the necessary OAuth parameters:

OAuth Parameter

Saxo App Value

RequiredExample
client_id
AppKeyYes
1234-5678-9101
client_secret 
AppSecretYes
abcdefghijklmn
redirect_uri
AppUrlYes
http://localhost/mytestapp
authorization_url
AuthenticationUrl + '/authorize'Yes
https://sim.logonvalidation.net/authorize
token_url
AuthenticationUrl + '/token'Yes
https://sim.logonvalidation.net/token
Below parameters are determined by the developer:
response_type
Must always be set to 'code'Yes
code
state
Randomly generated string used by the client to maintain state between the request and callback.No
y90dsygas98dygoidsahf8sa
code_verifier

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.

We suggest you follow the official recommendation which is that "the output of a suitable random number generator be used to create a 32-octet sequence. The octet sequence is then base64url-encoded to produce a 43-octet URL safe string to use as the code verifier." (https://tools.ietf.org/html/rfc7636#section-4.1)

Yes
dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
code_challenge

if code_challenge_method is "Plain": code_challenge = code_verifier
If code_challenge_method is "S256": code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))

Yes
E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM

code_challenge_method
Possible values are 'Plain' and 'S256'. The client MUST use 'S256' unless otherwise agreed with Saxo Bank.No, default is 'plain'S256
scope
Not usedN/A


Authorization Request

To initiate the authentication flow, redirect the client to the /authorize with the required parameters in the query string. Make sure to set the content-type to 'application/x-www-form-urlencoded'.

Example:

Example Authorize request (line breaks for display purposes)
GET /authorize?response_type=code
        &client_id=1234-5678-9101
        &state=y90dsygas98dygoidsahf8sa
        &redirect_uri=http%3A%2F%2Flocalhost%2Fmytestapp
        &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
        &code_challenge_method=S256


Once the user is logged in, he will be redirected back to the provided redirect_url with an authorization code as a query parameter.

Authorize response
HTTP/1.1 302 Found
Location: http://localhost/mytestapp?code=09ccbf1c-ec0d-4da2-bcce-a0ba39f57771&state=y90dsygas98dygoidsahf8sa


Access Token Request

Once the authorization code has been obtained, it can be exchanged for an access token by sending a POST request to the /token endpoint. This request needs to be authenticated using HTTP Basic Auth with your client_id as username and client_secret as password. The basic auth should be a base64 encoded string in the following format: "client_id:client_secret".

Example Access Token request - with Authorization header
POST /token HTTP/1.1
Host: sim.logonvalidation.net
Authorization: Basic MTIzNC01Njc4LTkxMDE6YWJjZGVmZ2hpamtsbW4=
Content-Type: application/x-www-form-urlencoded
 
grant_type=authorization_code
&code=09ccbf1c-ec0d-4da2-bcce-a0ba39f57771
&redirect_uri=http%3A%2F%2Flocalhost%2Fmytestapp
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk


If your OAuth library does not support sending the credentials as HTTP Basic Auth, we also accept them as part of the post body:

Example Access Token request - with Authorization header
POST /token HTTP/1.1
Host: sim.logonvalidation.net
Content-Type: application/x-www-form-urlencoded
 
grant_type=authorization_code
&code=09ccbf1c-ec0d-4da2-bcce-a0ba39f57771
&redirect_uri=http%3A%2F%2Flocalhost%2Fmytestapp
&client_id=1234-5678-9101
&client_secret=abcdefghijklmn


The response to this request will contain an access_token and a refresh_token:

Example Access Token response
{
	"access_token" : "eyJhbGc.eyJvYWEiOiIwMDA0NCIsImlzcQ.gElDA_9M0_eDr6Jw",
	"expires_in": 1200,
	"token_type": "Bearer",
	"refresh_token": "5e7fa3d2-5e13-4736-80c1-9c3e5cde660b",
	"refresh_token_expires_in": 2400
}


Using the Refresh Token

If you were provided with a refresh token you can use it to keep the connection alive by exchanging it for a new access and refresh token within it's lifetime.

To do this, send another request to the /token endpoint with 'grant_type=refresh_token':

Example Access Token request - with Authorization header
POST /token HTTP/1.1
Host: sim.logonvalidation.net
Authorization: Basic MTIzNC01Njc4LTkxMDE6YWJjZGVmZ2hpamtsbW4=
Content-Type: application/x-www-form-urlencoded
 
grant_type=refresh_token
&refresh_token=5e7fa3d2-5e13-4736-80c1-9c3e5cde660b
&redirect_uri=http%3A%2F%2Flocalhost%2Fmytestapp