Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/vkuznet/2fa-server

Example of 2FA server in GoLang
https://github.com/vkuznet/2fa-server

Last synced: 3 months ago
JSON representation

Example of 2FA server in GoLang

Awesome Lists containing this project

README

        

## 2fa-server

[![Build Status](https://github.com/vkuznet/2fa-server/actions/workflows/build.yml/badge.svg)](https://github.com/vkuznet/2fa-server/actions/workflows/build.yml)
[![Go Report Card](https://goreportcard.com/badge/github.com/vkuznet/2fa-server)](https://goreportcard.com/report/github.com/vkuznet/2fa-server)
[![GoDoc](https://godoc.org/github.com/vkuznet/2fa-server?status.svg)](https://godoc.org/github.com/vkuznet/2fa-server)

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](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en_US&gl=US) 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](https://gorm.io/docs/) 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:
- [GoLang server with 2FA](https://www.thepolyglotdeveloper.com/2017/05/add-two-factor-authentication-golang-restful-api)
- [GoLang server with JWT](https://www.thepolyglotdeveloper.com/2017/03/authenticate-a-golang-api-with-json-web-tokens)
- [GoLang with Google Auth App](https://www.socketloop.com/tutorials/golang-verify-token-from-google-authenticator-app)
- [sec51 twofactor](https://github.com/sec51/twofactor)
- [go-guardian](github.com/shaj13/go-guardian)
- [Writing auth app with go-guardian](https://medium.com/@hajsanad/writing-scalable-authentication-in-golang-using-go-guardian-83691219a73a)
- [GoLang JWT auth/authz](https://www.bacancytechnology.com/blog/golang-jwt)
- [Using JWT for auth in GoLang](https://codeburst.io/using-jwt-for-authentication-in-a-golang-application-e0357d579ce2)