Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AccountsJS Improvements #181

Open
11 of 12 tasks
Aetherall opened this issue Mar 13, 2018 · 2 comments
Open
11 of 12 tasks

AccountsJS Improvements #181

Aetherall opened this issue Mar 13, 2018 · 2 comments

Comments

@Aetherall
Copy link
Member

Aetherall commented Mar 13, 2018

As you can see, I have been doing some work on the repo

The instanciation i would like to achieve is this one (collapse)

/*
  >=> ========================= >=>
      ACCOUNTS-JS SETUP EXAMPLE
  >=> ========================= >=>
*/

// ============================= ==>
// >=> import Accounts-Js packages
// ============================= ==>



// =================================================
// Accounts Server => Core
// Permit to tie all packages together

import AccountsServer from '@accounts/server';


// =================================================
// Accounts Mongo => Database Interface
// Provides Access to a database

import MongoInterface from '@accounts/mongo';


//==================================================
// Transport Express => Network Interface
// Provides the Express middleware connecting your express application to Accounts-JS

import TransportExpress from '@accounts/express';


//==================================================
// Token Transport Express Headers => Token Storage
// Defines the way to store the tokens while sending them to the client 

import TokenTransportExpressHeaders from '@accounts/express-token-headers';   // Headers => Store in request headers
import TokenTransportExpressCookies from '@accounts/express-token-cookies'; // Cookies => Store in request cookies
import TokenTransportExpressBody from '@accounts/express-token-body';       // Body    => Store in request body


//==================================================
// Token Transport Manager => Token Storage 
// Allow multiple TokenTransport

import TokenTransportManager from '@accounts/token-transport-manager';


// =================================================
// Password Service => Authentication By Password

import PasswordService from '@accounts/password';


// =================================================
// Email Service => Email Sender Service
// Provide an Interface to send emails

import EmailService from '@accounts/email-debug';     // Email Debug   => console.log
//import EmailService from '@accounts/email-mailgun'; // Email Mailgun => mailgun sender



// =================================================
// Email Plugin Password => Email Notification Service Plugin for Password Authentication
// Provide a set of email templates to an Email Service

import EmailPluginPassword from '@accounts/email-plugin-password';


// =================================================
// TokenManager => JWT Management
// Generate and decode accessTokens and refreshTokens

import TokenManager from '@accounts/token';



// ================= ==>
// >=> instanciation
// ================= ==>



// >=> Database Interface

// Get a Mongo Database Object or a Promise returning one
import Connection from './connection';

// Create the Database Interface
const databaseInterface = new MongoInterface(Connection);




// >=> Transport

// Select a way to store tokens
const tokenTransportHeaders = new TokenTransportExpressHeaders()
const tokenTransportCookies = new TokenTransportExpressCookies({
  access:{
    secure: false,
    httpOnly: false,
    domain: 'localhost',
    sameSite: false,
  },
  refresh:{
    secure: false,
    httpOnly: false,
    domain: 'localhost',
    sameSite: false,
  }
})
const tokenTransportBody = new TokenTransportExpressBody()

// If multiple token transport selected, the Token Transport Manager must be used 
const tokenTransport = new TokenTransportManager(tokenTransportHeaders, tokenTransportCookies, tokenTransportBody)


// Build the transport 
const transport = new TransportExpress({

  tokenTransport,

})

// Extract the authentication middleware and export it to consume it on express
export const authMiddleware = transport.middleware;

//extract the accounts router and export it to consume it on express
export const accountsRouter = transport.router;

// >=> Authentication

// instanciate your authentication services
const passwordService = new PasswordService();




// >=> Notification

// instanciate the notification plugins needed to provide notification support to authentication services
const emailPluginPassword = new EmailPluginPassword();

// instanciate your notifications services
const emailService = new EmailService({

  notificationPlugins: [ emailPluginPassword ]

})




// >=> Token Manager

// instanciate the Token Manager
const tokenManager = new TokenManager({

  secret: 'e'

});


// ================= ==>
// >=> Accounts Server
// ================= ==>

const accountsServer = new AccountsServer({
  
    databaseInterface,
  
    transport,
  
    tokenManager,
  
    authenticationServices: [ passwordService ],
  
    notificationServices: [ emailService ]
  
})

@Aetherall Aetherall changed the title AccountsJS 0.2 ? AccountsJS Improvements Mar 13, 2018
@Aetherall
Copy link
Member Author

Flow Ideas

The actions made by accountsJS can be split into 3 categories

  • The ANONGUY want to Authenticate => get tokens

    • via password
    • via code sent on phone
    • via gpg
    • via oauth
      • via twitter
      • via google
    • via MFA
      • password and code
      • password and code and gpg
  • The KNOWNGUY want to use the authorization of his tokens

    • Impersonate
    • get session
    • logout
    • reset Password
    • send Enroll Email
    • send Verify Password Email
    • unlink OAuth
  • The ANONGUY want to execute actions which doesn't need rights

    • send Reset Password Email
    • register

So in my opinion we need to change the way the suite works.

The current way of doing things limit the "multistep" behavior of modern authentication methods

In the case of just using the authorization, we just have to get the DBUser from the DB via tokens, and then apply dev defined "verifyFunctions" as we does for impersonating

In the case of authorization, we should first identify the ANONGUY

// it could be :
const input = {
	identity: {
		email: '[email protected]',
	}
}
// or :
const input = {
	identity: {
		username: 'aaaaaa',
	}
}
// or even :
const input = {
	identity: {
		userId: 25,
		username: 'aaaaaa'
	}
}

Well, any information able to identify the ANONGUY

Then we use thoses informations to retrieve the DBUser from database

Now, in order to identify the ANONGUY, we should read on the DBUser the authentication requirements

const DBUser = {
	requirements: {
		AND: ['password', 'code']
	}
}

const DBUser = {
	requirements: [
		{ OR: ['password', 'facebook', 'twitter'] },
		'code'
	]
}

Then, we should provide a way to incrementally satisfy the requirements, and I propose to do this by using the session.

See the auth chart for details on the flow : https://drive.google.com/file/d/1k9SAoqx7RLiF-1RNH0beOmtkUPQCeztc/view?usp=sharing

Also, An authentication Service should provide a way to identify an user

For now, each time we want to add such a way, we need to add a corresponding database function. In the future maybe it will be appropriate to provide a plugin API in our DatabaseInterfaces, but It seems inappropriate now.

So let's say we want to add a service able to identify the user with 'shortId'

We would have to add the findUserByShortId method to the databaseInterfaces, of course, but in order for the identification method on the AccountsServer to be able to recognize an user by it's shortId, we would just have to add a public object to the class:

const input = {
	identity: {
		shortId: 14
	}
}

class ShortIdService implements AuthenticationService {
	public identificationMethods = { shortId: 'findUserByShortId' }
}

Then, the accountsServer identify method should interpret the presence of shortId as a need to use the findUserByShortId function on the databaseInterface.

With this method, we allow the use of any combination of authenticationServices but we also simplify the development of the authenticationServices themselves

@TimMikeladze
Copy link
Member

@Aetherall

  1. Totally agree about the need of multi steps for authentication.
  2. The identification method design looks good to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants