Edenred Direct Payment Services icon

Edenred Direct Payment Services

(0 reviews)

Integration guide

Overview

Edenred Payment Services allows a partner platform to initiate a payment using an ER payment means (meal card...) after authentication of end user (cardholder). The aim of this document is to describe the integration of Edenred Connect (authentication platform) and Edenred Payment APIs.

Edenred Connect environments

The environment base address is called {{xp-identityserver-url}} OR {{authentication-url}} in script samples.

EnvironmentBase address
Sandboxhttps://sso.sbx.edenred.io
ProductionAvailable on request

Payment APIs environments

The environment base address is called {{payment-url}} OR {{xp-fooddelivery-url}} in script samples.

EnvironmentBase address
Sandboxhttps://directpayment.stg.eu.edenred.io/v2
ProductionAvailable on request

Authentication Process

1 / Edenred Connect

Edenred Connect is an identity provider that implements OpenID Connect and OAuth 2.0.

2/ Authorization Code Flow

Authorization Code flow involves a two-step process, where the user validates himself against the authorization server by providing his own identity credentials. Then , Connect validates the user credentials and provides with an Authorization Code.

The authorization code flow offers a few benefits over the other grant types. When the user authorizes the application, they are redirected back to the application with a temporary code in the URL. The application exchanges that code for the access token. When the application makes the request for the access token, that request can be authenticated with the client secret, which reduces the risk of an attacker intercepting the authorization code and using it themselves. This also means the access token is never visible to the user or their browser, so it is the most secure way to pass the token back to the application, reducing the risk of the token leaking to someone else.

3/ Requirement

The prerequisite of this flow is that the client application must be registed in Connect to obtain a clientId and a clientSecret which are needed during the token exchange requests.

The client should be configured with:

  • allowedGrantTypes: should contains authorization_code in order to use Authorization Code Flow. Otherwise, the authorization fail.
  • allowedScopes: a list of scopes to be used while authorization, if the requested scope in not mentioned in this list, the authorization fails.
  • redirectUris : lists of accepted redirects Urls , if the requested redirecturl is not mentioned in this list, the authentication fails.
  • postLogoutRedirectUris : lists of accepted Urls for logout.

Note : Assert that the client used by you application has the right configuration to use Authorization Code Flow.

4/ Initiating authentication: Login

A/ Authorize Endpoint Request

The authorize endpoint can be used to request tokens or authorization codes via the browser. This process typically involves authentication of the end-user and optionally consent.

GET /connect/authorize?                           HTTP 1.1
       response_type={{authentication_response_type}}
       &client_id={{authentication_clientId}}
       &scope={{authentication-scopes}}
       &redirect_uri={{authentication-redirectUri}}
       &acr_values={{authentication-tenant}}
       &ui_locales={{authentication_ui_locales}}
       &state={{authentication-state}}
       &nonce={{authentication-nonce}}
  • response_type : for Authorization Code Flow the value of {{authentication_response_type}} should be *code. The client should have "authorization_code" in the list allowedGrantTypes.
  • client_id *: unique idenitifier the client.
  • scopes *: Scope is a mechanism in OAuth 2.0 to limit an application's access to a user's account. An application can request one or more scopes, this information is then presented to the user in the consent screen, and the access token issued to the application will be limited to the scopes granted. . The client should have the requested scope in its allowedScopes.
    • openid
    • offline_access : offline_access scope is required for requesting refresh token.Other scopes or Api Ressources can be used like: profile, phone, address ...
  • redirect_uri *: The uri , where connect will redirect the code, must exactly match one of the allowed redirects URIs for that client.
  • arc_values * : allows passing in additional authentication related information, like tenant. acr_values: tenant:name_of_tenant
  • ui_locales *: a hint about the desired display language of the login UI.
  • state : echos back the state value on the token response, this is for round tripping state between client and provider, correlating request and response and CSRF/replay protection. (recommended).
  • nonce : echos back the nonce value in the identity token (for replay protection), Required when identity tokens is transmitted via the browser channel.

Request Example

GET https://sso.eu.edenred.io/connect/authorize           HTTP 1.1
         ?client_id=12e7e1dd73e64735a1ee51f73bf9a3a5
         &response_type=code
         &scope=openid%20%20autoconnect
         &redirect_uri=https%3A%2F%2Fwww.myedenred.be%2FAccount%2FSignInCallback
         &state=c51f9804a00d434fb01aef820c94ca62
         &nonce=43aa3cb027424579820ed46fd24fdafe
         &acr_values=tenant%3Abe-ben
         &ui_locales=FR

After successful authentication, a consent page pops up.

A consent page normally renders the display name of the current user, the display name of the client requesting access, the logo of the client, a link for more information about the client, and the list of resources the client is requesting access to. It’s also common to allow the user to indicate that their consent should be “remembered” so they are not prompted again in the future for the same client.

