Giter Site home page Giter Site logo

authhero's Introduction

AuthHero

A simple authentication service.

Setup

Prerequisites

  • Dependency management using poetry

    • If you'd rather not install poetry on your system, you can download the wheel from the Github Releases page and install the authhero package in a local virtual environment.
  • PostgreSQL

    • The app will connect to a Postgres database running on localhost
    • If you'd rather not install Postgres, but still want to run the tests, you can skip the tests that need a database with: pytest -m "not functional"
    • Set up the local development and test databases with:
# Assumes username: postgres, without password (configurable)
./scripts/init_local_db.py

Installation

You can either setup a local virtual environment with poetry or install the authhero package with a wheel from the project's Releases page on Github.

Running

Run a local Flask dev server from the src directory with:

flask run

You should be able to see the Swagger API documentation with fully functioning UI to call the API on http://127.0.0.1:5000/.

User journey ๐Ÿš€

  • Register a new user with /auth/register
  • Login with entered credentials at /auth/login
    • Save the api_key token provided in the response
    • In the Swagger Docs, enter the token in the Authorize menu on the top-right
  • Interact with the User CRUD API at /users/*
    • Can view all active users
  • Logging out will invalidate all of users active tokens, and the user will need to login again, and request a new token
  • Deleting a user can only be done on the logged in user, and it is a soft-delete, where the user's API keys will no longer be able to be used for authentication.

Testing

There are two kinds of tests: "simple" unit tests and functional tests that, while not being true end-to-end tests, they test the full functionality, including the database.

  • Inside a virtual env, run pytest from the repo root.
  • Run only the unit tests with `pytest -m "not functional"

Due to time, only partial code coverage.

Design decisions

  • Picked MVC to structure the code, since it should be a simple project
    • Would try the Repository pattern for more complex use cases
    • Added a layer for business logic, so as to not pollute models or views, in services.py files
  • Flask as a simple web server, with the following libraries:
    • flask-restx - a handy library for building REST APIs in Flask, comes with integrated Swagger Docs.
    • SQLAlchemy - a database toolkit
    • bcrypt - for secure password hashing
  • Configuration through Config objects
  • Storing of hashed passwords using bcrypt (hashing and salt using default configuration)
  • Minimal validation in User CRUD, done using flask_restx.reqparse
  • No AUTOCOMMIT, prefer "Unit of Work" pattern
  • PostgreSQL instead of SQLite
    • Slightly more complicated to set up, but since I had enough time to do so, I did :)
    • Much more likely to be used in a real product

Data Model:

  • Two entities: User and ApiKey (one-to-many relationship)
  • All models have the created_on and updated_on attributes for easy auditing and data analysis
  • Implemented "soft" deletion of Users, with the is_active flag

Authentication

  • Decided to implement only Token-authentication, due to time restrictions
  • Currently can only authenticate from custom header: "X-API-KEY"
    • Authentication via querystring was not implemented due to time

Future improvements and ideas

  • Use pydantic for configuration and secrets handling
    • Also add a ProductionConfig using this
  • Document all possible responses and status codes
    • Did not cover all in docs due to time
  • Handle all database errors since it's quite an important dependency
  • Better test coverage - would've done more with more time
    • Also different tests:
      • end-to-end
      • smoke tests
      • load testing, for example with locust
  • CI/CD system
  • Docker container
  • Kubernetes configuration
  • User.id currently is currently an int that autoincrements from 1
    • In a distributed authentication system, would prefer uuid over int to avoid collision
    • If still int, would configure primary key generation differently
  • Introduce role-based access and have a more sophisticated authorization system, with at least an "admin" role
  • Have the authentication system be more abstract so that it's extendable to more ways of authenticating and/or providers, for example to be able to add JWT and OAuth

Addendum, after submitting the assignment...

Would also do the following improvements:

  • Split off User attributes like first_name and last_name into a new table called Profile, so as to not affect the User model that is used for authentication.
  • Do not return ints as status codes in views, but use classes provided by Flask
  • As it is, I did not include any logging in the solution and instead relied on built in error-handling of the libraries used. For an actual solution, I would add way custom exceptions per level of abstraction, and then error-handling and logging.
  • In an actual production-ready solution, I would also add integrations with a monitoring platform like Prometheus/Grafana, as well as Infrastructure-as-Code, like Terraform or Pulumi.

authhero's People

Contributors

kibernick avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.