Coder Social home page Coder Social logo

curveball / a12n-server Goto Github PK

View Code? Open in Web Editor NEW
442.0 16.0 48.0 4.27 MB

An open source lightweight OAuth2 server

License: Apache License 2.0

Dockerfile 0.19% Makefile 0.33% TypeScript 92.16% CSS 1.39% JavaScript 2.43% Handlebars 3.50%
oauth2 authentication webauthn totp mfa 2fa pkce javascript typescript hacktoberfest

a12n-server's Introduction

Authentication API

This package aims to provide a simple authentication system. The goal is to provide a simple authentication system for developers considering building their own.

The project implements OAuth2 standards where applicable.

a12n-server home screenshot

Requirements

  • Node.js 16.x
  • MySQL, Postgres or Sqlite

Try it out!

You can quickly get a test server up and running by running these commands:

mkdir a12n-server
cd a12n-server
npx @curveball/a12n-server

This will automatically create a configuration file and sqlite database in the current directory.

Then, just open http://localhost:8531/ to create your admin account.

Features

Documentation

Check out the Docs folder

The state of this project

If you are thinking of building a new authentication system, and decide to use this project instead, you get a lot of features for free.

The project has been used in production since 2018 and is still actively developed.

a12n-server's People

Contributors

allanice001 avatar amindhouib avatar beckypollard avatar claudiunicolaa avatar dependabot[bot] avatar elaugier avatar ericrabiner avatar evert avatar greenkeeper[bot] avatar ikbensiep avatar juhangsin avatar lorefnon avatar merrickread avatar mhum avatar mihok avatar nchangfong avatar pschwyter avatar syedfkabir avatar trasherdk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

a12n-server's Issues

Add an admin role and prevent actions

There should be a flag that marks specific users as an 'admin'. We want to prevent many actions in the API if a user is not an admin.

This can be done with the user_privileges table. Once this role is added, we should prevent actions such as:

  • Creating new users
  • Seeing a user's audit log
  • Creating new OAuth2 tokens

Add support for group members.

This should be done after #105

When we have groups in the system, these groups might be accessed via:

/principal/123

If a user is a group, we should add the following API endpoint:

/principal/123/member

This endpoint is a collection that is a list of users that are part of the group. The scope of this ticket is a read-only interface for this. We don't yet need to support adding members or removing them.

The implication of this ticket is also to add a new MySQL table such as 'group_members'.

Add an API that shows currently active sessions

We already have some information in the database in the form of oauth2 tokens. It would be nice to expose a list of tokens that haven't expired yet per user.

Bonus points:

Maybe we can add some more information per access token, such as the last used User-Agent and ip address.

Every active session should be represented as a resource in the API.

Integrate WebAuthN

WebAuthN is the new web api for integrating with systems like:

  • Yubikeys (hardware keys)
  • Windows Hello
  • OS X Face ID

It would be great to have this as a 2FA option. But ideally this would be done after #26 to make it a bit easier to add this to the existing interface.

Rename 'users' to 'principals'

Given that a 'user' can be a 'user', 'app' or in the future also 'group', I think we should switch to a more generic name for this.

I would like to rename all 'users' apis to 'principals'. Almost everything else can remain the same.

When we do this, we should not remove the 'users' API. Instead, mark it as deprecated. We can do the removing of this API later, but this means that for a while we will have both a 'users' and a 'principals' API that are (mostly) identical.

Add a HTML registration form

Allow new users to register.

First steps:

  1. Add a link from the 'home document' to /register
  2. Add an exception to the authentication middleware to allow access to /register without login
  3. Create a new route for /register
  4. Create a new controller : /src/register/controller.ts
  5. Create a method in the controller get()
  6. Render a HTML form

Make 2FA code optional

If a user does not have a 2FA code set in the database, allow the user to log in without the 2FA code.

What has to be changed?

  • The login form has to no longer have the 'required' attribute on the TOTP form field
  • Add some text to the login form that says: TOTP token (if set)
  • When logging in, if the user did not supply a TOTP token, check if the user has a TOTP token set.
    • If not, log the user in.
    • If they do, return a new error "TOTP token required"

Authentication mode not supported MySQL 8.0.16

Running into an issue using the latest mysql version, something may have been deprecated or requires additional configuration beyond default configuration to support a12n-server out of the box.

So this may end up just be an update to documentation.

Tested on MySQL 5.7.26 and works fine.
Tested on MySQL 8.0.16 (via docker) and received the following error:

    at PromisePool.query (/home/mihok/development/src/github.com/savearthdigital/auth-api/node_modules/mysql2/promise.js:322:22)
    at Object.query (/home/mihok/development/src/github.com/savearthdigital/auth-api/node_modules/a12n-server/dist/database.js:20:34)
    at process._tickCallback (internal/process/next_tick.js:68:7)
  message:
   'Client does not support authentication protocol requested by server; consider upgrading MySQL client',
  code: 'ER_NOT_SUPPORTED_AUTH_MODE',
  errno: 1251,
  sqlState: '08004',
  sqlMessage:
   'Client does not support authentication protocol requested by server; consider upgrading MySQL client' }

Re-do the login form to make the 2FA token input a 'second step'

Right now the login form has 3 fields:

  1. Username
  2. Password.
  3. TOTP (google authenticator code)

In the future we want to support the following cases as well:

  1. TOTP is disabled, so there is no TOTP setup
  2. Alternative forms of 2FA
  3. WebAuthN (yubikey and such).

To do this effectively, what should happen is that the login screen just has a username + password field. After these are filled in, the user gets redirected and prompted for their TOTP code.

Lost password functionality

