Fully functional Go based HTTP server with 2FA based on OTP (One-Time Password) manager like Google Authenticator, etc.
The server contains the following end-points:
/authenticate
to authenticate user and return a valid JWT token via HTTP POST request/verify
performs OTP authentication with OTP provider (Google Authenticator) and return a valid OTP token via HTTP POST request/qrcode
provides existing users QR code/user
provides user home page/api
provides authorized user access to protected data either using GET or POST HTTP methods And, the server provides sing-in and sign-up HTML pages.
You should install Google Authenticator or similar OTP authenticator on your smart phone.
To build and run server just do the following:
# build server code
go build
# run server, by default it runs on port 12345 and use static area
./2fa-server
# to customize your server create JSON configuration file
cat > server.json << EOF
{"port":12345, "static": "/my/path/static"}
EOF
# and now you can run it as following
./2fa-server -config server.json
The server stores user data into SQLite DB (basically user's name/secret pairs) and generate QR code image file(s) in user's static area.
The data flow can be represented as following:
# Step 1: install Google Authenticator on your phone
# Step 2: visit our server
# http://localhost:12345
# and either SignIn or SingUp to setup your account
# Ther server will redirect you to /qrcode end-point where
# you can see your QR code
# or, if you already have your credentials you can request QR code via
# HTTP POST API call
curl -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "user=UserName" \
http://localhost:12345/qrcode
# Step 3: scan QR code and open URL. It will add new entry into Google Authenticator
# now we are ready to use it with our app
# Step 4: get token
curl -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "user=UserName" \
http://localhost:12345/authenticate
# it returns server token in JSON format
{"token":"eyJhb..."}
# Step 5: now visit Google Authenticator to obtain new code
# Step 6: authenticate with our server using OTP (One-Time Password) code
# obtained from a previous step
curl -X POST \
-H "Authorization: Bearer $token" \
-H "Content-Type: application/json"
-d '{"otp":"383878", "user": "UserName"}' \
http://localhost:12345/verify
# it returns new token from otp secure code generated by Google Authenticator
"eyJhbG..."
# Step 7: call protected API using new OTP token
otpToken="eyJhbG..."
# if our API needs to be accessed via HTTP GET method we'll use
curl -H "Authorization: Bearer $otpToken" "http://localhost:12345/api?user=UserName"
# if our API needs to be accessed via HTTP POST method we'll use
curl -X POST \
-H "Authorization: Bearer $otpToken"
-H "Content-Type: application/json"
-d '{"user": "UserName"}' \
http://localhost:12345/api
# if everything is fine you'll see the following data with proper password for the user
{"authorized":true,"password":"XXXYYYZZ","username":"UserName"}
The code is organized in modules:
config.go
provides confugration structure for our serverdb.go
provides DB layer based on gorm libraryhandlers.go
jwt.go
contains all code related to JWT tokens and its structures used in HTTP server- main.go
middleware.go
provides different middleware used by the HTTP serverserver.go
provides server codebasetempaltes.go
provides codebase for loading HTML templatesutils.go
contains varioud utility functions used across the code
All HTML tempaltes are located in static/tmpl
area, while css in
static/css
.
I'm greateful to many resources I found online. In particular, this work will not be complete without the following: