Most of the time, when we have to deal with authentication, we have a real person on the other side, our end user.
But there is another group of application interactions where the other party is another process. Another process who wants to use the data we have available and which they need.
So how can we make sure that we can trust a request we receive and that we can send the data?
With JWT (JSON Web Tokens) which are signed with an RSA key, we have a simple way of authenticating the process.
JWT, maybe you heard already about it, if not, this is also a quick introduction together with the explanation how you can use it to authenticate a process.
The JSON Web Token seems a long string of characters, but they have 3 parts each separated by a . (dot) like xxxxx.yyyyy.zzzzz
Each part is base64URL encoded so that we can safely transfer it over an HTTP connection.
The first part, the xxx's, are the header and contain general information like the type of token (there exists a bunch of related concepts) and the used hashing algorithm.
The JSON representation of the header (before it is base64URL encoded) could look like this:
the 'kid' property will become clear when we talk about the signing of the token.
PayLoad or claims
The second part, the yyy's in the above example, is the payload or the claims. There are a few properties that you can use in this section and you can also use your own keys to transfer data.
The JSON for the application I made looked something like this
The 'sub' property defines the subject, 'aud' (audience) is informative and indicates the application the token can be used for. And the 'iat' (issued at) and 'exp' (expiration) are a few time stamps that can be used to limit the reuse of the token.
And thus, limit the chance a token is captured and reused by a malicious third party. (replay / playback attacks)
The first 2 parts are just encoded values and thus readable by anyone who can see the token. That is the reason why we have the last part, the zzz's in our example.
When the other process uses the private part of an RSA key to sign the header and payload, you get the 3th part if the JWT which completes it.
The signing makes sure that
- The payload can't be changed between the sender and receiver because the verification of the signature will then fail.
- We can trust the other party because the JAX-RS endpoint can verify the signature with the public part of the RSA key used to sign it.
The 'kid' property in the header is an additional check to determine which RSA key is used for the signing.
So let us review step by step what you can do, as the developer of the JAX-RS endpoint and client to setup a secure way of authenticating.
- As JAX-RS endpoint creator, I create an RSA key.
- The JAX-RS endpoint creator chooses an identifier to refer to this key (I call this the api key) because we possibly need to support multiple processes which read information.
- The JAX-RS endpoint creator gives this key to the other party which will create the client. The public part of the RSA key will be used by the JAX-RS endpoint creator.
- The JAX-RS client creator generates a JWT (according to the specifications of the creator regarding the claims) and signs it with the private part of the RSA key.
- The api key and JWT are send to the JAX-RS endpoint in the header
x-api-key : cbeba027-39e1-4c70-a584-77081422e16a
Authorization : Bearer ey......
- The JAX-RS endpoint can use the x-api-key header value to lookup the corresponding RSA key and check the signing if the JWT.
- If the check passes, the JAX-RS endpoint knows who sent the request and can verify the claims part to see if the other requirements are met (for example the timestamps to reduce the replay / playback attacks.
By using a JWT, we can easily determine which process made the request to the JAX-RS endpoint and allow the information exchange between processes. There are various frameworks available for all kind of programming language so that we can even use it across language / technology transfer of the data.