Developers can build their own applications to manage user data in Lokalise using the OAuth 2 authentication flow.

With the OAuth 2 authentication, an application can make requests to Lokalise APIv2 on behalf of a user.

If you are looking for sample apps utilizing OAuth 2 flow, you can find those at our DevHub.

Index

Authorization flow

OAuth 2 is an authorization protocol that allows a user to grant third-party applications access to their information on another site.

This process can be separated into three stages:

  1. The user requests an access code.

  2. The user makes a request with the access code and receives an access token. The user can receive data from Lokalise with this access token.

  3. After the access token expires the user makes a request to refresh the token.

The authorization flow is shown in more detail in the following diagram:

Register a new application

To register your app with Lokalise, you should contact our support team and provide the following information:

  • Title of your application

  • Logo of your application

    • Supported size is 150x150px.

    • Supported formats are PNG and JPG.

  • Description of your application (this field is optional).

  • Link to app website/documentation (this field is optional).

  • Required scopes. Find the list required scopes for the corresponding API endpoints in the Lokalise API description.

OAuth 2 authorization overview

Lokalise is using OAuth 2.0 authorization protocol implementation of authorization code flow.

Prerequisites

  • The app should be registered with Lokalise. OAuth client ID ("Client ID") and OAuth client secret ("Client Secret") should be obtained.

  • Publicly available URL, where the user will be redirected after the authentication ("Redirect URI").

Step 1. Obtain Authorization Code

The app should redirect the user to the auth URL. After a successful authorization users are forwarded to the redirect URL with the authorization code as a parameter.

The request should be sent to the following URL:

https://app.lokalise.com/oauth2/auth

URL parameters:

client_id

The App Client ID received after registration

redirect_uri

The URL in your application where users will be sent after authorization.

scope

Scopes the app requires. Multiple scopes should be separated with spaces.

state

A random string used for protection against CSRF attacks. (Optional if you are not using redirect_uri)

Example request:

https://app.lokalise.com/oauth2/auth?client_id=SomeClientID&redirect_uri=https://example.com/auth/success&scope=write_projects+read_keys&state=someRandomStateString

User will be redirected to the following URL:

https://example.com/auth/success?oauth_code=oauthCodeReceived

Step 2. Obtain access token

The app can use the authorization code received to obtain the access token. To achieve that, the app should send a POST request to the access token URL.

URL parameters:

grant_type

Specifies action to be taken (should be authorization_code)

client_id

The app client ID received after registration

client_secret

The app client secret received after registration

code

The code received after successful user authentication and redirect

Example request with cURL:

curl -X POST \ 
https://app.lokalise.com/oauth2/token \
-H "content-type: application/json" \
-d "{
\"grant_type\":\"authorization_token\",
\"client_id\":\"SomeClientID\",
\"client_secret\":\"SomeClientSecret\",
\"code\":\"yourCode\"
}"

A successful response should contain the following data:

access_token

Access token to use for request authentication

refresh_token

Refresh token to use to obtain new access token after the current expires.

expires_in

Amount of seconds until the access token expires (Usually, 1 hour)

token_type

The authorization token type used. Will be required for authenticated requests. (Usually, "Bearer").

Example:

{ 
"access_token":"someAccessToken",
"refresh_token":"someRefreshToken",
"expires_in": 3600,
"token_type": "Bearer"
}


Make requests to the API

The app now can make requests to Lokalise API on behalf of the authorized user. In order to authorize a request, the Authorization request header must contain the token type and the actual access token.

Request example with cURL:

curl -H "Authorization: Bearer someAccessToken" https://api.lokalise.com/api2/projects

Step 3. Refresh token

For security reasons, the access token has a relatively short expiration time. In order to prevent user from reauthorizing the app after the token expiration, the app can obtain new access token using refresh token.

The app should send a POST request to the access token URL.

grant_type

Specifies action to be taken. (Should be "refresh_token").

client_id

The App Client ID received after registration

client_secret

The App Client Secret received after registration

refresh_token

The refresh token obtained with "authorization_code" request

Example with cURL:

curl -X POST \ 
https://app.lokalise.com/oauth2/token \
-H "content-type: application/json" \
-d "{
\"grant_type\":\"refresh_token\",
\"client_id\":\"SomeClientID\",
\"client_secret\":\"SomeClientSecret\",
\"refresh_token\":\"someRefreshToken\"
}"

A successful response should contain the following data:

access_token

Access token to use for request authentication

scope

Scopes the token has access to (see required scopes for needed API calls in descriptions below)

expires_in

Amount of seconds until the access token expires (usually, 1 hour)

token_type

The authorisation token type used. Will be required for authenticated requests. (usually, "Bearer").

Example:

{ 
"access_token":"someAccessToken",
"scope":"write_projects",
"expires_in": 3600,
"token_type": "Bearer"
}

OAuth 2 request errors

If an OAuth request results in an error, the response will an HTTP status code 400 and the body will contain a JSON object with the following fields:

error

Error name

error_description

Error description

state

(Optional) The state string added on the Authorization code request

Example:

