@tailored-apps/keyhole
v2.6.3
Published
gatekeeper oauth2 server companion library
Downloads
46
Readme
keyhole
gatekeeper oauth2 server companion library
Token Verification
The tokenVerification
factory returns an async function that can be used to verify that a provided token is valid (i.e. it has been issued, has not revoked and is not expired). This function will throw a 401
HTTP error if the provided token is invalid, and it will do nothing for valid tokens.
API
tokenVerification ({ baseUrl, verifyEndpoint }) -> Function
baseUrl
gatekeeper base URLverifyEndpoint
(optional) Endpoint used for token verification (defaults to/oauth/verify
)
The function returned by this factory has the following API:
verifyToken(token, requiredScopes) -> void
token
Access tokenrequiredScopes
(optional) List of scopes the token needs to have in order to be considered valid
Example
import { tokenVerification } from 'keyhole'
export const tokenVerificationMiddleware = () => {
const verifyToken = tokenVerification({ baseUrl: 'https://gatekeeper.tailored-apps.com' })
return async (ctx, next) => {
const [ , token ] = ctx.get('authorization').split(' ')
// If you just need to make sure the token is valid
await verifyToken(token)
// or, if you also need to verify the scope:
await verifyToken(token, [ 'required_scope', 'second_required_scope' ])
// We now know the token is valid, continue
return next()
}
}
Token Introspection
The tokenIntrospection
factory returns an async function that can be used for introspecting arbitrary tokens. The returned function accepts only one parameter - the token which will be sent to the gatekeeper API for introspection.
As per RFC 7662, the introspection endpoint will return a 200 OK
HTTP response for both valid and invalid tokens. Invalid (i.e. revoked, expired or non existing) tokens will always produce the same response: { active: false }
.
API
introspection ({ baseUrl, clientId, clientSecret, requiredScopes, introspectEndpoint }) -> Function
baseUrl
gatekeeper base URLclientId
Client ID used inclient_credentials
authenticationclientSecret
Client secret used inclient_credentials
authenticationintrospectEndpoint
(optional) Endpoint used for introspection (defaults to/oauth/introspect
)
Example
import { tokenIntrospection } from 'keyhole'
const token = 'asdf-foo-bar'
const introspect = tokenIntrospection({
baseUrl: 'https://gatekeeper.tailored-apps.com',
clientId: 'my-api-client-id',
clientSecret: 'my-client-secret'
})
introspect(token)
.then((data) => console.dir(data))
/*
->
{
active: true,
accessToken: 'asdf-foo-bar',
accessTokenExpiresAt: '2017-07-18T13:01:30.016Z',
scope: 'authenticate_user',
clientId: 'my-api-client-id',
user: {
username: 'emart86',
customProp: 'some value',
anotherCustomProp: 'some other value'
}
*/
Scope Verification
keyhole provides a helper function to verify that a token's scope is a superset of a list of required scopes.
API
verifyTokenScope(tokenScope, requiredScope) -> Boolean
tokenScope
Token scope. Can either be an array or a space separated string.requiredScope
List of scopes the token needs to have. Can either be an array or a space separated string.
Example
import { verifyTokenScope } from 'keyhole'
verifyTokenScope('foo bar baz', 'foo') // -> true
verifyTokenScope('foo bar baz', 'foo bar') // -> true
verifyTokenScope('foo bar baz', 'bar foo') // -> true
verifyTokenScope('foo bar baz', 'foo bar qux') // -> false
Middleware
As of v2.0.0
, keyhole
also includes a middleware module which exports various functions that cover common usecases.
tokenVerificationMiddleware
Returns a koa middleware function that will verify a token by reading it from the Authorization
header and subsequently calling the tokenVerification
function (see above).
API
tokenVerificationMiddleware({ logger, baseUrl, verify, requiredScopes, verifyEndpoint }) -> Function
logger
(optional) winston compatible logger object (defaults to console logging)verify
(optional) function that will be called to verify the token (defaults totokenVerification({ baseUrl, verifyEndpoint })
)
See tokenVerification
API docs for baseUrl
, requiredScopes
and verifyEndpoint
parameter explanations.
tokenIntrospectionMiddleware
Returns a koa middleware function that will introspect a token (which is read from the Authorization
header) and store it's data in ctx.state
. If the token fails introspection (i.e. if active === false
), the token will be passed to the verify
function, which will throw an appropriate error. Therefore, this middleware does not need to be used in conjunction with tokenVerificationMiddleware
but should be used instead of it if token introspection data is needed at some point in the request.
This function can also verify a token's scope by comparing it against a list of requiredScopes
. Since token data will already be in memory at the time of comparison, this will not perform an HTTP request for doing so, but will instead simply call the verifyTokenScope
helper function locally. If in-memory verification fails, verify
will be called and subsequently produce an appropriate error.
API
tokenIntrospectionMiddleware({ statePropName, logger, requiredScopes, baseUrl, clientId, clientSecret, introspect, verify, introspectEndpoint, verifyEndpoint }) -> Function
statePropName
(optional) name of the property inctx.state
that will hold token data (defaults totokenPayload
)logger
(optional) winston compatible logger object (defaults to console logging)requiredScopes
(optional) Array of scopes the token needs to have in order to be considered valid.introspect
(optional) function that will be called to introspect the token (defaults totokenIntrospection({ baseUrl, clientId, clientSecret, introspectEndpoint })
)verify
(optional) function that will be called to verify the token (defaults totokenVerification({ baseUrl, verifyEndpoint })
)
Remaining parameters will be passed to tokenIntrospection
and tokenVerification
factory functions - see documentation for these functions for an explanation of the parameters they expect.
Example
import router from 'koa-router'
import { tokenIntrospectionMiddleware } from 'keyhole'
const router = new Router()
router
.get('/something',
tokenIntrospectionMiddleware({ baseUrl: 'https://gatekeeper-dev.tailored-apps.com', clientId: 'someClient', clientSecret: 'secret' }),
(ctx, next) => {
console.dir(ctx.state.tokenPayload)
return next()
}
)