Private vs Public Keys

There are 2 types of token we can return. Reference and Self-Contained tokens.

We don't use reference tokens at ITC, but just for your understanding, reference tokens are a way to reference a record in the database. Think of them as kind of like primary keys on a table, but as unique strings. With reference tokens, whenever we want to validate they're still valid, or retrieve information about the user who's authenticated, we need to make a request to the authentication service and ask for information relating to the reference token.

This can cause systems to slow done since if every request needs to know information about the user, each request has to make an additional call to look up that user.

We get around this by using Self-Contained tokens, most developers at ITC will have heard the term JWT thrown around. This is a type of Self-Contained token.

A Self-Contained token contains information about the token embedded within the token itself. It's not a reference that we can use to get information from somewhere else. JWT tokens are split into 3 different parts. The Header, the Payload and the Signature.

The downside to Self-Contained tokens, is that because they're easy to create, and because they contain information about the token within it, there's no need to make another call to verify it on each request, which opens it to abuse.

Let's say we're an attacker. We know the structure of the data stored inside the token, so we can just create a new token ourselves with whatever user ID we want to authenticate as. The attacked can then pass that token to one of our services to authenticate.

To get around this, we have the concept of Signing tokens.

This is a process where we generate the data we want to put in the token, and then put a signature on it programmatically to say "this is the data we've approved, nothing in it should change". If an attacker tries to change anything in the token, that will produce a different signature and therefore invalidate the token.

Generating public and private keys

php artisan oauth:keys --force

Private Keys

As mentioned above, if an attacker changes the data stored in the token, the signature changes and so the token becomes invalid.

So what if the attacker just generates a new signature? This is where private keys come in.

A private key is kind of like a password. It's a secure string that only the people or company that created it know. Attackers will not have access to this private key.

When we sign a token in compliance-auth, we'll sign it using our private key. If an attacker tries to create a new signature, they'll need to know the private key to sign the token properly. Private keys never leave the compliance-auth service, and are kept secret from everyone, including developers.


Public Keys

Public keys on the other hand are similar to private keys, except they're designed to be publicly readable. The aim of a public key is to make sure that the signature on the token was signed by the correct private key.

Lets say the attacker creates a new JWT access token. They create a brand new signature using their own private key. Because they've used their own private key, the signature now matches the payload so it's a valid token. We can use a public token for services attempting to verify the token to check that it was signed by our private key and not an attackers.

Public keys are readable through a URL. Anyone can read or copy this private key. They're never used to sign a token, only to validate that the private key used for signing is correct. If we ever need to create a new private key, it'll also create a new public key that matches it.

Request

GET
/oauth/discovery/public
use Compliance\Sdk\Authentication\OAuth\Contracts\OAuthSdkInterface;
use Compliance\Sdk\Authentication\Types\Machine;

private OAuthSdkInterface $sdk;

$response = $this->sdk->v1(new Machine())->getPublicKey();

Response

-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArB3CPofUMO+DYATB4TNa
LokduFDdb6tOo6PTOP6vXvjZ4AyZMWmKSm8QgOKn19wu0ZtDI2CKSKhg52Q4fxRc
kTxk/84AY4K42PGC23ngaMJQD/sBckk25HsP9FeNw7QsbSit1bDm1KzS1rTolYIs
nph84j0EhiLFqAuuEAahPDEwHOjH1j1WYWtPFQCSwQEVlvKah/ct+IvTaZ/I7Eo4
VpY5L+wDj2Pvnxv4hRWIYuwFHp3KK1SfqzHM36JKNwIieVIbiJDXXw+4/mrKLBvu
i5fw3D4qIBI81iGOXWxMeNGf6qwXedZquYWkNLPyAMCGWpR9UeLVmFDUr+gNCr2t
3z8l3zQ/a5GfkNIsNYoM0Yrw93hFvQYobXuT6qcs4EBHi3zhx86dCgiZ9Kf7m+z3
N1PhgfrJZepTpUnvl2LzbS3TBTXmmlTQIS/9tzvJ7CdNX4K6YpkIUsuiCQ5PdbEr
AqrSm7vNKTOfL3hDSZnik883wb3pFkuNHF8hhBlaVe81LCEsm08NEi8OF6rh8+CC
bKbG9mW08C+5Br5sqVyDZryzHc2kDIWmcVus/F6ozj8TbTiU1tPlq7pk1InxdrX4
OBgH/EdNzJGNvCRtaLSCqAQkWIMQ9j8FzZRbWD38q1swuMzlBl8PZi+cUcNvr7YB
jhn/mSubGKURnfsSxmkCOZUCAwEAAQ==
-----END PUBLIC KEY-----