api/v2

REST API v2

Contents

Overview

The API v2 provides updates for some of the elDoc REST API endpoints and more strict JWT security requirements.

JWT requirements

JWT header must contain the following attributes:

  • alg - Must be present, supported algorithms: HS256, HS384, HS512

JWT payload must contain the following claims:

  • sub - Must be present, system ID of the respective API account
  • iat - Must be present
  • nbf - Must be present, allowed time difference with the server time can not be more than 30 sec
  • exp - Must be present, allowed maximum validity period 5 min
  • aud - Must be present, to be provided in format "METHOD:URL" where:
    • METHOD is method type of the request (in uppercase), e.g.: POST, GET, etc.
    • URL is a path part without get-parameters of the request target url. For the request sent to the URL "https://eldoc.domain.com/api/v2/docForm/ABC123?fields=_id,_id_web" the value must be set to: "/api/v2/docForm/ABC123"

JWT has to be signed with the security token of the the respective API Account.

According to the JWT spec all dates are to be stated in UTC time zone in Unix epoch time format (the number of seconds that have elapsed since January 1, 1970).


elDoc API JWT generation implementation samples:


Java implementation
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.lang.JoseException;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.keys.HmacKey;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class JWT {

    /**
     * Signs payload with key
     */
    public String getSignedJwt(String subject, char[] key, String method, String url) throws JoseException {
        JsonWebSignature jws = new JsonWebSignature();

        JwtClaims claims = new JwtClaims();
        claims.setIssuer("elDocRestApiClient");
        claims.setAudience(method + ':' + url);
        claims.setNotBeforeMinutesInThePast(1); // to cover clock skew between servers
        claims.setIssuedAtToNow();
        claims.setExpirationTimeMinutesInTheFuture(3);
        claims.setGeneratedJwtId();
        claims.setSubject(subject);

        jws.setPayload(claims.toJson());
        jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256);
        jws.setHeader("typ", "JWT");
        jws.setKey(new HmacKey(charsToBytes(key)));
        return jws.getCompactSerialization();
    }


    /**
     * Converts chars to bytes
     */
    private static byte[] charsToBytes(char[] chars) {
        final ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(CharBuffer.wrap(chars));
        return Arrays.copyOf(byteBuffer.array(), byteBuffer.limit());
    }
}


C# imlementation
using System;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Newtonsoft.Json.Linq;

namespace DMSSolutions
{
    public enum HMAC_ALGS
    {
        SHA256,
        SHA384,
        SHA512
    }

    public class elDocApiUtils
    {

        /**
         * Signs payload with key
         */
        public static string GetSignedJWT(string subject, string subjectKey, string method, string url, HMAC_ALGS alg)
        {
            byte[] key = Encoding.UTF8.GetBytes(subjectKey);
            SymmetricSecurityKey securityKey = new SymmetricSecurityKey(key);

            SecurityTokenDescriptor descriptor = new SecurityTokenDescriptor();
            descriptor.Issuer = "elDocRestApiClient";
            descriptor.Subject = new ClaimsIdentity(new[] { new Claim("sub", subject) });
            descriptor.NotBefore = DateTime.UtcNow.AddMinutes(-1); // to cover clock skew between servers
            descriptor.Expires = DateTime.UtcNow.AddMinutes(3);
            descriptor.Audience = method + ":" + url;

            string algorythm = SecurityAlgorithms.HmacSha256Signature;

            switch (alg)
            {
                case HMAC_ALGS.SHA384:
                    algorythm = SecurityAlgorithms.HmacSha384Signature;
                    break;

                case HMAC_ALGS.SHA512:
                    algorythm = SecurityAlgorithms.HmacSha512Signature;
                    break;

                default:
                case HMAC_ALGS.SHA256:
                    algorythm = SecurityAlgorithms.HmacSha256Signature;
                    break;
            }

            descriptor.SigningCredentials = new SigningCredentials(securityKey, algorythm);

            JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
            JwtSecurityToken token = handler.CreateJwtSecurityToken(descriptor);
            return handler.WriteToken(token);
        }
    }
}

Last modified: April 27, 2023