- 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
An authorization framework!
- extremely lightweight
- zero dependencies
- compatible with express
- RESTful design
- easy use with openid and oauth 2.0
- easy to customize
- 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
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;
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
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
- 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')
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) => {
//...
}
globalLoginVerify
:the global login verify functionglobalAuthVerify
:the global auth verify functionthrowUnauthorizedError
:should throw error when unauthorized-error occurs otherwise kkk just only setreq.unauthorizedError
- UnauthorizedError ⇐
Error
A Unauthorized Error
- KnockKnockKnock
knock-knock-knock main class
Kind: global interface
Ee: ./doc/examples/all-schema.js
a schema must implement one of the interface's methods
Kind: static interface of schemaInterface
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 |
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 |
if the schema implemented this interface , it is able to use [schemaFunctions] to call this function in schema
Kind: static interface of schemaInterface
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 |
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 |
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 |
if the schema implemented this interface , it is able to use [schemaFunctions] to call this function in schema
Kind: static interface of schemaInterface
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 |
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 |
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 |
A Unauthorized Error
Kind: global class
Extends: Error
- UnauthorizedError ⇐
Error
Kind: instance property of UnauthorizedError
Kind: instance property of UnauthorizedError
knock-knock-knock main class
Kind: global class
Ee: ./doc/examples/newKKK.js
Param | Type |
---|---|
[option] | Option |
check able to work available to work. it won't return true until least one login-schema are enabled
Kind: instance property of KnockKnockKnock
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);
disable a schema
Kind: instance method of KnockKnockKnock
Param | Type | Description |
---|---|---|
id | string |
schema id |
Example
kkk.disable('test');
Kind: instance method of KnockKnockKnock
Todo
- implement this
Param |
---|
router |
authenticate a request
Kind: instance method of KnockKnockKnock
Ee: ./doc/examples/knockLogin.js
Param | Type | Default | Description |
---|---|---|---|
[id] | string |
null |
schema id |
[option] | actionOptions |
{} |
authorize a request
Kind: instance method of KnockKnockKnock
Ee: ./doc/examples/knockAuth.js
Param | Type | Default | Description |
---|---|---|---|
[id] | string |
null |
schema id |
[option] | actionOptions |
{} |
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 |
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 |
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 |
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 |
MIT