Once the user has provided consent, the consent page must inform your IdentityServer of the consent, and then the browser must be redirected back to the authorization endpoint.

C/ Redirected response

HTTP/1.1 302 Found
Location: https://redirect_uri/callback?code={{code}}&scope={{scopes}}&state={{state}}&session_state={{sessionState}}
Example of Redirect
https://redirect_uri/callback
      ?code=35C3E7F0C5132BC2D588C29BA5C0EF9FD764EEB500488E39D8F864AFF0319C12
      &scope=openid%20profile%20offline_access%20email
      &state=statesOne
      &session_state=arfoASULTUTzj3v6v2jNygeRnMKQ4ml1OYtLhnyatak.608522AE6F2BD29FB235E285B5049135

This callback must be handled server-side in order to get the code in query params and use it later to retive access-token and refresh token from Connect.

5/ Retrieve Token using Code

A/ Retrieve Token Request

After Retrieving the code, the client then opens a back-channel communication to the token service to retrieve the tokens from Connect Token Endpoint.

POST /connect/token                                 HTTP 1.1
    CONTENT-TYPE application/x-www-form-urlencoded
    BODY :
    client_id={{authentication_clientId}}&
    client_secret={{authentication_secret}}&
    grant_type={{authorization_code}}&
    code={{authentication_code}}&
    redirect_uri={{redirect_url}}
  • client_id *: unique idenitifier the client.
  • client_secret *: client secret.
  • grant_type : for Authorization Code Flow the value of {{authorization_code}} should be *authorization_code.
  • redirect_uri *: the same redirect uri used to retrive Code from authorization endpoint.
  • code *: The code recived in the callback url.

Example of Request

    POST  https://sso.eu.edenred.io/connect/token         HTTP 1.1
    CONTENT-TYPE application/x-www-form-urlencoded
    BODY :
    client_id=934fc8072faa423086cac8c6c62a2b5e
    &client_secret=secret
    &grant_type=authorization_code
    &code=B1CEDCFE0F57F5966AAC7361033EA8761A965415010258909FA2EF50CD5F7B60
    &redirect_uri=https://redirect_uri/callback

B/ Retrieve Token Response

Connect will return a json response containing all the required information to authenticate: The id_token , access_token , expires_in , token_type , refresh_token , scope.

HTTP/1.1 200 OK
Content-Type: application/json
{
   "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjcyOTAyQkZDQkI4Njk1NTc5NUU1NThDNzNEQUZEMTNFIiwidHlwIjoiSldUIn0.eyJpc3MiOiJodHRwczovL2xvY2FsaG9zdDo1MDAxIiwibmJmIjoxNjQ4NzQwMzM4LCJpYXQiOjE2NDg3NDAzMzgsImV4cCI6MTY0ODc0MDYzOCwiYXVkIjoiOTM0ZmM4MDcyZmQ4NDIzMDg2Y2FjOGM2YzYyYTJiNWUiLCJhbXIiOlsicHdkIl0sImF0X2hhc2giOiJSS21XdWVPeWxFV3ViWEYtMl9HLUl3Iiwic19oYXNoIjoiM1hRdlJOVVVMbXJFVGNodmxaTER6USIsInNpZCI6IjkzNTRDQzM1RDY5QjJGRTQxOTkwREY2NzlCQ0VGRjBBIiwic3ViIjoibW9ja1xcbW9jayIsImF1dGhfdGldsdsdsdZSI6MTY0ODczNjYyMywiaWRwIjoibG9jYWwiLCJ0ZW5hbnQiOiJtb2NrIiwidXNlcm5hbWUiOiJtb2NrIn0.LxpPH3EWtfGU98S4QtrR0NTknCLfFkBJqAc_kfQ4O3eEOLT6X3UclsvS6S02M7QLQMlkPFemOu_tthyDOxznidQA_DkZmsa2zoEfCpupjsI5Hvuk5_xXD-NJMiXWHWE2QlL0vQkuJa-Qrw_2wZkvVhJmEHJ7z4lD-fEEkmGbSMo6DuhQ95b5okEhG4-IPULALyesIycbZiQWJTujOuT6RnkoKNOJ4wFLQHuznx3uLUFCA5IrK0Rvm4U5_cM_DIlXguPOhKi-oT3rYmr8DfVIAyl3YRwqSfV5GwZadYTqOHbT-iwDkXR6zlzYRGEmS5HOTjdhG4AiwQOIZkM0OUftmA",
   "access_token": "C0D2DF58D0140728952F53B4BB8CA94D28D3B0CCD88695115BEC0384C7246FF36",
   "expires_in": 3600,
   "token_type": "Bearer",
   "refresh_token": "94BDBF77BB1FAF97F79BEE68ACE0AA966CEAB1305FEAB0D5F1D82CBEAA723112",
   "scope": "openid profile offline_access email"
}

