I find myself having to create user authentication systems over and over again for various projects and hackathons. So, I created this starter template that I can modify for any future projects easily. Basic authentication is set up with this GraphQL API for users to register, login, get user data, update user data and reset passwords. Users are persisted in MongoDB.
- Node.js (server environment)
- TypeScript - language
- dotenv - environment variables
- bcryptjs - encryption
- Express.js - serving
- GraphQL (API)
- Apollo Server - serving
- TypeGraphQL - structure
- MongoDB (database)
To run this project, you will need to add the following environment variables to a config.env
file in the root directory (not src
).
MONGO_URI
Your MongoDB uri (e.g. mongodb://127.0.0.1:27017/auth-template)
JWT_SECRET
A private key for creating your json web token's. Can be any string value (e.g. helloworld). For a production application, it should be something hard to guess.
JWT_EXPIRES_IN
The amount of time before a JWT expires (e.g. 1 year)
Your config.env
file should look something like:
MONGO_URI=mongodb://127.0.0.1:27017/auth-template
JWT_SECRET=helloworld
JWT_EXPIRES_IN="1 year"
git clone https://github.com/ammar-ahmed22/graphql-auth-template.git
cd graphql-auth-template
npm install # yarn install
echo 'MONGO_URI=mongodb://127.0.0.1:27017/auth-template\nJWT_SECRET=helloworld\nJWT_EXPIRES_IN="1 year"' >> config.env
npm run dev # yarn dev
API is now live at http://localhost:8080/graphql
!
There are only two types of significance in this starter template; User
and AuthPayload
. User
is self-explantory. AuthPayload
is the JWT response sent with a number of mutations.
type User {
_id: ID! # MongoDB ID
createdAt: Timestamp! # Custom scalar created by type-graphql for Date handling
firstName: String!
lastName: String!
middleName: String
username: String!
}
type AuthPayload {
token: String! # JWT
}
These mutations can be called without any authentication required.
Used to create a user in the database
mutation Register(
$password: String!,
$username: String!,
$firstName: String!,
$middleName: String
$lastName: String!,
) {
register(
username: $username
password: $password,
firstName: $firstName,
middleName: $middleName
lastName: $lastName,
){
token
}
}
Input your username
, password
, firstName
and lastName
(middleName
is optional):
{
"username": "YOUR_USERNAME",
"password": "YOUR_PASSWORD",
"firstName": "YOUR_FIRST_NAME",
"lastName": "YOUR_LAST_NAME",
"middleName": "YOUR_MIDDLE_NAME"
}
Responds with a JWT.
{
"data": {
"register": {
"token": "<JWT>"
}
}
}
Used to login with your credentials
mutation Login(
$password: String!,
$username: String!,
) {
login(
username: $username
password: $password,
){
token
}
}
Input your username
and password
:
{
"username": "YOUR_USERNAME",
"password": "YOUR_PASSWORD",
"firstName": "YOUR_FIRST_NAME",
"lastName": "YOUR_LAST_NAME",
"middleName": "YOUR_MIDDLE_NAME"
}
Responds with a JWT.
{
"data": {
"login": {
"token": "<JWT>"
}
}
}
Used to generate a reset password token (pre-requisite to resetting your password)
mutation ForgotPassword($username: String!){
forgotPassword(username: $username)
}
Input your username
:
{
"username": "YOUR_USERNAME",
}
Responds with the reset password token:
{
"data": {
"forgotPassword": "<token>"
}
}
Used to reset password (a token must be generated with forgotPassword
first)
mutation ResetPassword(
$token: String!,
$newPassword: String!
){
resetPassword(
token: $token,
newPassword: $newPassword
)
}
Input your token
and newPassword
:
{
"token": "<token>",
"newPassword": "YOUR_NEW_PASSWORD"
}
Responds with a boolean indicating success:
{
"data": {
"resetPassword": true
}
}
With all authorized queries and mutations, an Authorization
header with the value of Bearer <token>
must be set.
Otherwise, access will be denied.
Used to update your authenticated user's name in the database
mutation UpdateName(
$firstName: String,
$middleName: String
$lastName: String,
) {
updateName(
firstName: $firstName,
middleName: $middleName
lastName: $lastName,
){
token
}
}
Input your firstName
, lastName
and middleName
. (all values are optional, any values not provided will remain the same):
{
"firstName": "YOUR_FIRST_NAME",
"lastName": "YOUR_LAST_NAME",
"middleName": "YOUR_MIDDLE_NAME"
}
Set your headers:
{
"headers": {
"Authorization": "Bearer <JWT>"
}
}
Responds with a JWT.
{
"data": {
"updateName": {
"token": "<JWT>"
}
}
}
Gets your authenticated user
query User {
user{
username
firstName
lastName
middleName
_id
createdAt
}
}
Set your headers:
{
"headers": {
"Authorization": "Bearer <JWT>"
}
}
Responds with user.
{
"data": {
"user": {
"username": "YOUR_USERNAME",
"firstName": "YOUR_FIRST_NAME",
"lastName": "YOUR_LAST_NAME",
"middleName": "YOUR_MIDDLE_NAME",
"_id": "MONGO_DB_ID",
"createdAt": 0
}
}
}