Building the API - user interaction
We're building software for people, and we need to give them a way to communicate with it. This lesson will show you how to prepare an API for user interaction like loging in and adding products to list of favorites. Moreover you will be introduced to the security essentials like cookies encryption and password hashing.
You are about to implement three more endpoints:
POST /login will accept body in the form of
{email: user_email, password: user_password}
, look for a user in the database, and respond with one of the following:Status code
200
along with a cookie containinguserID
if the user is found.Status code
401
if the user is not found.
GET /isLoggedIn will respond with one of the following:
Status code
200
if a cookie containinguserID
is present in the request, and the user with the givenuserID
exists in the database.Status code
401
if the cookie is not set or the user is not found.
POST /favorites/:id will add a product to the list of a user's favorites. The product will be defined by the
:id
query parameter, and the user will be retrieved byuserID
from the cookie. Action success will be confirmed by status code202
. If the cookie is not present, this endpoint will respond with status code401
.
You will keep userID
in a cookie file, which could be easily compromised. An attacker could steal this data, use it to impersonate someone else, and act in the system as that person, which is as easy as changing the cookie file content. To protect your users against this kind of attacks, always encrypt cookies containing sensitive data.
Install dependencies necessary to accomplish this step:
npm i cookie-parser
Cookie encryption#
Generate a private key that you will use to encrypt and decrypt cookies:
openssl genrsa -out ./privkey.pem 2048
Add import statements that you'll need for /user/* endpoints to api.ts:
import * as crypto from 'crypto';
import * as fs from 'fs';
import { join } from 'path';
Declare the encrypt()
and decrypt()
functions that will help protect data kept in cookies from manipulation:
const key = fs.readFileSync(
join(process.cwd(), 'privkey.pem'),
'utf8'
);
function encrypt(toEncrypt: string): string {
const buffer = Buffer.from(toEncrypt);
const encrypted = crypto.privateEncrypt(key, buffer);
return encrypted.toString('base64');
}
function decrypt(toDecrypt: string): string {
const buffer = Buffer.from(toDecrypt, 'base64');
const decrypted = crypto.publicDecrypt(key, buffer);
return decrypted.toString('utf8');
}
User authentication#
You can now introduce endpoints mentioned at the beginning of this section, and keep userID
in the cookie file as it's now protected from manipulation.
Start by importing the cookie-parser
:
This page is a preview of The newline Guide to Angular Universal