Two factors too many
In a perfect world, we would not need any authentication. In a real world, we often feel protected enough by our
Password1 universal password. Maintaining sufficient security is often a major pain for
internet organizations, as security and usability are almost always in either or relationship.
Unfortunately, oftentimes, the single authentication factor is not enough. As it happens almost on a daily basis, hackers might steal your social account password and post spam under your account. Worse yet, somebody might gain access to your health record and make it public or steal your credit card information from your bank. Thus, most governments often require software businesses to be compliant with multi-factor authentication schemes when it comes to securing sensitive information, such as electronic health records.
Two factor authentication systems can be composed of something a user knows and something a user has. Also, third authentication factor can be something a user is, but, unfortunately, biometrics are beyond the scope of this post. For simplicity reasons, we will use client certificate as something a user has, and username and password as something a user knows.
In this example, let’s assume we have an authentication server that provides access to web resources.
First Authentication Factor - SSL client certificate
One way to issue a client certificate from our certificate authority is by using the OpenSSL library and the steps below:
1. Generate RSA private key testclient.pem with 2048-bit encryption strength
2. For self-signed certificate, issue certificate signing request testclient.csr with your details
3. Issue client certificate testclient.crt against our certificate authority ariCA.crt with 360 days expiry
Now, we can give testclient.crt to a user which they will use as the first authentication factor. Every time the user tries to access a web resource on our server, our authentication server should request this client certificate, check it against our certificate authority, and either grant or deny access.
Second authentication factor - username and password
Once a user passes the first authentication step, the server should then validate their username and password. Arguably, the simplest way for a user software to pass username and password to our web service would be using HTTP protocol basic authentication scheme, which uses base-64 encrypted username and password. For instance, user HTTP request header to our authentication server could look like this:
QkMwMDAwMEMzNTpTZXZDbGllbnRUZXN0 would be the output of a client-side function such as
string base64encrypt(username + ":" + password).
Upon successful validation of username and password, our authentication server could issue a token which expires after a certain time, with which a client finally could access various resources. Using the token we issued, the authenticated user resource request headers could look like this:
SN3528Ev0r~lkMTq2jY7 is a token issued by our server of type Bearer. For more information on Bearer Tokens and Oauth 2.0 authentication, please check
The OAuth 2.0 Authorization Framework and The OAuth 2.0 Authorization Framework: Bearer Token Usage.
Both authentication factors working together
The system diagram demonstrates issuing tokens by a two factor authentication system, where usernames, passwords, and access tokens are stored in MySQL database. The authentication protocol flow is described below:
- Web resource client initiates SSL handshake and provides their SSL certificate to the server.
- Authentication server verifies client certificate against root certificate authority stored on the server.
- Client sends an HTTP(POST) request to authentication server with HTTP basic authorization header (base64-encoded username:password).
- Authentication server returns a bearer access token or HTTP error (ie. 401 Unauthorized).
- Clients sends an HTTP(POST) request to resource server containing bearer token in authorization header.
- Resource server verifies an access token and responds with a requested resource.