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:
/authenticateto authenticate user and return a valid JWT token via HTTP POST request/verifyperforms OTP authentication with OTP provider (Google Authenticator) and return a valid OTP token via HTTP POST request/qrcodeprovides existing users QR code/userprovides user home page/apiprovides 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.goprovides confugration structure for our serverdb.goprovides DB layer based on gorm libraryhandlers.gojwt.gocontains all code related to JWT tokens and its structures used in HTTP server- main.go
middleware.goprovides different middleware used by the HTTP serverserver.goprovides server codebasetempaltes.goprovides codebase for loading HTML templatesutils.gocontains 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: