When working with an SPA (Single Page Application) all the view components and templates are already in the client and the authentication is used only for API calls. Because you don’t need (but you can if you want) to authenticate the user until the first interaction against an API is made, or you can even authenticate each API call for a more robust and secure communication between the server and the SPA. Let see what are our options:
- Saving authentication information in the session data on the server side
- Authenticating each API call using the password to create a digital signature of the request
- Authenticate the user and return an authentication token to identify a session (combining both)
Saving authentication information in the session data on the server side
This is similar to the first approach of authentication used by web applications in past
When a browser makes a call to the server, the server returns a Session Id (usualy saved in cockies) to be re sent to the server in every call from that browser, then the server saves data associated to that session id for example a boolean variable containing if the user is authenticated or not. Then the browser sends the username and password and if the user is authenticated that variable is changed to true.
let see a diagram
this scheme is also supported by SPAs because every API call is made inside a browser window. So you can create an API let say
where you receive the username and password and process it, save the result in session data and send a response to the client.Then all the subsequent API calls to that server will be already authenticated in the session data.
This is the simplest scheme of authentication but also it’s the less robust and secure.
- Easy to develop
- Simple to understand
- Fastest to deploy
- It doesn’t scale to clustered servers, because each server stores the session data (most servers have methods to overcome this)
- if the session id is sniffed an attacker could impersonate the authenticated user
- the username and password are sent over the wire (hashing the password won’t solve this because we are still sending the hashed version)
Authenticating each API call using the password to create a digital signature of the request
A newer authentication scheme could be used to overcome this faults. Based on the public and private key idea, we can think of them as “public key” = “Username” and “private key” = “password”. We can improve this process using hashed versions of them (“publicKey” = SHA1(“username”), “privateKey”=SHA1(password)) but we wont consider that for learning process.
In this case there is no need for an initial authentication request (/api/login) because each API call will be authenticated.
Here is the process:
First both ends (SPA and server) should know the public key and the private key.
Then, before making the request to the API (let say /api/doSomething/ ), the SPA takes the entire list of parameter values and adds the public key, then signs them using the SHA1 HMAC algorithm and the private key, this creates a digital signature that is also included in the request as a parameter and finally makes the request
On the other end, the server receives the request and all the parameters including the signature and the public key, retrieves the private key for that public key and recreates the signing process using SHA1 HMAC, then compares the signatures and if they are equal then the request is authenticated
But, as we usually need to present a login form to the user, it might be a good idea to have a login api (/api/login/) to know immediately if the user entered a correct username and password. to avoid sending always the same signature with the public key, you can add an extra parameter with random values.
- the password/private key is never sent over the wire
- scales better against clustered servers
- a timestamp could be added to the parameters list to avoid reusing a signature
- requires authentication process on every API call
- SHA1 HMAC depends on the same character coding on both sides
Authenticate the user and return an authentication token to identify a session (combining both)
Beyond the public and private key authentication scheme, we can introduce improvements to enhance the robustness and security. For example we can create a token of authentication to avoid signing the parameters always with the same private key, and instead of that usign the authentication token and the private key to sign the parameters with SHA1 HMAC this method prevents the inference of the private key from a set of API calls with parameters and signatures