X.509 certificate-based authentication

The X.509 standard (https://en.wikipedia.org/wiki/X.509) is used to secure the Web. Every website using SSL out there (serving pages on HTTPS), have an X.509 certificate on their web server and use it to encrypt and decrypt data on-the-fly.

These certificates are issued by a Certificate Authority (CA), and when your browser opens a page that presents a certificate, it has to be published from one of the CAs supported by the browser.

The reason why CA exists is to limit the risk of compromised certificates by having a limited number of trusted entities that generates and manages them, independently from the companies that use them.

Since anyone can create a self-signed certificate in a shell, it would be quite easy to end up in a world where you don't know if you can trust a certificate. If the certificate is issued by one of the CAs trusted by the browser, like Let's Encrypt (https://letsencrypt.org/), it should be legitimate.

However, if your microservices are exposed to other third parties, or vice versa, it's better to rely on a trusted CA. Let's Encrypt is free and is a pretty good one. This project aims at securing the Web, but by using extend you can also use it to secure your microservices as long as you own a domain name.

For now, let's create our self-signed certificate and see how it can be used to sign JWT tokens.

In a shell, you can use the openssl command to create a certificate and extract a public and private key pair out of a certificate.

If you are under the latest macOS operating system, you might need to install openssl from brew since it was removed from macOS.
$ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 
Generating a 4096 bit RSA private key 
..........................++ 
..........................++ 
writing new private key to 'key.pem' 
Enter PEM pass phrase: 
Verifying - Enter PEM pass phrase: 
----- 
You are about to be asked to enter information that will be incorporated 
into your certificate request. 
What you are about to enter is what is called a Distinguished Name or a DN. 
There are quite a few fields, but you can leave some blank 
 
 For some fields, there will be a default value, 
 
 If you enter '.', the field will be left blank. 
----- 
Country Name (2 letter code) [AU]:FR 
State or Province Name (full name) [Some-State]: 
Locality Name (eg, city) []: 
Organization Name (e.g., company) [Internet Widgits Pty Ltd]:Runnerly 
 
 Organizational Unit Name (eg, section) []: 
Common Name (e.g. server FQDN or YOUR name) []:Tarek 
Email Address []:[email protected] 
 
$ openssl x509 -pubkey -noout -in cert.pem > pubkey.pem 
$ openssl rsa -in key.pem -out privkey.pem 
Enter pass phrase for key.pem: 
writing RSA key 

These three calls generate four files:

  • The cert.pem file has the certificate
  • The pubkey.pem file has the public key extracted from the certificate
  • The key.pem file has the RSA private key, encrypted
  • The privkey.pem file has the RSA private key, in clear
RSA stands for Rivest, Shamir, and Adleman, the three authors. The RSA encryption algorithm generates crypto keys that can go up to 4,096 bytes and are considered secure.

From there, we can use pubkey.pem and privkey.pem in our PyJWT script to sign and verify the signature of the token, using RSASSA-PKCS1-v1_5 signature algorithm and the SHA-512 hash algorithm:

    import jwt 
 
    with open('pubkey.pem') as f: 
        PUBKEY = f.read() 
 
    with open('privkey.pem') as f: 
        PRIVKEY = f.read() 
 
    def create_token(**data): 
        return jwt.encode(data, PRIVKEY, algorithm='RS512') 
 
    def read_token(token): 
        return jwt.decode(token, PUBKEY) 
 
    token = create_token(some='data', inthe='token') 
    print(token) 
 
    read = read_token(token) 
    print(read) 

The result is similar to the previous run, except that we get a much bigger token:

b'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJzb21lIjoiZGF0YSIsImludGhlIjoidG9rZW4ifQ.VHKP2yO1dCUrS5YAOCZsGXF_mesMJNNYcnBHe4mFiPpBDCbMhrI8h10vr1BaCiN8rVEMcUXQ4Gc7183w6ga3spyEzONg3-Sv-eId4rPbTqbbmPErrnWPRIH9hQMHsMebVOlI9lOvNmV-J3DIEmV4riqRluJMIFYuy_A7fB2r8IqeHBfrsEPWmvw2_tIZ3V3dJGU4ZBkn8zdzgfbou_LHc28_dyC32kR2Ec1nsRV3zRffEjx60cjzmNNFqB9kYZHun0IIzBqdh0IiRxPF4rgYG3oBKJXP3u2uyfBifNy3Bz4bMPJ8iRRmQleciyFdzDkm7J4SAyz5I0TKHSPOZA-9x6dgacQ9w_JAtmElH7u8_ES_2TxmvbBLqsXIzghAhG10CL79UeSKeXMTjc8DOQrIbWmaRCIbPy9AdlIJQxqul4UnCoUhUQ6PZwD6CEuaZTjKdPvql7n_-u1Tjrw7e339WC9QZS5DFCzMe2F0TY-kI52-AaNEoRaO8oSCwW3E7u-NcSt-bD019MdX3bxN0FdNvL62BUDqqxind7TFF7YFX3zTxTu15Pex2F64YvnhG1CDk337htROt8B9vH8CIUWo_2ujkair8zCdd9sfIdssOGFDnawIX2NPGd4vZ1dpw0DwHBaXw0gP8zzcRAsuZ7rfNMZeJTH6gB-kMc5UKf26nAc' 
{'some': 'data', 'inthe': 'token'} 

Notice that adding over 700 bytes of data to each request can add up over time, so the secret-based JWT token technique is an option to keep in mind if you need to reduce the network overhead.

Now that we've learned how to deal with JWT tokens, let start to implement our authentication microservice; we'll call it the TokenDealer.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset