Skip to main content

Username & Password

This recipe will show you how to register users, save hashed and salted passwords in a database and issue JWTs that the frontend can use for subsequent requests.

tip

Looking for complete code samples? Check the ready made code section!

Ingredients

  1. Bcrypt library for hashing passwords
  2. JWT library for generating JSON web tokens
  3. Ability to send email from your server (for email verification)

Outputs

Screens

NamePathDescription
Register/registerDisplays the registration form and sends data to the POST /users endpoint
Verify/verify?token={token}Handles email verification links, sending data to POST /auth/verify
Login/loginDisplays the login form and sends data to the POST /auth/login endpoint
Dashboard/Only accessible if the user has a valid JWT issued. Fetches data from GET /me

Endpoints

MethodPathDescription
POST/usersRegister a new user
POST/auth/verifyVerifies a user's email address
POST/auth/tokenValidates the email/password and returns a JWT
GET/meReturns the current user's details, only if logged in

Tables

Method

Registration Screen

The registration screen allows users to create accounts by specifying their email and password. It will trigger an email to be sent for verification purposes via the POST /users endpoint.

Logic

Registration Endpoint

The POST /users endpoint is where user accounts will be registered. It accepts a body that should contain all user information necessary to create an account, including the email and password.

Request Body

The request body can contain as few or as many fields as required for your use case. You may wish to omit the first and last names, for example.

{
"meta": {
"verificationURL": "http://localhost:3001/verify"
},
"data": {
"type": "users",
"attributes": {
"firstName": "Fred",
"lastName": "Smith",
"email": "fred@codecookbook.io",
"password": "MyS3cureP@assword#"
}
}
}

Logic

  1. Ensure all provided fields are valid (including password requirements)
  2. Hash and salt the provided password
  3. Save the information to the User database table
  4. Return the newly created user information

Response Body

{
"data": {
"type": "users",
"attributes": {
"id": 1234,
"firstName": "Fred",
"lastName": "Smith",
"email": "fred@codecookbook.io",
"createdAt": "2023-04-12T20:07:22.115Z",
"updatedAt": "2023-04-12T20:07:22.115Z"
}
}
}

Verification Screen

The verification screen is used to verify a user's email address. The POST /users endpoint includes a link to this page when sending the verification email. The screen accepts a token in the querystring and submits the data to the POST /auth/verify endpoint in order complete verification.

Logic

Token Endpoint

The POST /auth/token endpoint accepts the user's credentials and returns a JSON web token (JWT) which should be stored by the client for subsequent requests.

Request Body

{
"data": {
"type: "credentials",
"attributes": {
"provider": "password",
"email": "fred@codecookbook.io",
"password": "MyS3cureP@assword#"
}
}
}

Logic

  1. Look up the user in the database based on the email field
    a. Check the user exists
    b. Use the bcrypt library to compare the provided password to the hashed password saved in the database
  2. Generate a JWT, providing the user's ID as the sub field
  3. Return the JWT to the client along with the user's information

Response Headers

# The Set-Cookie header contains the issued JWT as a HTTP-only cookie
Set-Cookie: access_token=dXNlcm5hbWU6cGFzc3dvcmQ...; HttpOnly

Response Body

{
"data": {
"type": "sessions",
"attributes": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}
}

Protected Endpoints

In this example we will create an endpoint called GET /users/:id which will return the specified user's details, but only if a valid JWT is provided and the sub field matches the user ID requested. In other words, a user shouldn't be able to view another user's details.

Request Headers

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Logic

  1. Verify the Authorization header has been provided
  2. Use the JWT library to validate the provided token
  3. Get the user based on the sub property extracted from the token (the user ID)
  4. Throw an unauthorized exception if any of the above fails

Ready-Made Code

Download this recipe as a complete application!

Download Code