Middleware to support JWT audience role for SakuraApi servers
Middleware to support JWT audience role for SakuraApi servers
Include this as a plugin when instantiating SakuraApi
. For example:
const authAudienceOptions = {
// see: IAuthAudienceOptions for all your options
};
const sapi = new SakuraApi({
// ... other stuff
plugins: [
{
options: authAudienceOptions,
order: 1,
plugin: addAuthAudience
}
]
});
npm i @sakuraapi/auth-audience
You’ll need to setup your environment (src/config/environment.ts
, for example) with at least the following:
modules.export = {
authentication: {
jwt: {
audience: "audience.somedomain.somewhere",
issuer: "issuer.somedomain.somewhere",
key: "12345678901234567890123456789012"
}
}
};
The audience
is the identifier for the server on which you are implementing this plugin, it should have also been configured in your auth-native-authority
or auth-oauth-authority
settings.
The issuer
is the identifier of the server that’s providing the JWT credentials.
The key is the shared secret with the issuer. It’s a 32 character key. Remember, if your issuer is supporting multiple audience servers, they don’t have to share the same private keys — in fact, you might not want them to.
This shouldn’t need to be stated: don’t commit your production private keys to your repo. Instead, inject them during deployment. How you do this is beyond the scope of this readme. This, by the way, is why you don’t provide your key via the authOptions
above. By putting it in your config files, you’re able to create a config file for production that takes an environmental variable instead of having the key hard coded.
There will be times when in a multi tenanted environment when you will want to have a server authenticate on those different domains. Each domain will have the 3-tuple of audience
-issuer
-key
. This auth-audience plugin is able to handle multiple domains (i.e., depending on the domain in the JWT, determining if the audience is supported and if the JWT signs correctly with the secret key for that audience given the domain)
jwt: {
domainedAudiences: {
"field": {
audience: "audience1.somedomain.somewhere",
issuer: "issuer1.somedomain.somewhere",
key: "123"
},
"default": {
audience: "audience2.somedomain.somewhere",
issuer: "issuer2.somedomain.somewhere",
key: "456"
}
}
}
auth-audience
exports AuthAudience
. This can be used on your @Routable
api calsses.
Some rules to keep in mind:
[...route-level-authenticators, ...class-level-authenticators]
.
@Routable({
authenticators: [AuthAudience, Anonymous],
baseUrl: 'someapi'
})
class SomeApi {}
(Anonymous
is an authenticator exported by @sakuraapi/api
).
Example 1 subjects all someapi
routes to AuthAudience
. If that fails, then it subjects the request to Anonymous
(which will never fail). If AuthAudience
succeeds, a JWT for the user will be available on res.locals.jwt
(or wherever you put it if you override onAuthorized
in your options).
@Routable({
authenticators: AuthAudience,
baseUrl: 'someapi'
})
class SomeApi {}
Subjects all someapi
routes to AuthAudience
, if that fails the user will get a 401 or whatever you set in your options.
@Routable({
baseUrl: 'someapi'
})
class SomeApi {}
This just lets everything through.
@Routable({
baseUrl: 'someapi'
})
class SomeApi {
@Route({
authenticators: Anonymous
method: 'get',
path: 'handler1'
})
handler1(res, req, next) {
next();
}
@Route({
authenticators: AuthAudience
method: 'get',
path: 'handler2'
})
handler2(res, req, next) {
next();
}
}
Here, someapi/handler1
route is Anonymous and will let anyone through. someapi/handler2
route is subjected to AuthAudience
.
@Routable({
authenticators: AuthAudience,
baseUrl: 'someapi'
})
class SomeApi {
@Route({
authenticators: Anonymous
method: 'get',
path: 'handler1'
})
handler1(res, req, next) {
next();
}
@Route({
method: 'get',
path: 'handler2'
})
handler2(res, req, next) {
next();
}
}
In the above example, all routes would be subjected to AuthAudience
, but someapi/handler1
would override that and let anyone through as Anonymous.
In this case, route someapi/handler1
would not have a JWT injected since Anonymous would be executed before AuthAudience
. Be careful with your ordering.
npm run lint
) to verify you comply with the style guideEveryone should be treated with respect. Though candor is encouraged, being mean will not be tolerated.