Skip to content

vkuznet/2fa-server

Repository files navigation

2fa-server

Build Status Go Report Card GoDoc

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"}

Code organization

The code is organized in modules:

  • config.go provides confugration structure for our server
  • db.go provides DB layer based on gorm library
  • handlers.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 server
  • server.go provides server codebase
  • tempaltes.go provides codebase for loading HTML templates
  • utils.go contains varioud utility functions used across the code

All HTML tempaltes are located in static/tmpl area, while css in static/css.

References

I'm greateful to many resources I found online. In particular, this work will not be complete without the following: