Go Auth App
Simple session based authentication with Mux and MongoDB
This repository was created as an exercise in Go development. This serves as a barebones boilerplate for a webapp that requires authentication via a database.
Setup
You can build the binary by running go build
and run it via ./go-auth-w-mongo
Please make sure you have a local MongoDB instance running before attempting to run anything here! A simple auth flow may look something like this
- User attempts to access dashboard
- User is redirected to log in
- User logs in and is redirected to dashboard
- (Admin only) Admin can add a new user
The following routes have been implemented:
/register "register a new user"
/login "authenticates a user"
/dashboard "simple dashboard to display user's name"
/logout "destroys current user's session"
/register
The /register
endpoint first checks to see if the user has a valid session (this is done through the authentication middleware in middleware/middleware.go
) and is an admin.
Then, it attempts to parse the form data into the User schema. After doing so, a hash is generated from the password to avoid storing it in plaintext, and the document is inserted into the database.
curl --location --request POST 'localhost:8080/register' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'email=test@email.com' \
--data-urlencode 'name=jacky' \
--data-urlencode 'password=pass123'
/login
The /login
endpoint attempts to decode the form data into the Credentials schema. Then, it attempts to find a user with a matching email in the database. If found, it compares the password hashes to see if the password is correect. If so, it will create a new session token, write that to both the client (as a cookie) and the database (as a document), and redirect them to /dashboard
curl --location --request POST 'localhost:8080/login' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'email=test@email.com' \
--data-urlencode 'password=pass123'
/dashboard
The /dashboard
endpoint takes advantage of the fact that our middleware injects a header called X-res-email
with the user's email if the user has a valid session. This is a basic endpoint that returns a custom greeting based on the user's name.
curl --location --request GET 'localhost:8080/dashboard'
/logout
The /logout
also uses the X-res-email
header to make the logout code super simple and short. Basically, it just resets the user's session on the database side, so auth will redirect to login.
curl --location --request GET 'localhost:8080/logout'
Adding to the project
As this is just a boilerplate, this project is meant to be easily extensible. Feel free to add more endpoints in routes/routes.go
, render and serve templates, and add more middleware! The project is your oyster :)
FAQ
How does session based authentication work?
This photo (courtesy of PracticalDev) does a pretty good job at explaining it!
Adding an admin user
Remove the admin checker middleware from server.go
register endpoint by changing line 22 from
r.HandleFunc("/register", middleware.Auth(routes.Register, true))
to
r.HandleFunc("/register", routes.Register)
Then, make a POST request to the /register
endpoint with a x-www-form-urlencoded
(form data) with the required fields. Make sure to set the admin field to true!
It would look something like this
curl --location --request POST 'localhost:8080/register' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'email=test@email.com' \
--data-urlencode 'name=jacky' \
--data-urlencode 'password=pass123' \
--data-urlencode 'admin=true'
Don't forget to change that line back later.
Changing URL of database
This is set in routes/routes.go
line 19,
var session, _ = mgo.Dial("mongodb://localhost:27017")
Changing name of database used and name of collection
This is set in routes/routes.go
line 22,
// "exampleDB" is the name of the database
// "Users" is the name of the collection
var Users = session.DB("exampleDB").C("Users")
Other types of database connections
Edit db/db.go
and change const DB_TYPE
to something else.