Authentication Middleware for Expresso
Install:
$ npm i @expresso/auth
Import and use:
import expresso, { IExpressoConfigOptions } from '@expresso/app'
import auth, { IAuthConfig } from '@expresso/auth'
import server from '@expresso/server'
interface IAppConfig extends IAuthConfig, IExpressoConfigOptions {}
const appFactory = expresso((app, config: IAppConfig, environment) => {
const { jwt, scope, types } = auth.factory(config)
app.get('/', jwt, types('client'), scopes('namespace:your-scope'), routeHandler)
})
const options = {
name: 'myApp',
jwt: {
algorithms: ['HS256'],
audience: 'your-audience',
issuer: 'your-issuer',
secret: 'shhhhh'
}
}
server.start(appFactory, options)
Since expresso is an opinionated framework, you must use an URN in the format urn:type:description
for the subject private claim in the JWT
The middleware can check if a subject is from a determined type by using the types('type')
middleware. It'll parse the URN and check if the types are matching, if not, the user will not be authorized.
The auth middleware takes an option object as configuration. This object is as follows:
export interface IAuthConfig {
jwt: {
audience: string
issuer: string
algorithms?: string[]
secret?: string
},
jwks?: {
uri: string
cache?: boolean
rateLimit?: boolean
requestPerMinute?: number
}
}
The JWT object is required. There's also more than one way to secret your token, this is either with a string secret or a JWKS URI. If the secret is provided, then the JWT string secret will be used. However if you provide the middleware with the jwks
key and a uri
property then the middleware will request this URI to find the token.
This middleware supports scopes. This means you can restrict your token to explicit permission levels using the scopes
public claim in your JWT token:
{
"sub": "yourSubject",
"name": "John Doe",
"iat": 1516239022,
"scope": "namespace:your-scope"
}
The scope
can be either a string or an Array. But it'll only validate if your determined scope is equal to the string or if it is included in the array.
You can perform wildcard validation using the
*
keyword as long as your scope separator is.
, for instance,users.*
will match all the scopes within theusers
namespace, butusers:*
won't.
You can match several scopes using the or
and and
keywords.
app.get('/', scopes.or(['users.read', 'admin.write']), routeHandler)
Will return true
if either the users.read
or admin.write
is present in the scope
public claim.
app.get('/', scopes.and(['users.read', 'admin.write']), routeHandler)
Will return true
if both the users.read
and admin.write
is present in the scope
public claim.
If you return any other properties that are not in the original JWT spec (like, an email or any other). Auth will put them into customProperties
in the req.user
object. Therefore you can access your defined properties as req.user.customProperties.yourProperty
.