Show / Hide Table of Contents

Authentication

All API calls to Freemarket are authenticated using JWT authentication tokens according to the OpenID Connect standard, OAuth 2.0 Password Grant.

Authentication consists of two independent parts, the authentication of the client (the piece of software integrating with the API) and the authentication of the service user account to establish the security context (permissions). The authentication token can be obtained by either using the client secret or using a client certificate and the mutual TLS protocol.

Client secret authentication endpoint

This endpoint accepts a client id and secret combination to authenticate the client.

  • HTTP
  • CURL
  • C#
  • Java
  • PHP
POST /connect/token HTTP/1.1
Host: identity.wearefreemarket.com
Content-Type: application/x-www-form-urlencoded

grant_type=password&scope=freemarketFXAPI&client_id={clientId}&client_secret={clientSecret}&username={userEmail}&password={userPassword}
curl --request POST 'https://identity.wearefreemarket.com/connect/token'
--header 'Content-Type: application/x-www-form-urlencoded'
--data-urlencode 'grant_type=password'
--data-urlencode 'scope=freemarketFXAPI'
--data-urlencode 'client_id={clientId}'
--data-urlencode 'client_secret={clientSecret}'
--data-urlencode 'username={userEmail}'
--data-urlencode 'password={userPassword}'
// request token
HttpClient client = // get HttpClient
var response = await client.PostAsync("https://localhost/connect/token", new FormUrlEncodedContent(new KeyValuePair<string, string>[]
{
    new KeyValuePair<string, string>("grant_type", "password"),
    new KeyValuePair<string, string>("scope", "freemarketFXAPI"),
    new KeyValuePair<string, string>("client_id", clientId),
    new KeyValuePair<string, string>("client_secret", clientSecret),
    new KeyValuePair<string, string>("username", userEmail),
    new KeyValuePair<string, string>("password", password)
}));

if (!response.IsSuccessStatusCode)
{
    throw new Exception($"Unsuccessfull response: {response.StatusCode} - {response.ReasonPhrase}");
}

string responseContent = await response.Content.ReadAsStringAsync();
JsonDocument responseDocument = JsonDocument.Parse(responseContent);
string accessToken = responseDocument.RootElement.GetProperty("access_token").GetString();
int expiresInSeconds = responseDocument.RootElement.GetProperty("expires_in").GetInt32();
String enc = "UTF-8";
URL url = new URL("https://identity.wearefreemarket.com/connect/token");

HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

StringBuilder contentBuilder = new StringBuilder();
contentBuilder.append("grant_type=password&");
contentBuilder.append("scope=freemarketFXAPI&");
contentBuilder.append("client_id=").append(URLEncoder.encode(clientId, enc)).append("&");
contentBuilder.append("client_secret=").append(URLEncoder.encode(clientSecret, enc)).append("&");
contentBuilder.append("username=").append(URLEncoder.encode(userEmail, enc)).append("&");
contentBuilder.append("password=").append(URLEncoder.encode(userPassword, enc));
byte[] content = contentBuilder.toString().getBytes(enc);

conn.setRequestProperty("Content-Length", Integer.toString(content.length));
try (OutputStream outputStream = conn.getOutputStream()) {
    outputStream.write(content);
}
int responseCode = conn.getResponseCode();
if (responseCode != 200) {
    throw new Exception("Unsuccessfull response code: " + responseCode);
}
ObjectMapper mapper = new ObjectMapper();
try (Reader reader = new InputStreamReader(conn.getInputStream(), enc)) {
    HashMap<String, Object> response = mapper.readValue(reader, new TypeReference<HashMap<String, Object>>() {});
    System.out.println("access_token: " + response.get("access_token"));
    System.out.println("expires_in: " + response.get("expires_in"));
    System.out.println("token_type: " + response.get("token_type"));
    System.out.println("scope: " + response.get("scope"));
}
$curl = curl_init();
$data = array(
    'grant_type' => 'password',
    'scope' => 'freemarketFXAPI',
    'client_id' => '{clientId',
    'client_secret' => '{clientSecret}',
    'username' => '{userEmail}',
    'password' => '{userPassword}
);

$this->setup_curl($curl, '/connect/token', array(), true, $data);
$result = curl_exec($curl);
if ($result === false) {
    // error handling
}
curl_close($curl);

$decoded = json_decode($result);
// the access token
$accessToken = $decoded->access_token;
// the access token expiry in seconds
$expiry = intval($decoded->expires_in);
parameter description
client_id the identifier of the integrating party, obtained upon request from your account manager
client_secret the password associated with the client_id
username the freemarket portal email address associated with the user account representing the integrating service
password the password associated with the user account

