Note: this plugin is for hapi v17+
This authentication package was inspired by hapi-auth-bearer-token and hapi-auth-jwt2
hapi-now-auth takes care of verifying your JWTs or bearer tokens. We will try to provide the best documentation possible, but reachout should you need help.
You can add the plugin to you project using npm or yarn:
npm:npm i @now-ims/hapi-now-auth
yarn:yarn add @now-ims/hapi-now-auth
This plugin creates a hapi-now-auth
authentication scheme with the following options:
validate
- (required) your validation function with[async] function(request, token, h)
where:request
is the hapi request objecttoken
if (verifyJWT === false)
- the auth token received from the client
if (verifyJWT === true)
- object
{ decodedJWT, token }
- object
h
the hapi response toolkit- Response
{ isValid, credentials, artifacts }
where:isValid
true ifJWT
orBearer
token is validcredentials
an object passed back to your application inrequest.auth.credentials
artifacts
optional related data
options
(Optional)accessTokenName
- (Default:'authorization'
, Type:string
)allowQueryToken
- (Default:false
, Type:boolean
)allowCookieToken
- (Default:false
, Type:boolean
)allowMultipleHeaders
- (Default:false
, Type:boolean
) - accept multiple headers, e.g., Authorization Bearer <token>; Authorization JWT <token>tokenType
- (Default:Bearer
, Type: string) - accept a custom token type e.g., Authorization JWT <token>allowChaining
- (Default:false
, Type:boolean
) - permit additional authentication strategiesunauthorized
- (Default: Boom.unauthorized, Type:function
) - e.g.,function(message, scheme, attributes)
verifyJWT
- (Default:false
, Type:boolean
) - verify and decode JWT (note:validate
function will need to accept object of{ decodedJWT, token }
)keychain
- (Required if verifyJWT:True
, Type:array[string]
) - an array of your secret keysverifyOptions
- (Optional, Type:object
)algorithms
- (*Default:['HS256']
, Type:array
)audience
- (Optional, Type:array
) - if you want to check the audienceaud
supply an array to be checkedissuer
- (Optional, Type:array
) - array of strings of valid values for iss fieldignoreExpiration
- (Default:false
, Type:boolean
) - ignoreexp
ignoreNotBefore
- (Default:false
, Type:boolean
) - ignorenbf
subject
- (Optional, Type:string
)clockTolerance
- (Optional, Type:integer
) - number of seconds to tolerate when checkingnbf
orexp
claims. note: assists with minor clock differencesmaxAge
- (Optional, Type:string
) - maximum allowed age for tokens to still be valid - e.g.,2 days
,1 hour
,15m
clockTimestamp
- the time in seconds that should be used as current time for all necessary comparisons
const Hapi = require('hapi');
const HapiNowAuth = require('@now-ims/hapi-now-auth');
// create your hapi server
const server = Hapi.server({ port: 8000 });
// Start server function
async function start() {
// register hapi-now-auth plugin
try {
await server.register(HapiNowAuth);
} catch (error) {
console.error(error);
process.exit(1);
}
server.auth.strategy('jwt-strategy', 'hapi-now-auth', {
verifyJWT: true,
keychain: [process.env.SECRET_KEY],
validate: async (request, token, h) => {
let isValid, artifacts;
/**
* we asked the plugin to verify the JWT
* we will get back the decodedJWT as token.decodedJWT
* and we will get the JWT as token.token
*/
const credentials = token.decodedJWT;
/**
* return the decodedJWT to take advantage of hapi's
* route authentication options
* https://hapijs.com/api#authentication-options
*/
/**
* Validate your token here
* For example, compare to your redis store
*/
redis.get(token, (error, result) => {
if (error) {
isValid = false;
artifacts.error = error;
return { isValid, credentials, artifacts };
}
isValid = true;
artifacts.info = result;
return { isValid, credentials, artifacts };
});
},
});
server.auth.default('jwt-strategy');
server.route({
method: 'GET',
path: '/',
handler: async (request, h) => {
return { info: 'success!' };
},
options: {
auth: false,
},
});
server.route({
method: 'GET',
path: '/protected',
handler: async (request, h) => {
return { info: 'success if JWT is verified!' };
},
});
server.route({
method: 'GET',
path: '/admin',
handler: async (request, h) => {
return { info: 'success if JWT is verified and scope includes admin' };
},
options: {
auth: {
scope: 'admin',
},
},
});
try {
await server.start();
} catch (error) {
console.error(error);
process.exit(1);
}
console.log(`Server running at: ${server.info.uri}`);
}
// Don't worry be hapi
start();
This project is kindly sponsored by Now IMS
Licensed under MIT