SSO and M2M

SSO and Machine-to-Machine Interfaces (M2M)

The following section is a description of a possible technical solution of how an SSO-protected resource can be accessed in an automated manner and is applicable from Portal Release 3.15 from March 05. It shall not be considered the only technical solution to apply, and any OAuth 2.0 compatible implementation serving and accepting Bearer Access Tokens will also be valid. Therefore, the following text is to be treated as just an example and the reader is encouraged to research more resources online, including use of possible off-the-shelf OAuth and OIDC libraries.
Note that OAuth 2.0 specification supports several grant flows, and an appropriate flow shall be used depending on the application in question.

If you operate an automated application requiring access to an SSO-protected resource (e.g. a product, an API), it shall also be registered in our SSO platform, enabling it to use its own client_id and client_secret pair. For that purpose, please fill the OIDC M2M Client Profile Request.
For your convenience, you can find a zip file with example scripts here.

Using OAuth 2.0 protected resources

The full API documentation can be found on-line at: https://oauth.net/2/
The process sequence is as follows:

  1. The requesting application (typically a non-interactive script) uses its client_id and
    client_secret pair as well as a scope to obtain a valid SSO token.
  2. The calling service embeds the token into an API query and sends it to the receiving service,
  3. The service validates the received SSO token, and verifies that the user is properly
    authenticated and authorized to access the requested resource.

Scope and access token audience claim

To protect access tokens from misuse by compromised actors, typically an audience claim is embedded in the token. The receiving service validates this claim and rejects tokens with an invalid audience.
The audience included in the token is determined by the scope parameter used during the token request and should include the client_id of the Resource Server. Reosurce Server must reject tokens with audience not including its client_id. The scope should be configured to the client_id of the server hosting a resource to be accessed, which is then mapped by the IdP to the respective audience value. The way to identify the client id of the Resource Server (under e.g. https://product- site.example.com) is leveraging its OIDC RP flow redirect like so:
curl 'https://product-site.example.com' | grep -o 'client_id=.[^&]*'
Which shall return the id in the following format (sometimes the id is a SHA-like hash, other times it will be another arbitrary string):
client_id=4e0a03aa0edaee3a97c4b6a492e4a52908ba6fc0

Authentication and token retrieval

 This shows a cURL request yielding a valid access_token which should produce a token with audience equal to the RP operating under product-site.example.com domain:
curl \
-d 'client_id=<APP_CLIENT_ID>' \
-d 'app_client_id=<APP_CLIENT_SECRET>' \
-d 'grant_type=client_credentials' \
-d 'scope=4e0a03aa0edaee3a97c4b6a492e4a52908ba6fc0' \
'https://sso.s2p.esa.int/realms/swe/protocol/openid-connect/token' | python -m json.tool
{
   "access_token": "SlAV32h…kKG",
   "expires_in": 86400,
   "token_type": "Bearer"
}

Using the token to perform a request on a SWE resource

Again, using cURL, this is how a request to SWE resource would look like:
curl \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
'https://product-site.example.com' > output.txt

This is a GET request. The query result will be written to a file named output.txt. Please consult the curl man page (https://linux.die.net/man/1/curl) for further options, which may be required by the service that is being called.

Checking token validity

To check the user session through OAuth 2.0 API, both the client and the resource server could use the token introspection endpoint as follows:
curl \
  -d "token=" \
  -d "client_id=" \
  -d "client_secret=" \
'https://sso.s2p.esa.int/realms/swe/protocol/openid-connect/token/introspect' | python -m json.tool

Which will verify and return information about the passed token, returning the following example structure:
{
  "exp": 1759747298,
  "iat": 1759746998,
  "jti": "aabbccdd-1122-3344-5566-aabbccddeeff",
  "iss": "https://sso.s2p.esa.int/realms/swe",
  "aud": "4e0a03aa0edaee3a97c4b6a492e4a52908ba6fc0",
  "sub": "aabbccdd-1122-3344-5566-aabbccddeeff",
  "typ": "Bearer",
  "azp": "68ef32b9fc5f57dc910c139ec3b02d91",
  "resource_access": {
    "4e0a03aa0edaee3a97c4b6a492e4a52908ba6fc0": {
     "roles": [
       "product_access"
     ]
  }
},
  "scope": "4e0a03aa0edaee3a97c4b6a492e4a52908ba6fc0",
  "client_id": "68ef32b9fc5f57dc910c139ec3b02d91",
  "username": "service-account-68ef32b9fc5f57dc910c139ec3b02d91",
  "token_type": "Bearer",
  "active": true
}

The "active" field determines the token validity – the resource server will only grant access based on an active token, which includes that server’s own client_id in the audience field "aud".
If the session token is not valid or expired, a simple {"active": false} JSON message is returned.
Note that the token introspection endpoint can be used by either the token owner, or the service that the token was passed on to. Each of them shall use their own client credentials pair.

Logging out

The issued bearer JSON Web Access Tokens (JWT) are relatively short-lived (5 – 15 minutes) and cannot be centrally invalidated. Typically, token shall be cached and reused if possible, and re-requested when close to or after its expiration.

Security and fair use

Client M2M applications shall be sufficiently secured, minimising the risk of their credentials being stolen. Credentials shall not be shared with 3rd parties, and any system generating excessive amount of sessions or batch requests shall be coordinated in advance with the SWE Helpdesk.
ESA might revoke a pair of credentials with no warning if signs of abnormal usage are detected.