Last edited 6 months ago
by Serena Cericola

Auth

Revision as of 09:21, 8 February 2024 by Andrea Gazzarini (talk | contribs)

Overview

Share-VDE exposes an OAuth 2.0 authentication system we call Identity Provider (IdP).

It provides both interactive and programmatic authentication, and in this document we will focus on the latter.

The IdP is hosted on the domain ip.svde.org.

The programmatic authentication is achieved through a RESTful HTTP API covering either client-based and user-based authentication use cases.

These are very similar authentication scenarios, indicating, though, different expectations.

Client authentication refers to those cases where an application needs to be authenticated in order to access common service features. This authentication guarantees the server on client’s genuinity, but no further, specific authentication is needed in this case.

On the other hand, user-based authentication binds a client authentication scenario with a specific user authentication.

Both scenarios rely on the server issuing an authentication token, used by a client to sign subsequent business requests.

Before diving into each authentication use case, let’s explore API operations.

Roles

The following table lists the roles defined in Share-VDE at time of writing. Endpoints are not publicly exposed, the caller is supposed to have at least a svde-reader role, which grants read permissions.

Share-VDE Roles
Name Code Description
Reader svde-reader Minimum level role which grants read capabilities on Share-VDE resources.
Basic Editor svde-editor-base Base editing capabilities required for the Curation API (i.e., resources editing). Includes the Reader role.
Advanced Editor svde-editor-advanced Advanced editing capabilities that allow full capabilities on Share-VDE resources. Includes the Basic Editor role.

API operations

Obtain a new authentication token

The first request a client must make to authenticate with ShareVDE is the /token request.

In case of client authentication, you will need client credentials, i.e. a Client ID and a Client Secret issued by Share-VDE.

In case of user authentication, you will need client credentials as well as a username and password.

The request returns a JSON structure containing a new authentication token to be used in subsequent operations.

Request endpoint

HTTP Method Endpoint
POST /auth/realms/ShareVDE/protocol/openid-connect/token

Authorization header

Authorization: Basic <authorization hash>

Here the Client ID and Client Secret issued by Share-VDE come into play.

The authorization hash is computed as follows:

Base64(client_id + “:” + client_secret)

This header must always be present for token requests, regardless of the client or user authentication use case.

Content-Type header

Content-Type: application/x-www-form-urlencoded

Request body

Key Description Value

(Client auth)

Value (User auth)
grant_type The kind of grant operation that is going to be requested to the server client_credentials password
username The user id to authenticate Not applicable <Provided by the user>
password The password to use Not applicable <Provided by the user>

Example - Client authentication request

curl --location --request POST 'https://sit3-ip-base-svde.atcult.it/auth/realms/ShareVDE/protocol/openid-connect/token' \
--header 'Authorization: Basic c2hhcmV2ZGUtYXBpLWdhdGV3YXk6MDU3NzlmYzItNzI5Yy00NmYyLTg2YWYtMTIzNTJkYTY5MmU2' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=sharevde-api-gateway' \
--data-urlencode 'client_secret=a_valid_secret' \
--data-urlencode 'grant_type=client_credentials'

Example - User authentication request

curl --location --request POST \
'https://ip.share-vde.org/auth/realms/ShareVDE/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Referer: https://af4080f8fb8a.ngrok.io/' \
--header 'Authorization: Basic \
c2hhcmV2ZGUtYXBpLWdhdGV3YXk6MDU3NzlmYzItNzI5Yy00NmYyLTg2YWYtMTIzNTJkYTY5MmU2' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=a_valid_user' \
--data-urlencode 'password=a_valid_password'

Example - Authentication response

{
   "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ...",
   "expires_in": 300,
   "refresh_expires_in": 1800,
   "refresh_token": ”eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6IC...",
   "token_type": "bearer",
   "not-before-policy": 0,
   "session_state": "acb9a64f-5309-4536-9fb2-682fe48fd58d",
   "scope": "email profile svde-resource-read"
}

