This microservice performs basic user authentication.
In order to keep labels consitent across micro services, we will use the template available in the docs folder of this repo to auto populate the new repo with labels. After running "npm install", run the following commands from the server directory:
npx ghlbl -o NACAGA -r <name-of-new-repo> -t <organization-pat> -d
npx ghlbl -o NACAGA -r <name-of-new-repo> -t <organization-pat> -i docs/labels.json
Provide a high-level overview of the microservice, including its purpose, key features, and any important concepts.
URL: /user-authentication
-
URL:
/create-user
-
Method:
POST
-
Description: Creates a user.
-
Query Parameters:
Parameter Type Description username
String The User's Username password
String The User's Password (this should be hashed when sent) -
Example:
Request
{ "headers": {}, "body": { "username": "user1", "password": "password" } }
Response
{ "body": { "code": 201, "message": "User successfully created" } }
-
URL:
/login-user
-
Method:
POST
-
Description: Logs in a user.
-
Query Parameters:
Parameter Type Description username
String The User's Username password
String The User's Password (this should be hashed when sent) -
Example:
Request
{ "headers": {}, "body": { "username": "user1", "password": "password" } }
Response
{ "body": { "code": 200, "message": "User successfully logged in", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOjEsImV4cGlyYXRpb25EYXRlIjoiMjAyMy0xMi0yOVQwMTo0ODo1OS43NTlaIiwiaWF0IjoxNzAzODA3MzM5fQ.tVw4HvHm-xyKvNltM3XrHDYi2c7vecgLNr_UoO9Oz4o" } }
-
URL:
/change-username
-
Method:
PATCH
-
Description: Changes a user's username.
-
Query Parameters:
Parameter Type Description username
String The User's current Username new_username
String The User's new Username token
String The User's session token (user must be ACTIVE and have a valid session token for request to succeed) -
Example:
Request
{ "headers": {}, "body": { "new_username": "user1", "username": "user2", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOjEsImV4cGlyYXRpb25EYXRlIjoiMjAyMy0xMi0yOVQwMjoyMzozMi42NDNaIiwiaWF0IjoxNzAzODA5NDEyfQ.3Wm3ivdpyWUFryDFIZhsKxpwL_VPD5hgcThHmO1iWcg" } }
Response
{ "body": { "code": 200, "message": "Username changed successfully" } }
-
URL:
/change-password
-
Method:
PATCH
-
Description: Changes a user's password.
-
Query Parameters:
Parameter Type Description username
String The User's Username new_password
String The User's new Password token
String The User's session token (user must be ACTIVE and have a valid session token for request to succeed) -
Example:
Request
{ "headers": {}, "body": { "new_password": "123456", "username": "user1", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOjEsImV4cGlyYXRpb25EYXRlIjoiMjAyMy0xMi0yOVQwMjoyMzozMi42NDNaIiwiaWF0IjoxNzAzODA5NDEyfQ.3Wm3ivdpyWUFryDFIZhsKxpwL_VPD5hgcThHmO1iWcg" } }
Response
{ "body": { "code": 200, "message": "Password changed successfully" } }
-
URL:
/change-user-info
-
Method:
PATCH
-
Description: Changes a user's basic info.
-
Query Parameters:
Parameter Type Description username
String The User's Username new_fields
Dict A dictionary containing key:value pairs where the key is the name of the db field and the value is the value for that field in the db (password, username, and status are not valid keys) token
String The User's session token (user must be ACTIVE and have a valid session token for request to succeed) -
Example:
Request
{ "headers": {}, "body": { "new_fields": { "firstname": "John", "lastname": "Smith", "favoritecolor": "blue" }, "username": "user1", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOjEsImV4cGlyYXRpb25EYXRlIjoiMjAyMy0xMi0yOVQwMjoyMzozMi42NDNaIiwiaWF0IjoxNzAzODA5NDEyfQ.3Wm3ivdpyWUFryDFIZhsKxpwL_VPD5hgcThHmO1iWcg" } }
Response
{ "body": { "code": 200, "message": "User info changed successfully" } }
-
URL:
/logout-user
-
Method:
POST
-
Description: Log a user out. This sets their session token to expired.
-
Query Parameters:
Parameter Type Description username
String The User's Username -
Example:
Request
{ "headers": {}, "body": { "username": "user1" } }
Response
{ "body": { "code": 200, "message": "User successfully logged out" } }
-
URL:
/deactivate-user
-
Method:
POST
-
Description: Deactivates a user. This sets their user to
INACTIVE
, pretty much deleting the user whilst keeping their info in the database. Inactive users cannot be set back to Active without direct access to the database. Their user record is also not considered in any username checking. -
Query Parameters:
Parameter Type Description username
String The User's Username -
Example:
Request
{ "headers": {}, "body": { "username": "user1" } }
Response
{ "body": { "code": 200, "message": "User successfully deactivated" } }
-
URL:
/activate-user
-
Method:
POST
-
Description: Activates a user. This request only works on Blocked or already Active users. If a user is Inactive they can only be reactivated through direct queries to the database.
-
Query Parameters:
Parameter Type Description username
String The User's Username -
Example:
Request
{ "headers": {}, "body": { "username": "user1" } }
Response
{ "body": { "code": 200, "message": "User successfully activated" } }
-
URL:
/block-user
-
Method:
POST
-
Description: Blocks a user. This request can only be performed on Active or already blocked users. If a user is Inactive they can only be set to Blocked through direct queries to the database.
-
Query Parameters:
Parameter Type Description username
String The User's Username -
Example:
Request
{ "headers": {}, "body": { "username": "user1" } }
Response
{ "body": { "code": 200, "message": "User successfully blocked" } }
-
URL:
/delete-user
-
Method:
DEL
-
Description: Deletes a user. It is recommended that Deactivation of a user is used rather than deletion. Deactivation voids the user's username as taken, and completly stops the user from logging in. Deleting a user will permanently delete a user's info from the database, while deactivation will keep their info.
-
Query Parameters:
Parameter Type Description username
String The User's Username -
Example:
Request
{ "headers": {}, "body": { "username": "user1" } }
Response
{ "body": { "code": 200, "message": "User successfully deleted" } }
-
URL:
/validate-user-session
-
Method:
POST
-
Description: Validates a user's session. This is meant to be used as validation that a user is logged in for actions that the user attempts to perform that are outside the scope of the authentication service. If a user has a valid unexpired session token, a success will be returned.
-
Query Parameters:
Parameter Type Description username
String The User's Username token
String The User's session token (user must be ACTIVE and have a valid session token for request to succeed) -
Example:
Request
{ "headers": {}, "body": { "username": "user1", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOjIsImV4cGlyYXRpb25EYXRlIjoiMjAyMy0xMi0yOVQwNDoxNDozNC4zOTBaIiwiaWF0IjoxNzAzODE2MDc0fQ.UEH4UgI-kAYmdwsASZytfxoJzJYt0ESFsEVPQoa2PGo" } }
Response
{ "body": { "code": 200, "message": "User session is valid" } }
-
URL:
/get-users
-
Method:
GET
-
Description: Gets all of the requested fields for each Active or Blocked user in the database. Will not retrieve password.
-
Query Parameters:
Parameter Type Description fields
List A list of the database fields you want to retrieve for each user -
Example:
Request
{ "headers": {}, "body": { "fields": ["username", "status", "firstname", "lastname"] } }
Response
{ "body": { "code": 200, "message": "Users successfully retrieved", "users": [ { "username": "user1", "status": "ACTIVE", "firstname": "John", "lastname": "Smith" }, { "username": "user2", "status": "ACTIVE", "firstname": "NULL", "lastname": "NULL" }, { "username": "user3", "status": "BLOCKED", "firstname": "Jim", "lastname": "NULL" } ] } }
-
URL:
/get-user-info
-
Method:
GET
-
Description: Gets all of the info in the database for a specified user. Does not retrieve password.
-
Query Parameters:
Parameter Type Description username
String The User's Username -
Example:
Request
{ "headers": {}, "body": { "username": "user1" } }
Response
{ "body": { "code": 200, "message": "Users successfully retrieved", "user": { "id": 1, "username": "user1", "status": "ACTIVE", "firstname": "John", "lastname": "Smith", "phone": "NULL", "favoritecolor": "blue" } } }
The microservice uses a relational database system, specifically MariaDB.
The following tables constitute the database schema:
Stores information about users.
Column | Type | Description |
---|---|---|
id |
INT | Unique user identifier |
username |
VARCHAR | User's username |
password |
VARCHAR | User's password |
status |
VARCHAR | BLOCKED, ACTIVE, or DEACTIVE |
firstname |
VARCHAR | User's first name |
lastname |
VARCHAR | User's last name |
phone |
VARCHAR | User's phone number |
favoritecolor |
VARCHAR | User's favorite color |
Stores user sessions and jw tokens.
Column | Type | Description |
---|---|---|
id |
INT | Unique session identifier |
userid |
INT | Foreign Key session owner's id |
token |
VARCHAR | jwt session token |
expiration |
DATETIME | Expiration date of the user's session |
- The
UserSessions
table has a foreign key (userid
) referencing theUsers
table'sid
.
Before you begin, ensure you have the following prerequisites installed:
-
Clone the repository:
git clone https://github.com/NACAGA/Authentication-Micro-Service.git
-
Change into the project directory:
cd <Authentication-Micro-Service>
-
Install dependencies:
npm install
Make sure to include a .env
file in the root directory of the project (Same directory as this README). The following environment variables
should be present:
MARIADB_PASSWORD=password # change this if you want to use a different password
MARIADB_USER=user1 # change this if you want to use a different user
MARIADB_DATABASE=test_database # change this if you want to use a different database name
MARIADB_ROOT_PASSWORD=root_password # change this if you want to use a different root password
DB_HOST=database # database is the name of the database container
DB_PORT=3306 # default mysql port
SERVER_PORT=3000 # change this if you want to use a different port
JWT_SECRET= # add your key here
Adjust the values based on your specific configuration. DB_HOST can be the ip address of the database container if you are not using docker-compose. It could also be localhost if running on your local machine.
To run the service locally on your machine, run the following command inside of the root directory. Line 1 copies the .env file to the current environment. Line 2 builds the database docker image with the environment variables from the .env file. Line 3 runs the database docker image. Line 4 runs the tests.
[ ! -f .env ] || export $(grep -v '^#' .env | xargs)
docker build -t ams-database database $(for i in `cat .env`; do out+="--build-arg $i " ; done; echo $out;out="")
docker run --rm -d -p $DB_PORT:$DB_PORT --name ams-database-dt ams-database
DB_HOST=localhost npm start
OR
To run the service in Docker containers the following command from the base directory:
docker compose up --build --force-recreate
To remove all containers afterwards, run:
docker compose down
To run the tests, run the following command inside of the root directory.
[ ! -f .env ] || export $(grep -v '^#' .env | xargs)
docker build -t ams-database database $(for i in `cat .env`; do out+="--build-arg $i " ; done; echo $out;out="")
docker run --rm -d -p $DB_PORT:$DB_PORT --name ams-database-dt ams-database
DB_HOST=localhost npm test
For Nate
docker compose up --build