HowTo implement Europace auth-code-flow

Step1 - client registration at europace

Needed registration-information:

  • necessary scopes to register on client
    • (scope=openid is needed for the flow)
  • your redirect-uri, we call after user-approval (path-param code is accepted)
    • for security purpose, the uri is not dynamic for the process, only one redirect-uri is registered

Handover from europace after client-registration:

  • client-id
  • client-secret

The following data is now prepared:

Discovery-Endpoint contains:

authorization_endpoint:https://www.europace2.de/authorize
token_endpoint:https://api.europace.de/auth/token
issuer:https://api.europace.de
jwks_uri:https://api.europace.de/auth/signing-keys
response_types_supported:code
request_uri_parameter_supported:true
subject_types_supported:public
end_session_endpoint:https://www.europace2.de/authorize/logout
id_token_signing_alg_values_supported:ES384

Step2 - flow-implementation at your application

The diagram is showing the flow and steps of the authorization process.

diagram auth-code-flow

After registration, you can create a link for the browser to get an id-token after user-authentication and user-consent for your client (step (1) in the diagram):

https://www.europace2.de/authorize/
?response_type=code
&client_id=[client-id]
&redirect_uri=[redirect-uri]
&scope=[registered and needed scopes]%20openid
&state=[yourDataForRedirectUri]
&prompt=select_account

This link will start the authentication process in the browser. The User will be authenticated and give the user-consent for the requested scopes and the client.

To close the registration-circle, we call back the redirect-uri in the browser with path-param code and state. If user already authenticated and user-consent already exists, the browser will directly redirect to your redirect-uri.

Europace will redirect to:

[redirect-uri]?code=[oneTimeCode]&state=[yourDataForRedirectUri]

Example:

https://client.example.org/?code=GGu48n-64cQen4gu&state=HelloWorld

State can be used to pass information through the process like sessions, user-id or security-handles.

With the code you can get an id-token for the authenticated user (step (2) in the diagram). Use your client-id and client-secret as basic authentication credentials for POST-Form with grant-type, code and redirect-uri. Usually, the redirect-uri has to be encoded.

Example-Request:

POST /auth/token HTTP/1.1
Host: api.europace.de
Authorization: Basic VlVIN...
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=GGu48n-64cQen4gu
&redirect_uri=https%3A%2F%2Fclient.example.org%2F

Example-Response:

{
   "access_token": "eyJraWQiO...",
   "scope": "openid profile baufinanzierung:vorgang:schreiben profile baufinanzierung:vorgang:lesen",
   "id_token": "eyJraWQiOiJPTE...",
   "token_type": "Bearer",
   "expires_in": 3600
}

If you need the access-token, only in the presence of the user, you can use this access-token.

In the process, problems could occur. In most problem-cases, we will provide the code but you can not get an access-token. You will get an error-message, which you can handle. The process ends unsuccessfully.

Possible problems:

  1. use declined the user-consent
  2. user are not allowed to use the client

Step3 - get an access-token without user-interaction (optional)

If you need access-token for backend-jobs, where the user is not present, you can link your user-data with the europace-user-profile by storing the europace-partner-id. This step is not shown in the diagram. To get the partner-id, inspect the id-token with decoding ES384, you will receive important information in the payload. You will find a lot of libs for your prefered code-language at www.jwt.io to decode jwt-tokens with ES384.

Example decoded id-token with scope=openid:

{
  "sub": "ABC12",
  "aud": "XMLM6XIG5JALVM3V",
  "auth_time": 1620743169,
  "iss": "https://api.europace.de",
  "exp": 1620752934,
  "iat": 1620745734,
  "jti": "cS_ZHi80_W958vNV"
}

Example decoded id-token with scope=profile openid:

{
  "sub": "ABC12",
  "iss": "https://api.europace.de",
  "preferred_username": "theo.test@example.org",
  "given_name": "Theo",
  "picture": "https://www.europace2.de/partnermanagement/d71c58aeaed4022384b169f83e0d8842.avatar?anonymousAvatar=BENUTZER
",
  "aud": "VUH5WE2SVDPBDJFD",
  "auth_time": 1620741571,
  "vo": "YOUR_ORGANISATION",
  "exp": 1620748826,
  "iat": 1620741626,
  "family_name": "Test",
  "email": "theo.test@example.org",
  "jti": "uW12IT_krnR0Zyrp"
}

sub contains the authenticated partnerId. Store the partnerId on your user-data to get an access-token in the future without any user-interaction.

To get the access-token use your client-id and client-secret as basic authentication credentials for POST-Form with grant-type, scope, actor and subject

Example-Request:

POST /auth/token HTTP/1.1
Host: api.europace.de
Authorization: Basic VlVIN...
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&scope=[registered and needed scopes]
&actor=[sub from id-token]
&subject=[sub from id-token]

If your client is valid and the user-consent exists and all requested scopes are registered on the client and approved by the user you should receive an access-token.

Example-Response:

{
   "access_token": "eyJraWQiOi..",
   "scope": "openid baufinanzierung:vorgang:schreiben profile baufinanzierung:vorgang:lesen",
   "token_type": "Bearer",
   "expires_in": 3600
}