Articles
Articles on web development
How I work!
Object oriented data modeling - Part 4
Security and final thoughts
Securing the API
Another area I have to think about is securing the API. I only want authorized people to access and use the routes. If I don’t protect them, anyone can come and post data to the database. In a production environment I don’t want that to happen. There are several ways to secure the API.API-keys
An API-key is used to identify and authenticate an application or user. The API-key can be of variable length containing a random choice of letter, numbers and symbols. It can also use uppercase and lowercase letters to make it even more random. The point here is I have to choose a key that is long enough and random enough to be difficult to guess. Then again I don’t want an API-key that’s too long. The longer the API-key is the longer it takes to evaluate it when the routes are used. But the longer the API-key is, the more secure it is. So It all comes down to how secure I need my data to be and how long I can wait to evaluate the key. Below is an example of an API-key and different ways to hash the key.7 8 API key generator 1 unique and random API key type mixed-numbers and length 128-bit with Base64, MD5 hash, Sha256 and Sha512 representations#1 API Key
BtlNwmfWyOL8oGfOwEypdkBoqVKnMk82yDR4sffnWltmj4O47MNYczGIIPlwxCqociP7Vcd1qVCMlNLrKTeE9UdfYU5PYy6Y0WHx4iE2uDoy82FUFiBYMYa0GwmvU2oN
Base 64
base64:QnRsTndtZld5T0w4b0dmT3dFeXBka0JvcVZLbk1rODJ5RFI0c2ZmbldsdG1qNE80N01OWWN6R0lJUGx3eENxb2NpUDdWY2QxcVZDTWxOTHJLVGVFOVVkZllVNVBZeTZZMFdIeDRpRTJ1RG95ODJGVUZpQllNWWEwR3dtdlUyb04=
MD5 Hash
64dd571c959ffffcdc6521c8487e61ab
Sha256
4c3443bf9cbcb8126dc445dd4b1d5e9cb0d032e1aca673247c3aadce5e070a85
Sha512
33a1bf60a3c79aba9e524f234879e04c47e3d58e1fdc28681a05f252e84886c59a43f28c7cba711f3e448eb2c686cc63323b3a291affb77880d954a27dece62e
Storing the key in plain text is not a good idea.9 If someone gets access to the keys they could get access to the data through the API routes without being authorized.
MD5 hash is no longer in use. It’s too easy to reverse engineer. The most common hashing algorithm for hashing keys is the SHA256 algorithm.
There are other algorithms like AES256. It is widely utilized for safeguarding sensitive information during storage and transmission while SHA256 is primarily employed for data integrity checks and digital signatures. 10 JWT - Json web tokens
Another way to secure my API is through the use of JSON Web Tokens. JWT for short. JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.11 A JWT looks somewhat like this: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImRvbkBwYXJrZW4uZGsiLCJleHAiOjE3MzY0NDU0MTcsInVzZXJJZCI6MH0.NkZg6vxLVcIqkyEVfoK6Lyf87MI0FrEgWHMKzQueG8I The token isn’t just random numbers and letters like the API-key. It is an Encoded version of the payload used to log in to the routes. It also contains the header where the algorithm and the token type are displayed. The encoded token consists of 3 pieces. Each piece is separated by a dot (.)The JWT Header
The first part is the header: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 The decoded data contains the algorithm and token type and looks like this:{
"alg": "HS256",
"typ": "JWT"
}
The JWT Payload
The next part of the token is the payload: eyJlbWFpbCI6ImRvbkBwYXJrZW4uZGsiLCJleHAiOjE3MzY0NDU0MTcsInVzZXJJZCI6MH0 The payload contains the data I provided when I logged in to the system. Logging in is where the JWT is created and added to the header of the response returned by the API. The above token has a payload that if decoded looks like this:{
"email": "johnDoe@onlyjohns.com",
"exp": 1736445417,
"userId": 0
}
The payload can contain whatever I want to receive as the authorization data. The data are called Claims and are classified into three categories; Registered Claims, Public Claims and Private Claims Registered Claims.
These are a set of predefined claims which are not mandatory but recommended, to provide a set of useful, interoperable claims. The names are three characters long as JWT’s are meant to be compact. These claims can be "exp" (Expiration Time), "iss" (Issuer), "iat" (Issued At). There is a full list of registered claims in the RFC7519 section-4.112 In the above example the "exp" claim is used. It’s A JSON numeric value representing the number of seconds from 1970-01-01T00:00:00Z like "exp": 1736445417,Public Claims
These can be defined at will by those using JWTs. But to avoid collisions they should be defined in the IANA JSON Web Token Registry13 or be defined as a URI that contains a collision resistant namespace.Private Claims
These are the custom claims created to share information between parties that agree on using them and are neither registered or public claims.The JWT signature
The last part of the token looks like this: NkZg6vxLVcIqkyEVfoK6Lyf87MI0FrEgWHMKzQueG8I This is the signature. The signature is made of the header, payload and the secret used to encode the token when it was created. Both header and payload are base64 encoded. HMACSHA256 is the algorithm used to create the signature. Here it is HMAC SHA256. The signature is created like this:HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
Your secret here
)
The signature is used to verify the message wasn't changed along the way, and, in the case of tokens signed with a private key, it can also verify that the sender of the JWT is who it says it is.
Do note that with signed tokens, all the information contained within the token is exposed to users or other parties, even though they are unable to change it. This means I should not put secret information within the token.Securing the API with a Json Web Token.
After programming the functions creating and verifying the token it's time to add it to the API routes. Here I need to decide what part of the API needs protection. First I have to create a route where I can create a login. A login is where the JWT is created. That route can of course not be protected. If it were, I couldn't create the user that is logging in. The same goes for the route where I will login and create the token. After that I have to decide what part of the other routes should be protected. I could argue that the GET requests should be public. Here I have to know if the data displayed is of such a character that it should NOT be public or if it’s ok that all people can read it. I would almost always protect the POST, PUT and DELETE routes. Whenever I’m able to add or modify data I only want authorized people to add or modify the database records. In a public API I will of course always have access to the route creating a user/login. Here I could use an API-key to make sure only selected people can create a login. The added routes look like this:.POST http://localhost:8080/create_user/
{
"username": "johnDoe@onlyjohns.com",
"password": "6CA13D52CA70C883E..." // sha256 hashed password = 123abc
}
//-------------------------------------------------------------------
POST http://localhost:8080/log_in/
{
"username": "johnDoe@onlyjohns.com",
"password": "123abc"
}
How JWT works
When a protected route is executed the user agent should send back a JWT. That is typically done by sending it through the Authorization header using the Bearer schema. The content of the header would look like this: Authorization: Bearer <token> The server would then validate the token and if it passes the resource will be available. Note, because the JWT is signed, all the information embedded in the token is visible. So I shouldn’t add private or sensitive information in the JWT payload. To make the JWT more secure I would set an expiration date in exp claim like "exp": 1736445417,. That means after a given time the token will expire and validate as not valid. There are different ways to set the Authorization header for different programming languages. This article is not a programming tutorial so I won’t go into details for a specific programming language here. At jwt.io14 There is a list of libraries used for JWT’s token signing and verification in a given programming language. There I can choose the library I want to use and then find the documentation for the package by googling the package name and programming language. Often I also get links to tutorials and other information I can use to learn how to use the package and more.Final thoughts
In this 4 part series I have laid out my approach for how to take on a software development project. This is no way a complete description of all the steps to take to make a solid API. I haven’t talked about testing the api or how to update it after the API has been in use. I also don’t write anything about deployment or how to connect the API to the front-end. I might write more in depth articles on some of those subjects at another time so keep an eye out for updates on flexworksoftware.com and connect with me on Linked InFoot notes
7 .
8.
What makes a good API key system: https://tedspence.com/what-makes-a-good-api-key-system-c7211de5ad33 ⤻
9.
10.
A Deep Dive into SHA-256: https://medium.com/@madan_nv/a-deep-dive-into-sha-256-working-principles-and-applications-a38cccc390d4 ⤻
11.
12.
13.
14 .