Regardless of the client or user authentication scenario, the successful authentication response has the same structure. Let’s analyze its contents:

  • access_token: the token to be used to sign subsequent business REST requests (see the example later in this document). It is digitally signed by the Share-VDE realm.
  • expires_in: the token’s TTL (in seconds). After this number of seconds has passed since token emission, the token won’t be valid anymore, unless a refresh request is issued by the client.
  • refresh_expires_in: the refresh token’s TTL. It represents indeed the time window (in seconds) within which the client can request the server-side session’s TTL extension. The new session’s TTL will be equal to the amount of seconds expressed with the expires_in member. After the number of seconds expressed by this member has passed, the session won’t be usable anymore.
  • refresh_token: the token to be used to sign the next refresh request (see the example later in this document).
  • token_type: the type of the issued token; for Share-VDE it will be “bearer”, meaning the token must be used in a “Authorization: Bearer” header.
  • not-before-policy: a time-based revocation policy. The server allows administrators to specify a time and date where any session or token issued before that time and date is invalid. For Share-VDE such value will always be zero (i.e. the token is valid starting from the exact moment it is issued).
  • session_state: the session state id. By definition, a session is a continuous period of time during which an end-user or an application accesses a Relying Party relying on the authentication of the end-user performed by the Identity Provider.
  • scope: a space-separated list of strings, showing the scopes represented by the access_token.

Refresh an authentication token

Via the /token request it is possible to request a new access token maintaining the same session_status.

This objective is achieved with the use of the refresh_token operation type (a.k.a grant type).

It is important to point out that access tokens have a usually short TTL and they often expire after only minutes. The additional refresh token that was transmitted by the client_credentials or password operations has a longer TTL and allows the client to obtain a new access token after it expires, maintaining the same session of the original scope.

With short-lived access tokens, things are made more secure and more scalable for the whole system.

Request endpoint

HTTP Method Endpoint
POST /auth/realms/ShareVDE/protocol/openid-connect/token

Authorization header

Authorization: Basic <authorization hash>

The authorization hash is computed as follows:

Base64(client_id + “:” + client_secret)

Content-Type header

Content-Type: application/x-www-form-urlencoded

Request body

Key Description Value (client auth) Value (user auth)
grant_type The kind of grant operation that is going to be requested to the server refresh_token refresh_token
username The user id to authenticate Not applicable <Provided by the user>
password The password to use Not applicable <Provided by the user>
client_id The client id used in the Authorization header <client_id> <client_id>
client_secret The client secret used in the Authorization header <client secret> <client secret>
refresh_token The refresh_token value received with the previous “new token” or “refresh token” response <taken from the previous request> <taken from the previous request>

Example - Client refresh token

curl --location --request POST 'https://ip.svde.org/auth/realms/ShareVDE/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'client_id=my-app-id' \
--data-urlencode 'client_secret=a_valid_client_secret' \
--data-urlencode 'refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCIgOiA...'

Example - User refresh token

curl --location --request POST 'https://idp.svde.org/auth/realms/ShareVDE/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'client_id=my-app-id' \
--data-urlencode 'client_secret=a_valid_client_secret' \
--data-urlencode 'username=a_valid_username' \
--data-urlencode 'password=a_valid_password' \
--data-urlencode 'refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCIgOiA...'

Example - Refresh response

{
   "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICz...",
   "expires_in": 300,
   "refresh_expires_in": 1800,
   "refresh_token": ”eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwiaAkzmjsHdu...",
   "token_type": "bearer",
   "not-before-policy": 0,
   "session_state": "acb9a64f-5309-4536-9fb2-682fe48fd58d",
   "scope": "email profile svde-resource-read"
}

The successful refresh token response has the same structure as the new token response. Refer to that section for a description of each field.

Example of a business request

The general principle is that both GraphQL API and REST api are protected by Share-VDE’s IdP.

We must use received access tokens to sign every request towards those two interfaces.

Let’s see how to perform a request towards the /api/graphql endpoint.

NOTE: Until the definitive Share-VDE environment will be available, instead of api.svde.org please use beta-base.svde.org.
curl --location --request POST 'https://api.svde.org/api/graphql' \
--header 'Authorization: Bearer eyJhbGcIgOiAiSldUIiwia2lkIiA6ICJ5eDZhRjZtM3ZTZkdIO...' \
--header 'Content-Type: application/json' \
--data-raw '{"query":"{\n  person(uri: \"https://share-vde.org/agents/201631288953646\") {\n    uri\n    preferredHeading\n    occupations {\n      uri\n      language\n      preferredHeading\n      alternateHeadings\n    }\n  }\n}","variables":null,"operationName":null}'

Error responses

In case of errors, the Share-VDE’s authentication RESTful API responds with the following HTTP status codes:

400 Malformed request. The request is incomplete or the payload is malformed.
401 Unauthorized. The authentication is possible but has failed or has not been provided yet.
403 Forbidden. The resource is available, but the authorization level is not sufficient in order to access it.