Step 3

​This step is all about retrieving the end user identification information like name, social security number (SSN), log on certificate and other personal data.


To get URLs for token and JWKS (required for validating signed ID Token), a request should be sent to the discovery URL []. It is returning a JSON document where the two values of interest are named token_endpoint and jwks_uri.​

String discoveryEndpoint = "";

var response = new HttpClient().GetAsync(discoveryEndpoint).Result;
var responseBody = response.Content.ReadAsStringAsync().Result;

JSONObject discovery = JsonValue.parse(responseBody);
String tokenEndpoint = discovery.getString(discovery, "token_endpoint");
String jwks_uri = discoverygetString(discovery, "jwks_uri");
// A truststore file is used to establish an HTTPS connection. 
// See the implementation of ClaimsService.getHTTPRequest in the demo app source code to 
// see how the values from the app config are used in the HTTPS request.

String truststorepath, truststorepwd; 

HTTPResponse discoveryHTTPResp = getHTTPRequest("", truststorepath, truststorepwd).send();

JSONObject discoveryJsonObject = discoveryHTTPResp.getContentAsJSONObject();
String tokenEndPoint = JSONObjectUtils.getString(discoveryJsonObject, "token_endpoint");
String jwks_uri = JSONObjectUtils.getString(discoveryJsonObject, "jwks_uri");
curl -s

ID token retrieval

Get ID token by doing an HTTP POST request to the token URL. The request should have the following parameters (URL encoded): 

  1. ​​grant_type with the value 'authorization_code'
  2. code with the authorisation code received (URL encoded) in the redirect_uri  (see Step 2)
  3. redirect_uri with the redirect_uri value that was sent in Step 1 ​(this parameter is optional if only one redirect_uri is configured during registration with Nets)​

The header should have this format: Authorization: Basic <base64-encoded cus​tomer-identifier:client-secret>.

var values = new Dictionary<string, string>
	{ "grant_type", "authorization_code" },
	{ "client_id", client_id},
	{ "client_secret", client_secret },
	{ "code" , <<URL encoded Authorization Code>> },
	{ "redirect_uri", <<redirect_uri earlier passed in Authentication request>>}

var postData = new FormUrlEncodedContent(values);
var response = new HttpClient().PostAsync(tokenEndpoint, postData).Result;

var itToken = response.Content.ReadAsStringAsync().Result;
ClientSecretBasic clientSecretBasic = new ClientSecretBasic(new ClientID(customerIdentifier), new Secret(clientSecret));
TokenRequest tokenReq = new TokenRequest(new URI(tokenEndPoint), clientSecretBasic, new AuthorizationCodeGrant(authCode, new URI(redirectUri)));

HTTPResponse tokenHTTPResp = tokenReq.toHTTPRequest().send();
if(400 == tokenHTTPResp.getStatusCode()) {
   throw new Exception("Invalid response from token URL [statuscode=400].");

// Get JSON object from Token response
JSONObject tokenJsonObject = tokenHTTPResp.getContentAsJSONObject();
String idtoken = JSONObjectUtils.getString(tokenJsonObject, "id_token");
curl -kiSs \ \
-H Authorization: Basic <<Base64Enocoded username:password>> \
-d grant_type=authorization_code \
-d redirect_uri=<<redirect_uri earlier passed in Authentication request>> \
-d code=<<URL encoded Authorization Code>>

​​ID token validation

The ID Token returned is signed, and it can optionally be encrypted. ID Token encryption is determined during customer configuration. Note: The use of encrypted ID Token is required for Finnish Trust Network customers offering identification with Finnish Bank IDs and Mobiilivarmenne.

The encrypted ID Token should be decrypted using the private key only if customers requested Nets to encrypt the ID Token after signing. Below is a code example for encrypted ID Token. Read for more information about ID Token encryption.

// Decrypt the recieved ID Token using the private key, if the token was encrypted
JWT jwt = JWTParser.parse(idtoken);
SignedJWT signedJWT = null;
if (jwt instanceof EncryptedJWT) {
	PrivateKey privateKey = getPrivateKey("token-enc", mid);
	JWEObject jweData = JWEObject.parse(encryptedRequest);
	jweData.decrypt(new RSADecrypter(privateKey));
	signedJWT = jweData.getPayload().toSignedJWT();
} else {
	signedJWT = SignedJWT.parse(idtoken);


The signed ID Token should be validated using a public key that is returned from an HTTP GET request to the JWKS URL. This returns a JSON document where the public key is the first element in a JSON array named keys.​

curl -X POST '' 
-H 'Content-Type: application/x-www-form-urlencoded' 
-H 'Authorization: Basic <<Base64Enocoded username:password>>' 
-d 'code=<<URL encoded Authorization Code>>&redirect_uri=<<redirect_uri earlier passed in Authentication request>>'

// Get JSON response from jwks_uri
HTTPResponse jwksResp = getHTTPRequest(jwks_uri, truststorepath, truststorepwd).send();
JSONObject jwksJsonObject = jwksResp.getContentAsJSONObject();
JSONArray keys = JSONObjectUtils.getJSONArray(jwksJsonObject, "keys");
JSONObject jsonKey = (JSONObject) keys.get(0);

PublicKey publicKey = buildPublicKey(jsonKey);
if (null != publicKey) {
	// Verify Signature
	JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) publicKey);
	if (!signedJWT.verify(verifier)) {
		throw new JOSEException("Signature mismatch");
	// Verified successfully

ID token claims

​​See the implementation of ClaimsService.buildPublicKey in the demo app source code​​. Finally, retrieve the claims from the ID Token.​​

JWTClaimsSet jwtClaimsSet = signedJWT.getJWTClaimsSet();
String subjectDN = jwtClaimsSet.getStringClaim("dn");
String birthdate = jwtClaimsSet.getStringClaim("birthdate");

​​​The ID Token is generated and made available to the customer by E-Ident service. The end user identity and associated claims are also stored in E-Ident service. The identification request is configured by way of parameters that specify how the identification session will be set up.

The E-Ident demo app displays the retrieved claims after successful identification.

E-Ident demo app - step 2.PNG

Together with the claims, the demo app also displays the full response from the ID Token URL in JSON format.