Tokens must be stored securely server-side. Connect token is a JWT (standalone) token containing information about user and authentication process (https://jwt.io), it has a very short lifetime.

6/ User Info Endpoint

A/ User Info Request

The UserInfo endpoint can be used to retrieve claims about a user. The caller needs to send a valid access token. Depending on the granted scopes, the UserInfo endpoint will return the mapped claims.

GET /connect/userinfo    HTTP/1.1
Authorization: Bearer {{access_token}}

B/ UserInfo Response

The user infos informations , depends to the client allowed scopes, and the scopes requested while authorization.

HTTP/1.1 200 OK
Content-Type: application/json

{
   "sub": "Teant\\username",
   "name": "Bob Smith",
   "tenant": "Teant",
}

7/ Refreshing Token

To get a new access token, you send the refresh token to the token endpoint. This will result in a new token response containing a new access token and its expiration and potentially also a new refresh token depending on the client configuration.

A/ Refreshing Token Request

POST /connect/token                         HTTP/1.1
   CONTENT-TYPE application/x-www-form-urlencoded
   BODY :
   client_id={{authentication-clientId}}&
   client_secret={{authentication-clientSecret}}&
   grant_type=refresh_token&
   refresh_token={{refresh_token}}

B/ Refreshing Token Response

HTTP/1.1 200 OK
Content-Type: application/json
{
   "id_token": "{{Jwt_token}}",
   "access_token": "C0D2DF58D0140728952F53B4BB8CA94D28D3B0CCD88695115BEC0384C7246FF36",
   "expires_in": 3600,
   "token_type": "Bearer",
   "refresh_token": "94BDBF77BB1FAF97F79BEE68ACE0AA966CEAB1305FEAB0D5F1D82CBEAA723112",
   "scope": "openid profile offline_access email"
}

Logout

To use the end session endpoint a client application will redirect the user’s browser to the end session URL. All applications that the user has logged into via the browser during the user’s session can participate in the sign-out.

  • id_token_hint: When the user is redirected to the endpoint, they will be prompted if they really want to sign-out. This prompt can be bypassed by a client sending the original id_token received from authentication. This is passed as a query string parameter called id_token_hint.
  • post_logout_redirect_uri: If a valid id_token_hint is passed, then the client may also send a post_logout_redirect_uri parameter. This can be used to allow the user to redirect back to the client after sign-out. The value must match one of the client’s pre-configured PostLogoutRedirectUris.
  • state: If a valid post_logout_redirect_uri is passed, then the client may also send a state parameter. This will be returned back to the client as a query string parameter after the user redirects back to the client. This is typically used by clients to round-trip state across the redirect.
    GET /connect/endsession?id_token_hint={{tokenId}}&post_logout_redirect_uri={{postLogoutRedirectUri}}&state={{state}
    Host: {{authentication-url}}

Revocation Endpoint

This endpoint allows revoking access tokens (reference tokens only) and refresh token. It implements the token revocation specification (RFC 7009).

  • token : the token to revoke (required)

- *token_type_hint : either access_token or refresh_token (optional)

POST /connect/revocation HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

token={{token}}&
token_type_hint={{token_type_hint}}

Full Revocation Endpoint

This endpoint allows full revoking access to a specific user, all current tokens in all allowed tenants for a client. The client should have the scope "revocation" in the allowed scopes.

POST /connect/fullrevocation
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer {{token}}

username={{username}}

Introspect Endpoint

It can be used to validate reference tokens (or JWTs if the consumer does not have support for appropriate JWT or cryptographic libraries). The introspection endpoint requires authentication - since the client of an introspection endpoint is an API, you configure the secret on the ApiResource.

POST /connect/introspect
Content-Type: application/x-www-form-urlencoded
Authorization: Basic xxxyyy

token={{token}}

Consuming Payment APIs

Edenred Payment Services are composed of a set of five (5) APIs:

Retrieve daily available balance

Place an authorization (amount reservation)

Cancel an authorization

Capture an authorization (confirm it and trigger clearing)

* Refund a captured transaction

All these APIs are protected using OAuth 2.0 and a pair of "payment-clientId" & "payment-ClientSecret. They require a valid access_token in Authorization header and both Client-Id & Client-Secret headers.

e.g. :

http

GET /v2/users/{{username}}/balances?mid={{mid}} HTTP/1.1

Host: {{payment-url}}

Authorization: Bearer {{access_token}}

Content-Type: application/json

Client-Id: {{payment-clientId}}

Client-Secret: {{payment-clientSecret}}

Please refer to the use case per country and the specification for further details on the API implementation


Reviews