Authentication
Learn how to deal with Authentication.
Authentications is needed for all calls to GBFS API, this can be done by using the credentials provided.
Depending on the type of credentials provisioned, the steps for generating an signing the token are different.
The credentials type can be identified by simply looking at the domain of the email provided with the credentials:
- External Organization:
@external.organization.ridedott.com
. - IAM (Deprecated):
@identity.iam.ridedott.com
or@com-ridedott-third-party.iam.gserviceaccount.com
.
Select the tab that matches your credentials type!
- External Organization
- IAM (Deprecated)
comment: cspell:ignore pyjwt,ntte,utcnow,timedelta
Requirements
The GBFS API follows a custom variant of the
Oauth2 credentials grant
to facilitate authentication and authorization for our clients.
Consumers of the GBFS API should be able to generate and sign a valid JSON Web Token (JWT) using the provided credentials.
The JWT can be passed via an Authorization
header in the request as a
Bearer token
:
Authorization: Bearer token
Generating and Signing a Valid JWT
This section intends to show how to use the provisioned API credentials for generating and signing the token.
-
Every request to the GBFS API must carry a newly generated token.
- Every JWT has a minimum lifetime of 60 seconds and a maximum of 3600 seconds (1 hour). Furthermore, each token on the same key must have a timestamp that is later than any previously used token.
Please note that audience
must be specified properly depending on which
environment the request is going to be performed:
- staging
- production
https://gbfs.api.staging.ridedott.com
https://gbfs.api.ridedott.com
The following examples are using "https://gbfs.api.staging.ridedott.com"
as
audience
.
Here is an example of a generated JWT:
eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjYyMGY2OTRhLWJhZDktNGYxZS04ZjMwLTY3NWZkMTJkNjM2NCJ9.eyJpYXQiOjE2NTk2MjAyNzYsImV4cCI6MTY1OTYyMDI3NywiYXVkIjoiaHR0cHM6Ly9nYmZzLmFwaS5zdGFnaW5nLnJpZGVkb3R0LmNvbSIsImlzcyI6IlB1UktxMngyckNZa01YZG9JNFFuMHdtR3c4ajFAZXh0ZXJuYWwub3JnYW5pemF0aW9uLnJpZGVkb3R0LmNvbSIsImp0aSI6ImM2NzE1NDgyLWQzODQtNDJjNi05OTNhLWZmMmE5ZDRlMTdiYiJ9.7l0kRdMGbxwRN_TyOksa6j6Dc3fQHAYLcSe0euiXrRTrh77Btwp-5yKFCwQc4snMIwWAdW5lDRjQwP3S1B9xYw
Note that this is a deactivated token.
Node.js
Prerequisites:
Create an npm package:
npm init
Install the required dependencies:
npm install jsonwebtoken uuid uuidv4 --save
Create a new file bin/index.js
within your node package
// This file lives in ./bin/index.js
const jwt = require('jsonwebtoken');
const fs = require('fs');
const { v4: uuidv4 } = require('uuid');
// The required EC private key that you were provided
const privateKey = fs.readFileSync('private.key');
// This can be empty for this example
const payload = {};
// Algorithm must be ES256
// For `kid` use the key you were provided
const header = {
alg: 'ES256',
kid: '{your-key-id}',
};
// Assemble the options
const options = {
header: header,
// Expiration timestamp MUST BE between 60 and 3600 seconds
expiresIn: 60,
// Use the identity ID to form the `issuer`
issuer: '{your-organization-id}@external.organization.ridedott.com',
// This remains constant regardless if you use gRPC or REST endpoints
audience: 'https://gbfs.api.staging.ridedott.com',
// Random UUID must be generated for each request
jwtid: uuidv4(),
};
const token = jwt.sign(payload, privateKey, options);
console.log(token);
Get the token by running the node script
node bin/index.js
Python
Prerequisites:
- python3 installed
- dependencies installed
pip3 install pyjwt cryptography
import jwt
import uuid
import datetime
# Replace those with real values.
FAKE_KEY_ID = '73oPlD8nBlf7ts19JKJ0ntteZT55' FAKE_ORGANIZATION_ID =
'1CpBmkB67iDkXg9cwlIc' KEY_VALIDITY_SECONDS = 60
# Algorithm must be ES256
headers = { 'alg': 'ES256', 'kid': FAKE_KEY_ID, }
options = { 'exp': datetime.datetime.utcnow() +
datetime.timedelta(seconds=KEY_VALIDITY_SECONDS), 'iss':
f'{FAKE_ORGANIZATION_ID}@external.organization.ridedott.com', 'aud':
['https://gbfs.api.staging.ridedott.com'], # Random UUID must be generated for each request
'jti': str(uuid.uuid4()), }
# Read the private key from a file
with open('private.key', 'r') as key_file: private_key = key_file.read()
# Generate the JWT
token = jwt.encode(options, private_key, algorithm='ES256', headers=headers)
print(token)
The IAM flow has been deprecated for any new consumers. However if you received your credentials for this flow, this documentation is still relevant for those.
Requirements
The GBFS API follows the
Oauth2 credentials grant
authorization flow. In which the client can request an access token using only its client credentials.
Consumers of the GBFS API should be able to generate and sign a valid JSON Web Token (JWT) using the provided credentials.
The JWT can be passed via an Authorization
header in the request as a
Bearer token
:
Authorization: Bearer token
Generating and Signing a Valid JWT
This section intends to show how to use the provisioned API credentials for generating and signing the token using Node.js.
-
Every request to the GBFS API must carry a newly generated token.
- Every JWT has a minimum lifetime of 60 seconds and a maximum of 3600 seconds (1 hour). Furthermore, each token on the same key must have a timestamp that is later than any previously used token.
Prerequisites:
Create an npm package:
npm init
Install the required dependencies:
npm install jsonwebtoken uuid uuidv4 --save
Create a new file bin/index.js
within your node package
Please note that audience
must be specified properly depending on which
environment the request is going to be performed:
- staging
- production
https://gbfs.api.staging.ridedott.com
https://gbfs.api.ridedott.com
The following examples are using https://gbfs.api.staging.ridedott.com as
audience
.
Depending on the type of credentials provisioned the steps for generating an signing the token are different.
The credentials can be either IAM type or Google Service Account.
They can be identified by simply looking at the domain of the email provided with the credentials:
- IAM:
@identity.iam.ridedott.com
- GSA:
@com-ridedott-third-party.iam.gserviceaccount.com
- IAM
- GSA
// This file lives in ./bin/index.js
const jwt = require('jsonwebtoken');
const fs = require('fs');
const { v4: uuidv4 } = require('uuid');
// The required EC private key that you were provided
const privateKey = fs.readFileSync('private.key');
// This can be empty for this example
const payload = {};
// Algorithm must be ES256
// For `kid` use the key you were provided
const header = {
alg: 'ES256',
kid: '{your-key-id}',
};
// Assemble the options
const options = {
header: header,
// Expiration timestamp MUST BE between 60 and 3600 seconds
expiresIn: 60,
// Use the identity ID to form the `issuer`
issuer: '{your-identity-id}@identity.iam.ridedott.com',
// This remains constant regardless if you use gRPC or REST endpoints
audience: 'https://gbfs.api.staging.ridedott.com',
// Random UUID must be generated for each request
jwtid: uuidv4(),
};
const token = jwt.sign(payload, privateKey, options);
console.log(token);
// This file lives in ./bin/index.js
const jwt = require('jsonwebtoken');
const serviceAccountKey = {
type: 'service_account',
project_id: 'project',
private_key_id: 'private-key-id',
private_key: 'private-key',
client_email: 'service-account-email',
client_id: 'service-account-id',
auth_uri: 'https://accounts.google.com/o/oauth2/auth',
token_uri: 'https://oauth2.googleapis.com/token',
auth_provider_x509_cert_url: 'https://www.googleapis.com/oauth2/v1/certs',
client_x509_cert_url:
'https://www.googleapis.com/robot/v1/metadata/x509/service-account-email',
};
const generateSignedToken = (credentials) =>
jwt.sign(
{
email: credentials.client_email,
},
credentials.private_key,
{
algorithm: 'RS256',
audience: 'https://gbfs.api.staging.ridedott.com',
expiresIn: 360,
keyid: credentials.private_key_id,
issuer: credentials.client_email,
subject: credentials.client_email,
},
);
const token = generateSignedToken(serviceAccountKey);
console.log(token);
Get the token by running the node script
node bin/index.js
Here is an example of a generated JWT:
eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ik80SUZVTmsxZjdVQk53T2xKbjV4In0.eyJpYXQiOjE2NTk2MjAyNzYsImV4cCI6MTY1OTYyMDI3NywiYXVkIjoiaHR0cHM6Ly9nYmZzLmFwaS5yaWRlZG90dC5jb20iLCJpc3MiOiJQdVJLcTJ4MnJDWWtNWGRvSTRRbjB3bUd3OGoxQGlkZW50aXR5LmlhbS5yaWRlZG90dC5jb20iLCJqdGkiOiJjNjcxNTQ4Mi1kMzg0LTQyYzYtOTkzYS1mZjJhOWQ0ZTE3YmIifQ.V_azrM3-URJUXILwroMeC8rl77BwlS0-5C_HSy0mcb5LWkpkMygoIf3KsfYYDAuVLHoThGAFfAtgYEuT3yAuJw
Note that this is a deactivated token.
Test the token
Run the following command to make a request to either staging or production environment:
- Staging
- Production
curl --location --request GET \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token-from-previous-step}' \
'https://gbfs.api.staging.ridedott.com/vehicles'
curl --location --request GET \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token-from-previous-step}' \
'https://gbfs.api.ridedott.com/vehicles'