Link Search Menu Expand Document

How to create a Json Web Token with ORGiD ?

The authentication in the Winding Tree protocol relies on the JSON Web Token (JWT) IETF RFC 7519, which is in use in many commercial applications. In the Winding Tree protocol, the access token is self-generated by the requesting party.

Create a Public/Private key pair

For security reasons, it is important to not leave on a server the Ethereum private key that is controlling your ORGiD. When connecting to APIs, you need to create a separate authentication key pairs for your server that will be allowed to act on behalf of your organization. A good security practise is to rotate the server key pair periodically.

In the Winding Tree ecosystem, the keys in used are asymetric keys using the scep256k1 elliptic curve.

using OpenSSL

openssl ecparam -name secp256k1 -genkey -noout -out secp256k1.pem
openssl ec -in secp256k1.pem -pubout -out secp256k1.pub

Using Python

import ecdsa
# Generate a key pair
signing_key = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1)
verifying_key = signing_key.verifying_key

# Get the content of the PEM key
print(signing_key.to_pem().decode("ascii"))
print(verifying_key.to_pem().decode("ascii"))

Register your Public Key in your organization

You can register the created public key with your organization.

The easiest way is to create it from the Winding Tree Marketplace.

Create a JWT Token

Using NodeJS

const { JWK, JWT } = require('jose');

const privPem = `-----BEGIN EC PARAMETERS-----
<EC Parameters here>
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
<EC Private Key goes here>
-----END EC PRIVATE KEY-----`;

const genOptions = (privKey, origin, recipient, fragment = 'webserver', time = '1 year', scope = undefined) => ({
    priv: privKey,
    alg: 'ES256K',
    aud: `did:orgid:${recipient}`,
    iss: `did:orgid:${origin}`,
    fragment: fragment,
    exp: time,
    scope: scope,
});

const createToken = (options) => {
  const priv = JWK.asKey(
    options.priv,
    {
        alg: options.alg,
        use: 'sig'
    }
  );

  return JWT.sign(
    {
      ...(options.scope ? { scope: options.scope } : {})
    },
    priv,
    {
      audience: options.aud,
      ...(options.iss ? { issuer: `${options.iss}${options.fragment ? '#' + options.fragment : ''}` } : {}),
      expiresIn: options.exp,
      kid: false,
      header: { typ: 'JWT' }
    }
  );
};

const options = genOptions(
    privKey,
    '0x..<your orgid>..',
    '0x..<recipient orgid>..',
    'webserver',
);
const jwtToken = createToken(options);

console.log(jwtToken);

Using Python

import jwt
from jwt.contrib.algorithms.py_ecdsa import ECAlgorithm
from datetime import datetime

# Define the Addresses of the ORG.IDs
recipients = {'my_recipient': '0x...'}

# Define some variables
tokens = {}
private_key = signing_key.to_pem().decode("ascii")
now = int(datetime.utcnow().timestamp())

# Register the ES256K algorithm as it is not recognized by default
try:
    jwt.unregister_algorithm('ES256K')
except:
    pass
jwt.register_algorithm('ES256K', ECAlgorithm(ECAlgorithm.SHA256))


# Walk through the list of recipients
for name in recipients:

    # Create a token
    tokens[name] = jwt.encode(
        {
            'iss': 'did:orgid:%s#webserver' % orgid,   # The reference of the Public Key
            'aud': 'did:orgid:%s' % recipients[name],  # The recipient of your token
            'iat': now,                                # The date of token issuance
            'exp': now + 60*60*24                      # Set the token to expire in 24h
        },
        private_key,
        algorithm='ES256K').decode("ascii")

    print("JWT for %s: %s\n" % (name, tokens[name]))