Local Authentication
npm install @feathersjs/authentication-local --save
@feathersjs/authentication-local
provides a LocalStrategy
for authenticating with a username/email and password combination, e.g.
{
"strategy": "local",
"email": "hello@feathersjs.com",
"password": "supersecret"
}
Usage
import { AuthenticationService } from '@feathersjs/authentication'
import { LocalStrategy } from '@feathersjs/authentication-local'
import type { Application } from './declarations'
declare module './declarations' {
interface ServiceTypes {
authentication: AuthenticationService
}
}
export const authentication = (app: Application) => {
const authentication = new AuthenticationService(app)
authentication.register('local', new LocalStrategy())
app.use('authentication', authentication)
}
Options
Options are set in the authentication configuration under the strategy name. Available options are:
usernameField
: Name of the username field (e.g.'email'
), may be a nested property (e.g.'auth.email'
)passwordField
: Name of the password field (e.g.'password'
), may be a nested property (e.g.'auth.password'
)hashSize
(default:10
): The BCrypt salt lengtherrorMessage
(default:'Invalid login'
): The error message to return on errorsentityUsernameField
(default:usernameField
): Name of the username field on the entity if authentication request data and entity field names are differententityPasswordField
(default:passwordField
): Name of the password field on the entity if authentication request data and entity field names are different
Options are usually set under the registered name via Feathers configuration in config/default.json
or config/<environment>.json
:
{
"authentication": {
"local": {
"usernameField": "email",
"passwordField": "password"
}
}
}
LocalStrategy
Note
The methods described in this section are intended for customization purposes and internal calls. They usually do not need to be called directly.
getEntityQuery(query, params)
localStrategy.getEntityQuery(query, params) -> Promise
returns the query for finding the entity. query
includes the usernameField
or entityUsernameField
as { [field]: username }
and by default returns a promise that resolves with { $limit: 1 }
combined with query
.
findEntity(username, params)
localStrategy.findEntity(username, params) -> Promise
return the entity for a given username and service call parameters. It will use the query returned by getEntityQuery
and call .find
on the entity (usually /users
) service. It will return a promise that resolves with the first result of the .find
call or throw an error if nothing was found.
getEntity(entity, params)
localStrategy.getEntity(authResult, params) -> Promise
returns the external representation for entity
that will be sent back to the client.
hashPassword(password)
localStrategy.hashPassword(password) -> Promise
creates a safe one-way hash of the given plain password
string. By default bCryptJS is used.
comparePassword(entity, password)
localStrategy.comparePassword(entity, password) -> Promise
compares a plain text password
with the hashed password of the entity
returned by findEntity
. Returns the entity
or throws an error if the passwords don't match.
authenticate(authentication, params)
localStrategy.authenticate(authentication, params)
is the main endpoint implemented by any authentication strategy. It is usually called for authentication requests for this strategy by the AuthenticationService.
Customization
The LocalStrategy
can be customized like any ES6 class and then registered on the AuthenticationService:
import type { Application, Params, Query } from '@feathersjs/feathers'
import { AuthenticationService, JWTStrategy } from '@feathersjs/authentication'
import { LocalStrategy } from '@feathersjs/authentication-local'
class MyLocalStrategy extends LocalStrategy {
async getEntityQuery(query: Query, params: Params) {
// Query for use but only include `active` users
return {
...query,
active: true,
$limit: 1
}
}
}
export default (app: Application) => {
const authService = new AuthenticationService(app)
authService.register('local', new MyLocalStrategy())
// ...
app.use('/authentication', authService)
}
Helpers
Protecting fields
As of Feathers v5, external resolvers using the schemaHooks.resolveExternal
hook are the preferred method to hide or change fields for external requests. The following will always hide the user password for external responses and events:
import { resolve, schemaHooks } from '@feathersjs/schema'
export const userExternalResolver = resolve<User, HookContext>({
properties: {
// The password should never be visible externally
password: async () => undefined
}
})
app.service('users').hooks({
after: {
all: [schemaHooks.resolveExternal(userExternalResolver)]
}
})
passwordHash
The passwordHash
utility provides a property resolver function that uses a local strategy to securely hash the password before storing it in the database. The following options are available:
strategy
- The name of the local strategy (usually'local'
)service
- The path of the authentication service (will useapp.get('defaultAuthentication')
by default)
export const userDataResolver = resolve<User, HookContext>({
properties: {
password: passwordHash({ strategy: 'local' })
}
})
hashPassword(field)
The hashPassword
hook is provided for Feathers v4 backwards compatibility but has been deprecated in favour of the passwordHash resolver.
protect(...fields)
The protect
hook is provided for Feathers v4 backwards compatibility but has been deprecated in favour of external data resolvers.