I'm looking for an answer to best practices for this solution. I have an IOT project im working on that requires authentication on two paths. User and device.
What I am attempting to do is have full control over route authentication separately on user and device so i thought that creating two separate JWT services would be appropriate.
Feathers: 4.5.8 My authentication Service looks like this
export default function (app: Application): void {
const deviceAuthentication = new DeviceAuthService(app, 'device-authentication');
deviceAuthentication.register('device-jwt', new DeviceJWTStrategy());
deviceAuthentication.register('device', new DeviceStrategy());
const authentication = new AuthService(app, 'authentication');
authentication.register('jwt', new JWTStrategy());
authentication.register('local', new LocalStrategy());
app.use('/device-authentication', deviceAuthentication);
app.use('/authentication', authentication);
app.configure(expressOauth());
}
//hooks /someapi
{before:{ get: [authenticate('device-jwt')]}
//config
"device-authentication": {
"entity": "device",
"service": "devices",
"secret": "***",
"authStrategies": [
"device-jwt",
"device"
],
"device": {
"usernameField": "uuid",
"altUsernameField": "email",
"passwordField": "password"
},
"jwtOptions": {
"header": {
"typ": "access"
},
"audience": "https://something.com",
"issuer": "feathers",
"algorithm": "HS256",
"expiresIn": "1d"
}
},
"authentication": {
"entity": "user",
"service": "users",
"secret": "*****",
"authStrategies": [
"jwt",
"local"
],
"jwtOptions": {
"header": {
"typ": "access"
},
"audience": "https://somthing.com",
"issuer": "feathers",
"algorithm": "HS256",
"expiresIn": "1d"
},
"local": {
"usernameField": "email",
"passwordField": "password"
},
"oauth": {
"redirect": "/",
"auth0": {
"key": "<auth0 oauth key>",
"secret": "<auth0 oauth secret>",
"subdomain": "<auth0 subdomain>"
},
"google": {
"key": "<google oauth key>",
"secret": "<google oauth secret>",
"scope": [
"email",
"profile",
"openid"
]
},
"facebook": {
"key": "<facebook oauth key>",
"secret": "<facebook oauth secret>"
},
"twitter": {
"key": "<twitter oauth key>",
"secret": "<twitter oauth secret>"
},
"github": {
"key": "<github oauth key>",
"secret": "<github oauth secret>"
}
}
},
The problem I am running into is that when i use GET on users, I expect to authenticate on the jwt strategy for the /authentication service. Debugging says i am parsing to the jwt strategy but get a result as see here
Invalid authentication information (strategy not allowed in authStrategies)
the jwt strategy attempted in debug is "device-jwt"
if Swap the service functions to
export default function (app: Application): void {
const authentication = new SippAuthService(app, 'authentication');
authentication.register('jwt', new JWTStrategy());
authentication.register('local', new LocalStrategy());
const deviceAuthentication = new SippDeviceAuthService(app, 'device-authentication');
deviceAuthentication.register('device-jwt', new DeviceJWTStrategy());
deviceAuthentication.register('device', new DeviceStrategy());
app.use('/device-authentication', deviceAuthentication);
app.use('/authentication', authentication);
app.configure(expressOauth());
}
Just the opposite happens, i will get the same message on the users auth service but it will never reach the device auth service
The error is thrown here
///AuthenticationService.authenticate. node_modules/@feathersjs/authentication/src/core.js (204)
if (!authentication || !authStrategy || !strategyAllowed) {
const additionalInfo = (!strategy && ' (no `strategy` set)') ||
(!strategyAllowed && ' (strategy not allowed in authStrategies)') || '';
// If there are no valid strategies or `authentication` is not an object
throw new NotAuthenticated('Invalid authentication information' + additionalInfo);
}
and as expected strategyAllowed
is false because "jwt" is not allowed in "device-jwt"
Is there a better way to go about this? Is there a way to utilize express next()
functionality to validate the request and pass it to the correct authentication service?