This feature is already underway, but will add a bit of a specification here (for the bits that are not already known).

Steps:

  1. User clicks 'forgot password'
  2. User fills in their email address
  3. A unique unguessable one-time token gets generated
  4. User receives an email with a link to: https://auth-server.example/reset-password/token/[token]
  5. The session gets updated with a flag that means that the user is now allowed to change their password. For instance: ctx.state.session.resetPassword = userId
  6. User gets redirected to a page where they may change their password. ``https://auth-server.example/reset-password/change-password`
  7. This form sends a POST request to do the actual reset. Both 5 and 6 need to check if the resetPassword session information is set.
  8. After the password is changed, remove the session tokens and redirect the user to the login page.

Make the TOTP code optional

This relates to #26 and might have to be done in conjunction?

If a user does not have a TOTP code, they should not be asked for it.

Use a standard JWT token format

The JWT tokens that we use right now don't make that much sense. They should really be based on a standard format.

OpenID Connect has a standard format with tons of default claims. It would be good first step towards OpenID connect to add some of their claims.

Someone else has written a separate RFC draft. This is not standard yet, but it could be a good starting point given that they're re-using OpenID claims and summarizing some stuff that is otherwise spread out over many OpenID Connect documents.

https://tools.ietf.org/html/draft-bertocci-oauth-access-token-jwt-00

Reset 2FA code interface

We should have an interface where people can generate a new 2FA code.

This system should store the new code and could show

  • The 2FA recovery code
  • A QR code

If the user already had a 2FA code setup, the user should be required to re-enter that before generating a new one.

Kill active sessions

A user should be able to kill an active session by issuing a DELETE request on a session resource.

This tickets depends on #37

Store session data in MySQL

Currently all sessions are stored in a memory-engine, which means:

  1. If the server restarts, all sessions expire.
  2. If multiple servers are started, they can't share sessions

As big step forward, we would want to store sessions in MySQL.

This means a new 'storage engine' will have to be written for this session data. This should be done in this github project:

https://github.com/curveballjs/session

Show 'country' in Audit Log API

We have an ip for every entry in the audit log, but it would be nice if we can automatically map this to a country.

This is only really a good idea if we can get a good free ip-to-country database we can integrate.

Support for invitations

Currently we don't have invitation functionality in the system.

It needs to have 2 things:

  1. When the non-existing user wants to have an account within the system, group owner/user will be able to send an invitation for the user to sign up
  2. Group to be able to inviting an existing user who's not part of any group to be part of a specific group,

Successful notifications are stylized as errors

When a user successfully requests to reset their password, they are met with a notification that looks more like an error. It's red and it has an alert symbol.

Lets fix this. This is partially a @ikbensiep thing for updating the style and a @juhangsin for updating the code.

I think the easiest way to handle this is that right now we have a ?msg= query parameter. Perhaps we can just add an ?error= query parameter and have each be styled appropriately.

Add support for a new user/principal type

Currently in our database we have 2 types of 'users'.

  1. user
  2. app

We should add a third type:

  1. group.

The scope of this task is only to allow a new type of user (type 3), nothing else.

When the server can't connect to MySQL, it tells the user that their password is wrong

This is a bad user experience, because it seems like their password was incorrect, but the log shows the real error.

Instead it should throw a real exception.

The exception that should be thrown is BadGateway.

Steps to reproduce:

  1. Start server
  2. Turn off mysql
  3. Try logging in
  4. Look at the log.

The reason the real mysql exception gets turned into a "Incorrect Username or Password" is because all exceptions are being caught in /src/login/controller.ts

Deadlocks in oauth2_tokens table

DELETE FROM oauth2_tokens WHERE access_token = 'Jvwx696fU9v5gZbSh6/SEvPMqGPiw9BuKRoMTueLnoc'
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 128 page no 10 n bits 368 index access_token of table auth.oauth2_tokens trx id 38755 lock_mode X locks rec but not gap
Record lock, heap no 266 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 30; hex 4a7677783639366655397635675a625368362f534576504d714750697739; asc Jvwx696fU9v5gZbSh6/SEvPMqGPiw9; (total 43 bytes);
1: len 4; hex 00000308; asc ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 128 page no 10 n bits 368 index access_token of table auth.oauth2_tokens trx id 38755 lock_mode X waiting
Record lock, heap no 266 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 30; hex 4a7677783639366655397635675a625368362f534576504d714750697739; asc Jvwx696fU9v5gZbSh6/SEvPMqGPiw9; (total 43 bytes);
1: len 4; hex 00000308; asc ;;

Step one is probably doing better garbage collection on this table, so it's too small for this to regularly happen.

Reset password interface

Users should be able to reset their own password. If they have 2FA setup, they should be required to re-enter that code.

OpenID Connect support

This list is non-exhaustive, adding todos here as I realize what needs to be done.

  • #428
  • #434
  • #435
  • Add a permission screen that explicitly asks a user if they want to allow an app to gain access to certain scopes. This should also introduce the concept of a 'trusted app' that insta-gains all the requested scopes.
  • Track which scopes were requested for an access token, (so when an access token is refreshed, that next access token has the same set of scopes).
  • oidc discovery document.
  • id token support.
  • userinfo endpoints support.
  • Support for prompt in authorize request.
  • Support for max_age in authorize request.
  • Support for ui_locales in authorize request.
  • Support id_token_hint in authorize request.
  • Support login_hint in authorize request.
  • Support acr_values in authorize request.
  • Support "claims"

Force reset password on next login

There should be a flag on user accounts that forces the user to create a new password the next time they login. This can for example be used when an admin sets up a new user account and gives them a temporary password.

This is probably easier to do after #26 and #34

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.