feathersjs-ecosystem / feathers-authentication-management

Adds sign up verification, forgotten password reset, and other capabilities to local feathers-authentication
https://feathers-a-m.netlify.app/
MIT License
246 stars 98 forks source link

feathers 5 BadRequest: validation failed #213

Closed foxhound87 closed 11 months ago

foxhound87 commented 1 year ago

I'm encountering errors on server when calling create method on client:

 ctx.data { action: 'verifySignupLong', value: '68c675716ca27e69ed972e8dd346eb' }
 error: BadRequest: validation failed
     at UserService.<anonymous> (/usr/src/app/node_modules/@feathersjs/schema/src/hooks/validate.ts:52:27)
     at runMicrotasks (<anonymous>)
     at processTicksAndRejections (node:internal/process/task_queues:96:5)
 error: Data: [
   {
     instancePath: '/verifyToken',
     schemaPath: '#/properties/verifyToken/type',
     keyword: 'type',
nginx_dev  | 172.18.0.1 - - [11/Sep/2023:10:41:24 +0000] "POST /auth-management HTTP/1.1" 400 245 "-" "axios/1.4.0"
     params: { type: 'string' },
     message: 'must be string'
   }
 ]
 error: BadRequest: validation failed
     at UserService.<anonymous> (/usr/src/app/node_modules/@feathersjs/schema/src/hooks/validate.ts:52:27)
     at runMicrotasks (<anonymous>)
     at processTicksAndRejections (node:internal/process/task_queues:96:5)
 error: Data: [
   {
     instancePath: '/verifyToken',
     schemaPath: '#/properties/verifyToken/type',
     keyword: 'type',
     params: { type: 'string' },
     message: 'must be string'
   }
 ]

it happens not only on verifyToken but also with other props when calling other actions, this makes this lib completely unusable. how can it be fixed?

claustres commented 1 year ago

At least in our use case it works in a v5 app, see https://github.com/feathersjs-ecosystem/feathers-authentication-management/issues/211. But we don't have any validation hook, not sure where validation comes from, is it your setup ?

foxhound87 commented 12 months ago

In my setup if I remove schemaHooks.validateData(userPatchValidator) from the users before.patch hook it works.

which is using:

export const userPatchSchema = Type.Partial(userSchema, {
  $id: 'UserPatch'
})
export type UserPatch = Static<typeof userPatchSchema>
export const userPatchValidator = getValidator(userPatchSchema, dataValidator)

my userSchema is:

export const userSchema = Type.Object(
  {
    // _id: ObjectIdSchema(),
    _id: Type.String({ format: 'uuid' }),
    email: Type.String(),
    password: Type.String(),
    // auth mgmt
    isVerified: Type.Boolean(),
    verifyToken: Type.String(),
    verifyTokenShort: Type.String(),
    verifyShortToken: Type.String(),
    verifyExpires: Type.Number(),
    verifyChanges: Type.Optional(Type.Object({})),
    // oauth
    googleId: Type.Optional(Type.String()),
    facebookId: Type.Optional(Type.String()),
    twitterId: Type.Optional(Type.String()),
    githubId: Type.Optional(Type.String()),
    // timestamps
    createdAt: Type.String(),
    updatedAt: Type.String(),
  },
  { $id: 'User', additionalProperties: false }
)
claustres commented 12 months ago

I wonder if you schema actually allows for null values as after an operation requiring a token all verifyXXXfields are reset and set to null.

foxhound87 commented 12 months ago

Thank you for your suggestion! I now updated the schema making the fields nullable (I had to add also reseetXXX fields), and seems working correctly now!

    isVerified: Type.Boolean(),
    verifyToken: Type.Union([Type.Null(), Type.String()]),
    verifyTokenShort: Type.Union([Type.Null(), Type.String()]),
    verifyShortToken:Type.Union([Type.Null(), Type.String()]),
    verifyExpires: Type.Union([Type.Null(), Type.Number()]),
    verifyChanges: Type.Optional(Type.Union([Type.Null(), Type.Object({})])),
    resetToken: Type.Optional(Type.Union([Type.Null(), Type.String()])),
    resetShortToken: Type.Optional(Type.Union([Type.Null(), Type.String()])),
    resetExpires: Type.Optional(Type.Union([Type.Null(), Type.Number()])),
    resetAttempts: Type.Optional(Type.Union([Type.Null(), Type.Number()])),