{ 
"error":"invalid_request",
"error_description":"Invalid post body",
"state":"someRandomStateString"
}

Examples

Ruby

The easiest way to manage OAuth 2 tokens is by using our ruby-lokalise-api gem. You can take the following approach:

# Create auth client with your client id and secret
auth_client = Lokalise.auth_client 'OAUTH2_CLIENT_ID', 'OAUTH2_CLIENT_SECRET'

# Generate authentication URL. Your users must visit this URL and explicitly grant access. As a result they'll obtain a secret code
url = auth_client.auth scope: 'read_projects', redirect_uri: 'http://example.com/callback', state: 'random string'

# Use the secret code to obtain OAuth 2 token
response = auth_client.token 'secret code'
token = response['access_token']

# Refresh the token once it expires
refresh_token = response['refresh_token']
new_token = auth_client.refresh(refresh_token)['access_token']

Our Ruby client supports both personal API tokens and OAuth 2 tokens. To use the latter, initialize the client in the following way:

@client = Lokalise.oauth2_client 'YOUR_OAUTH2_ACCESS_TOKEN'

projects = @client.projects # fetch all projects the user has access to

For Rails, you can take advantage of the omniauth-lokalise gem which makes the process of setting up OAuth 2 flow even simpler.

Python

Use our python-lokalise-api library to manage OAuth 2 tokens:

# Create auth client with your client id and secret
auth_client = lokalise.Auth('client id', 'client secret')

# Generate authentication URL. Your users must visit this URL and explicitly grant access. As a result they'll obtain a secret code
url = auth_client.auth(["read_projects", "write_team_groups"], "http://example.com", '123abc')

# Use the secret code to obtain OAuth 2 token
response = auth_client.token('auth code')
token = response['access_token']

# Refresh the token once it expires
refresh_token = response['refresh_token']
new_token = auth_client.refresh(refresh_token)['access_token']

Our Python client supports both personal API tokens and OAuth 2 tokens. To use the latter, initialize the client in the following way:

client = lokalise.OAuthClient('YOUR_OAUTH2_API_TOKEN')

projects = client.projects() # fetch all projects the user has access to

PHP

Example of a PHP application with OAuth2 authentication:

<?php
/**
* Example of a php application with OAuth2 authentication
*/

const AUTH_ENDPOINT = 'https://app.lokalise.com/oauth2/auth';
const TOKEN_ENDPOINT = 'https://app.lokalise.com/oauth2/token';
const API_ENDPOINT = 'https://api.lokalise.com/api2';
const CLIENT_ID = 'SomeClientID';
const CLIENT_SECRET = 'SomeClientSecret';
const SCOPE = 'read_projects';

$auth_redirect_uri = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
// Should be the app static url instead

// Session will be used here as an example to store token data. Real application should use a safer and more persistent storage
session_start();

// Handle incoming requests
if ($_GET['code']) {
// requestAuthorizationCode request successful result
$_SESSION['token_data'] = obtainAccessToken($_GET['code']);
}

if (!$_SESSION['token_data']) {
// Start authentication process
requestAuthorizationCode($auth_redirect_uri);
return;
}

// App action handling
if ($_GET['action']) {
switch ($_GET['action']) {
case 'logout':
unset($_SESSION['token_data']);
header("Refresh:0");
break;
case 'list_projects':
showProjects();
break;
}
}

// App main menu
echo "<a href='?action=list_projects'>Get projects</a>";
echo "<br />";
echo "<a href='?action=logout'>Logout</a>";

// Oauth flow actions
function requestAuthorizationCode(string $auth_redirect_uri): void
{
$query = [
'client_id' => CLIENT_ID,
'redirect_uri' => $auth_redirect_uri,
'scope' => SCOPE,
'state' => uniqid(),
];
$authorizationUrl = AUTH_ENDPOINT.'?'.http_build_query($query);
// Direct user to authorization page
echo "<a href='$authorizationUrl'>Login</a>";
}

function obtainAccessToken(string $oauthCode): array
{
$payload = [
'grant_type' => 'authorization_code',
'client_id' => CLIENT_ID,
'client_secret' => CLIENT_SECRET,
'code' => $oauthCode,
];

$ch = curl_init(TOKEN_ENDPOINT);
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['Content-Type:application/json'],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_POST => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_RETURNTRANSFER => true,
]);

$response = curl_exec($ch);
curl_close($ch);

return json_decode($response, true);
}

// Example request to the API
function showProjects()
{
$resourceUrl = API_ENDPOINT . '/' . 'projects';
$accessToken = $_SESSION['token_data']['access_token'];
$header = ["Authorization: Bearer $accessToken"];

$curl = curl_init($resourceUrl);
curl_setopt_array($curl, [
CURLOPT_HTTPHEADER => $header,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($curl);
curl_close($curl);

$responseDecoded = json_decode($response, true);

$projects = $responseDecoded['projects'];
echo "<ul>";
foreach ($projects as $project) {
echo "<li>{$project['name']}</li>";
}
echo "</ul>";
}
Did this answer your question?