knock-knock-knock
v1.0.0
Published
An authorization framework!
Downloads
3
Readme
TOC
- KKK abbr. knock-knock-knock
- Description
- Install
- Example
- Custom Schemas
- More Specific
- Interface
- options
- API
- Classes
- Functions
- Interfaces
- schemaInterface
- UnauthorizedError ⇐ Error
- KnockKnockKnock
- new KnockKnockKnock([option])
- knockKnockKnock.valid ⇒ boolean
- knockKnockKnock.enable(id, schema, setDefault)
- knockKnockKnock.disable(id)
- knockKnockKnock.lazy(router)
- knockKnockKnock.knockLogin([id], [option])
- knockKnockKnock.knockAuth([id], [option])
- knockKnockKnock.[schemaFunctions](id, options)
- KnockKnockKnock~Option
- KnockKnockKnock~actionOptions
- userVerifyFunction(req, res)
- License
KKK abbr. knock-knock-knock
Description
An authorization framework!
Features
- extremely lightweight
- zero dependencies
- compatible with express
- RESTful design
- easy use with openid and oauth 2.0
- easy to customize
Install
- yarn:
yarn add knock-knock
# install needed schemas
# yarn add knock-google-openid
# yarn add knock-jwt-schema
- npm:
npm install knock-knock
# install needed schemas
# npm install knock-google-openid
# npm install knock-jwt-schema
Example
basic example
let express = require('express');
let app = express();
app.use(express.json());
const KKK = require('../');
const kkk = new KKK({});
const schemaForKKK=require('./test-schema');
kkk.enable('test',schemaForKKK ,true);
app.post('/login', kkk.knockLogin('test'), (req, res, next) => {
res.send('okay');
});
module.exports = app;
a full example for google open-id login and jwt auth
let express = require('express');
let cookieParser = require('cookie-parser');
let app = express();
app.use(express.json());
app.use(cookieParser('yijiang'));
app.use(express.urlencoded({extended: false}));
const KKK = require('knock-knock-knock');
let kkk = new KKK();
let googleSchemaClass = require('knock-google-openid');
let jwtSchemaClass = require('knock-jwt-schema');
// openid discovery method
googleSchemaClass.discovery().then((googleSchema) => {
kkk.enable('google', googleSchema);
kkk.enable('jwt', new jwtSchemaClass({secret: 'top-secret'}));
}).catch((err) => {
console.error(err);
});
// oauth request step
app.get('/login', kkk.oauthLogin('google', {
authSession: true,
authSchemaID: 'jwt'
}));
// oauth callback step
app.get('/oauthcallback', kkk.knockLogin('google'), (req, res) => {
if (req.user) {
res.send(req.user);
}
});
// jwt authorization
app.get('/dashboard', kkk.knockAuth('jwt'), (req, res) => {
if (req.user) {
res.send(req.user);
}
});
app.use(function (err, req, res, next) {
//deal with KKK's error
if (err instanceof KKK.UnauthorizedError) {
console.error(err);
res.status(err.status).send(err);
} else {
res.status(500).send('interal error');
}
})
module.exports = app;
Custom Schemas
in KKK there is two types of schema: login
and auth
.
login
schema used as login or authentication. use this to get a login method
app.post('/login', kkk.knockLogin('test'), (req, res, next) => {
res.send('okay');
});
auth
schema used as create/revoke session and authorization. use this to get a auth method
app.get('/dashboard', kkk.knockAuth(), (req, res, next) => {
if (req.user) {
res.send(req.user);
}
});
here is an example: this example show how to implements a schema
module.exports = function () {
//login schema must implement this
this.knockLogin = this.login = async function (req, res) {
//you should check the login request from req
//and must set one of them:
// req.user =...
// or
// req.unauthorizedError = new KnockKnock.unauthorizedError();
};
//auth schema must implement this
this.knockAuth = this.auth = async function (req, res) {
//you should verify a session here...
//and must set one of them:
// req.user =...
// or
// req.unauthorizedError = new KnockKnock.unauthorizedError();
}
//optional for auth schema
this.createSession = async function (req, res) {
}
this.revoke = function (req, res) {
}
//optional for login schema
this.oauthCallback = function (req, res) {
}
this.oauthLogin = function (req, res) {
}
};
every function here has same signature: async func(req,res)
,so you can:
- return a Promise
- use
req
,res
same as express - set
req.user
as user object if login/auth approved - set
req.UnauthorizedError
to aKKK.UnauthorizedError
if login/auth fatal - get
req.user
to verify user info(e.g. query database) because KKK's login schema(e.gknock-password-schema
) only check the request but not verify it. - get
req.user._schemaID
specified which schema created this user object
More Specific
this shows how KKK internal flow
kkk.knockLogin
=>(internal)loginSchema.knockLogin
=>(internal)user `verify` function
=>(internal)authSchema.createSession
kkk.knockAuth
=>(internal)authSchema.knockAuth
=>(internal)user `verify` function
so you have to:
- set
verify
option if you want to verify request when you callkkk.knockLogin/kkk.knockAuth
- specify
createSession
option if you want to create session otherwise it going to be one time authentication/authorization
Interface
- call
kkk.knockLogin(schema)
andkkk.knockAuth(schema)
is the most common way. - if you omit the
schema
option, kkk will try to refer it from client request:
_getParamFromReq(req, param) {
return req.params[param] || req.query[param] || req.cookies[param] || req.body[param];
}
- kkk has shortcuts to directly get schema's methods, so after that you are able to pass it to express: you are able to use these shortcuts to get schema's method
//for login-schemas
kkk.login('test-schema');
kkk.oauthCallback('test-schema');
kkk.oauthLogin('test-schema');
//for auth-schemas
kkk.auth('test-schema');
kkk.revoke('test-schema')
options
verify
set verify
will be called after kkk.knockLogin is called
kkk.knockLogin(
'schema',
{
verify: async (req, res) => {
return await database.query(req.user);
}
}
)
//or set globally...
kkk.option.globalLoginVerify = async (req, res) => {
//...
}
kkk option
globalLoginVerify
:the global login verify functionglobalAuthVerify
:the global auth verify functionthrowUnauthorizedError
:should throw error when unauthorized-error occurs otherwise kkk just only setreq.unauthorizedError
API
Classes
Functions
Interfaces
schemaInterface
Kind: global interface
Ee: ./doc/examples/all-schema.js
schemaInterface.interface
a schema must implement one of the interface's methods
Kind: static interface of schemaInterface
interface.knockLogin(req, res)
must implement for login-schema.
Kind: static method of interface
Ee: ./doc/examples/login-schema.js
| Param | Type | Description |
| --- | --- | --- |
| req | Object | req.user
should be set if user authorized or req.unauthorizedError
should be set if error |
| res | Object | same like express |
interface.knockAuth(req, res)
must implement for auth schema.
Kind: static method of interface
Ee: ./doc/examples/auth-schema.js
| Param | Type | Description |
| --- | --- | --- |
| req | Object | req.user
should be set if user authorized or req.unauthorizedError
should be set if error |
| res | Object | same like express |
schemaInterface.loginOptional
if the schema implemented this interface , it is able to use [schemaFunctions] to call this function in schema
Kind: static interface of schemaInterface
loginOptional.login(req, res)
Kind: static method of loginOptional
| Param | Type | Description |
| --- | --- | --- |
| req | Object | req.user
should be set if user authorized or req.unauthorizedError
should be set if error |
| res | Object | same like express |
loginOptional.oauthLogin(req, res)
Kind: static method of loginOptional
| Param | Type | Description |
| --- | --- | --- |
| req | Object | req.user
should be set if user authorized or req.unauthorizedError
should be set if error |
| res | Object | same like express |
loginOptional.oauthCallback(req, res)
Kind: static method of loginOptional
| Param | Type | Description |
| --- | --- | --- |
| req | Object | req.user
should be set if user authorized or req.unauthorizedError
should be set if error |
| res | Object | same like express |
schemaInterface.authOptional
if the schema implemented this interface , it is able to use [schemaFunctions] to call this function in schema
Kind: static interface of schemaInterface
authOptional.createSession(req, res)
Kind: static method of authOptional
| Param | Type | Description |
| --- | --- | --- |
| req | Object | req.user
should be set if user authorized or req.unauthorizedError
should be set if error |
| res | Object | same like express |
authOptional.auth(req, res)
Kind: static method of authOptional
| Param | Type | Description |
| --- | --- | --- |
| req | Object | req.user
should be set if user authorized or req.unauthorizedError
should be set if error |
| res | Object | same like express |
authOptional.revoke(req, res)
Kind: static method of authOptional
| Param | Type | Description |
| --- | --- | --- |
| req | Object | req.user
should be set if user authorized or req.unauthorizedError
should be set if error |
| res | Object | same like express |
UnauthorizedError ⇐ Error
A Unauthorized Error
Kind: global class
Extends: Error
unauthorizedError.schema
Kind: instance property of UnauthorizedError
unauthorizedError.rawError
Kind: instance property of UnauthorizedError
KnockKnockKnock
knock-knock-knock main class
Kind: global class
Ee: ./doc/examples/newKKK.js
new KnockKnockKnock([option])
| Param | Type | | --- | --- | | [option] | Option |
knockKnockKnock.valid ⇒ boolean
check able to work available to work. it won't return true until least one login-schema are enabled
Kind: instance property of KnockKnockKnock
knockKnockKnock.enable(id, schema, setDefault)
enable a schema knock-knock-knock won't work until at least one login schema is enabled
Kind: instance method of KnockKnockKnock
| Param | Type | Default | Description | | --- | --- | --- | --- | | id | string | | schama id | | schema | schemaInterface | | schema | | setDefault | boolean | false | default use the schema if user won't specify a schema id |
Example
kkk.enable('test',schemaForKKK ,true);
knockKnockKnock.disable(id)
disable a schema
Kind: instance method of KnockKnockKnock
| Param | Type | Description | | --- | --- | --- | | id | string | schema id |
Example
kkk.disable('test');
knockKnockKnock.lazy(router)
Kind: instance method of KnockKnockKnock
Todo
- [ ] implement this
| Param | | --- | | router |
knockKnockKnock.knockLogin([id], [option])
authenticate a request
Kind: instance method of KnockKnockKnock
Ee: ./doc/examples/knockLogin.js
| Param | Type | Default | Description | | --- | --- | --- | --- | | [id] | string | null | schema id | | [option] | actionOptions | {} | |
knockKnockKnock.knockAuth([id], [option])
authorize a request
Kind: instance method of KnockKnockKnock
Ee: ./doc/examples/knockAuth.js
| Param | Type | Default | Description | | --- | --- | --- | --- | | [id] | string | null | schema id | | [option] | actionOptions | {} | |
knockKnockKnock.[schemaFunctions](id, options)
return the functions from schema who implemented the interface loginOptional and authOptional
e.g if a schema which implements oauthLogin it could call knockKnockKnock.oauthLogin(id,option)
Kind: instance method of KnockKnockKnock
Ee: ./doc/examples/KKKLazy.js
| Param | Type | Description | | --- | --- | --- | | id | string | schema id enable | | options | actionOptions | |
KnockKnockKnock~Option
Kind: inner typedef of KnockKnockKnock
Properties
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| [globalLoginVerify] | userVerifyFunction | | the global login verify function |
| [globalAuthVerify] | userVerifyFunction | | the global auth verify function |
| [throwUnauthorizedError] | boolean | true | should throw error when unauthorized-error occurs otherwise kkk just only set req.unauthorizedError
|
KnockKnockKnock~actionOptions
Kind: inner typedef of KnockKnockKnock
Properties
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| verify | userVerifyFunction | | verify function for current user object in req.user
|
| [authSession] | boolean | true | should invoke authSchema to create session after login |
| authSchemaID | string | undefined | | auth-schema id to create session after login. undefined
to use default schema |
userVerifyFunction(req, res)
Kind: global function
Ee: ./doc/examples/kkkverify.js
| Param | Type | Description |
| --- | --- | --- |
| req | Object | req.user
should be set if user authorized or req.unauthorizedError
should be set if error |
| res | Object | same like express |
License
MIT