Sign inSign up

tinymfa/go-tiny-mfa

By tinymfa

•Updated over 2 years ago

a tiny-mfa implementation written in go

Image
0

4.2K

tinymfa/go-tiny-mfa repository overview

⁠go-tiny-mfa

a tinymfa implementation written in go. See https://tinymfa.parzival.link⁠ for more information.

Our repository on github: https://github.com/ghmer/go-tiny-mfa⁠.

Find a docker repository at https://hub.docker.com/r/tinymfa/go-tiny-mfa⁠

Checkout our postman collection: https://tinymfa.parzival.link/tinymfa.postman_collection.json⁠

Attention This is a hobby project to get more used to go-programming. It is not intended to be used in a production environment without making further security related steps.

⁠How it works

  1. tinymfa connects to a postgres database and creates the required table structures. Then, it generates a root encryption key and access token. The encryption key is stored on the filesystem.
  2. when creating an issuer, a new encryption key is generated, encrypted with the root encryption key and then stored to the database. Also, an access token unique to this issuer is generated as well.
  3. when creating a user below an issuer, a new secret key is generated and encrypted with the issuer encryption key.
  4. The api offers an endpoint to generate a QRCode for a user. Use this to let the user register their secret key in an Authenticator App
  5. The api offers an endpoint to validate a token. Send the token using a http post request to the api interface. The resulting json object contains the boolean result of the validation.

⁠Access tokens

tinymfa can be configured to validate access to its resources. Once activated, tinymfa checks for presence of the http header key 'tiny-mfa-access-token'. This must be either the root token created on installation, or the issuer token presented upon issuer creation.

⁠API Endpoints

⁠System Configuration and Audit
EndpointMethodDescription
/api/v1/system/auditGETReturn audit entries
/api/v1/system/configurationGETReturn current system configuration
/api/v1/system/configurationPOSTUpdates the system configuration
⁠payload: Update system configuration
keytypedescription
http_portintegerthe port to run on. Requires a restart!
deny_limitintegerhow many times is a user allowed to input a wrong token before we don't allow validation for the given message. This is to defeat brute force attacks
veriy_tokenbooleanwhether to verify if the tiny-mfa-access-token is set and contains a valid token
{
    "http_port" : 57687,
    "deny_limit": 3,
    "verify_tokens": true
}
⁠Issuer handling
EndpointMethodDescription
/api/v1/issuerGETReturn all registered issuers
/api/v1/issuerPOSTCreate a new issuer using a POST request
/api/v1/issuer/{issuer}GETReturn a distinct issuer by its name
/api/v1/issuer/{issuer}POSTUpdates a distinct issuer using a POST request
/api/v1/issuer/{issuer}DELETEDeletes a distinct issuer using a DELETE request
⁠payload: create a new issuer
keytypedescription
namestringthe name of this issuer
contactstringa mail adress of the responsible person
token_lengthintegerLength of the desired totp tokens
enabledbooleanwhether this issuer is active
{
    "name": "issuer.local",
    "contact": "[email protected]",
    "token_length": 6,
    "enabled": true
}
⁠payload: update a new issuer
keytypedescription
contactstringa mail adress of the responsible person
token_lengthintegerLength of the desired totp tokens
enabledbooleanwhether this issuer is active
{
    "contact": "[email protected]",
    "token_length": 8,
    "enabled": true
}
⁠Access token handling
EndpointMethodDescription
/api/v1/issuer/{issuer}/tokenGETReturn all registered access tokens for a given issuer
/api/v1/issuer/{issuer}/tokenPOSTCreates a new access token for the given issuer using a PUT request
/api/v1/issuer/{issuer}/token/{tokenid}DELETEDeletes a distinct access token in the scope of a distinct issuer
⁠payload: create a new issuer access token
keytypedescription
descriptionstringa description for the new token
{
    "description" : "my access token"
}
⁠User handling
EndpointMethodDescription
/api/v1/issuer/{issuer}/usersGETReturn all users belonging to the scope of a distinct issuer
/api/v1/issuer/{issuer}/usersPOSTCreate a new user in the scope of a distinct issuer
/api/v1/issuer/{issuer}/users/{user}GETReturn a distinct user in the scope of a distinct issuer
/api/v1/issuer/{issuer}/users/{user}POSTUpdate a distinct user in the scope of a distinct issuer
/api/v1/issuer/{issuer}/users/{user}DELETEDeletes a distinct user in the scope of a distinct issuer
⁠payload: create a new user
keytypedescription
namestringthe name this user
emailstringa mail adress of the user
enabledbooleanwhether this user is active
{
    "name" : "demo",
    "email": "[email protected]",
    "enabled": true
}
⁠payload: update an existing user
keytypedescription
emailstringa mail adress of the user
enabledbooleanwhether this user is active
{
    "email": "[email protected]",
    "enabled": true
}
⁠User token handling
EndpointMethodDescription
/api/v1/issuer/{issuer}/users/{user}/totpGETGenerates and returns a PNG image of a QRCode in the scope of a distinct user and issuer
/api/v1/issuer/{issuer}/users/{user}/totpPOSTValidates a given token in the scope of a distinct user and issuer
⁠payload: validate a totp token
keytypedescription
tokenstringthe token to validate
{
    "token": "123456"
}

⁠docker-compose

This will result in a working tiny-mfa instance:

version: "3"
services:
    database:
        image: postgres:latest
        networks: 
            - tiny-mfa-net
        volumes:
            - data:/var/lib/postgresql/data
        environment: 
            - POSTGRES_USER=postgres
            - POSTGRES_PASSWORD=postgres
            - POSTGRES_DB=tinymfa
    
    tinymfa:
        image: tinymfa/go-tiny-mfa
        networks:
            - tiny-mfa-net
        ports:
            - "57687:57687"
        volumes:
            - tinysecret:/opt/go-tiny-mfa/secrets
        environment:
            - POSTGRES_HOST=database
            - POSTGRES_USER=postgres
            - POSTGRES_PASSWORD=postgres
            - POSTGRES_DB=tinymfa
        restart: unless-stopped
volumes: 
    data:
    tinysecret:

networks: 
    tiny-mfa-net:

⁠quickstart

  • create a tiny-mfa instance using the docker-compose script from above
  • create an issuer:
curl --location --request POST 'http://localhost:57687/api/v1/issuer' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "issuer.local",
    "contact": "[email protected]",
    "token_length:" 6,
    "enabled": true
}'
  • create a user:
curl --location --request POST 'http://localhost:57687/api/v1/issuer/issuer.local/users' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name" : "demo",
    "email": "[email protected]",
    "enabled": true
}'
  • get the QRCode for the Authenticator App:
curl --location --request GET 'http://localhost:57687/api/v1/issuer/issuer.local/users/demo/totp'
  • validate a token
curl --location --request POST 'http://localhost:57687/api/v1/issuer/issuer.local/users/demo/totp' \
--header 'Content-Type: application/json' \
--data-raw '{
    "token" : "123456"
}'

⁠Already working

  • v1 api to CRUD issuers and users
  • validate tokens
  • limit validation attempts to defeat brute force attacks
  • generate QRCode png images
  • basic authorization via http header

⁠Todo

  • authorization model
  • administrative UI
  • ...

Tag summary

Content type

Image

Digest

sha256:1825affeb…

Size

6.5 MB

Last updated

over 2 years ago

docker pull tinymfa/go-tiny-mfa