Mutual TLS Client authentication endpoint

This endpoints accepts a client id and a client certificate.

Note

The client certificate can be self signed, only the key material and thumbprint is required.

  • HTTP
  • CURL
  • C#
  • Java
POST /connect/mtls/token HTTP/1.1
Host: identity.wearefreemarket.com
Content-Type: application/x-www-form-urlencoded

grant_type=password&scope=freemarketFXAPI&client_id={clientId}&username={userEmail}&password={userPassword}
curl --request POST 'https://identity.wearefreemarket.com/connect/mtls/token'
--header 'Content-Type: application/x-www-form-urlencoded'
--data-urlencode 'grant_type=password'
--data-urlencode 'scope=freemarketFXAPI'
--data-urlencode 'client_id={clientId}'
--data-urlencode 'username={userEmail}'
--data-urlencode 'password={userPassword}'
--key ./cert-key.pem
--cert ./cert.pem
// request token
var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
    Address = disco.TokenEndpoint,

    ClientId = "client",
    ClientSecret = "secret",
    Scope = "api1"
});

if (tokenResponse.IsError)
{
    Console.WriteLine(tokenResponse.Error);
    return;
}

Console.WriteLine(tokenResponse.Json);
String enc = "UTF-8";
URL url = new URL("https://identity.wearefreemarket.com/connect/mtls/token");

HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

KeyStore keyStore = KeyStore.getInstance("PKCS12");
try (InputStream inputStream = new FileInputStream(certFile)) {
    keyStore.load(inputStream, certPassword.toCharArray());			
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX");
kmf.init(keyStore, certPassword.toCharArray());
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), null, null);
conn.setSSLSocketFactory(sc.getSocketFactory());

conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

StringBuilder contentBuilder = new StringBuilder();
contentBuilder.append("grant_type=password&");
contentBuilder.append("scope=freemarketFXAPI&");
contentBuilder.append("client_id=").append(URLEncoder.encode(clientId, enc)).append("&");
contentBuilder.append("username=").append(URLEncoder.encode(userEmail, enc)).append("&");
contentBuilder.append("password=").append(URLEncoder.encode(userPassword, enc));
byte[] content = contentBuilder.toString().getBytes(enc);

conn.setRequestProperty("Content-Length", Integer.toString(content.length));
try (OutputStream outputStream = conn.getOutputStream()) {
    outputStream.write(content);
}
int responseCode = conn.getResponseCode();
if (responseCode != 200) {
    throw new Exception("Unsuccessfull response code: " + responseCode);
}
ObjectMapper mapper = new ObjectMapper();
try (Reader reader = new InputStreamReader(conn.getInputStream(), enc)) {
    HashMap<String, Object> response = mapper.readValue(reader, new TypeReference<HashMap<String, Object>>() {});
    System.out.println("access_token: " + response.get("access_token"));
    System.out.println("expires_in: " + response.get("expires_in"));
    System.out.println("token_type: " + response.get("token_type"));
    System.out.println("scope: " + response.get("scope"));
}
parameter description
client_id the identifier of the integrating party, obtained upon request from your account manager
username the freemarket portal email address associated with the user account representing the integrating service
password the password associated with the user account
Note

The mutual TLS endpoint no longer accepts a client secret.

Authentication token structure

A successful authentication request yields a response with a 200 status code and a standard JWT token in its body that looks like the following

{
  "access_token": "eyJhbGciOi...[redacted]...Yv1egxCrAA",
  "expires_in": 900,
  "token_type": "Bearer",
  "scope": "freemarketFXAPI"
}
parameter description
access_token the encoded access token itself
expires_in the lifetime of the token, in seconds
token_type the type of token, always "Bearer"
scope the scope to which the token grants access

The token needs to be passed verbatim in every request to the API in the Authorization header.

GET https://portal.wearefreemarket.com/api/v1/Accounts HTTP/1.1
Host: portal.wearefreemarket.com
Authorization: Bearer eyJhbGciOi...[redacted]...Yv1egxCrAA
Note

The lifetime of the token is 15 minutes. In case of token expiry, the returned response will have a status code of 401 Unauthorized. Token reuse within its lifetime is encouraged.

An unsuccessful authentication request returns a response with a 400 status code and a JSON encoded structure with a single property explaining the erorr

{
  "error": "invalid_client"
}
parameter description
error the authentication error message

Among the possible errors are:

error message problem description
invalid_client the client {clientId} does not exist, or the provided {clientSecret} is incorrect
invalid_user the {username} does not exist, or the provided {password} is incorrect
In this article
Back to top Generated by DocFX