jonbloom / homebridge-ufp

Unifi Protect plugin for homebridge: https://github.com/nfarina/homebridge
Apache License 2.0
2 stars 0 forks source link

Authentication issue #4

Closed dvlamoen closed 4 years ago

dvlamoen commented 4 years ago

I am thoroughly stumped. Keep getting a LoginRequired error.

Is this a bug, or am I missing something?

(node:640) UnhandledPromiseRejectionWarning: StatusCodeError: 412 - {"data":[],"meta":{"rc":"error","msg":"api.err.LoginRequired"}}
    at new StatusCodeError (/usr/local/lib/node_modules/homebridge-ufp/node_modules/request-promise-core/lib/errors.js:32:15)
    at Request.plumbing.callback (/usr/local/lib/node_modules/homebridge-ufp/node_modules/request-promise-core/lib/plumbing.js:104:33)
    at Request.RP$callback [as _callback] (/usr/local/lib/node_modules/homebridge-ufp/node_modules/request-promise-core/lib/plumbing.js:46:31)
    at Request.self.callback (/usr/local/lib/node_modules/homebridge-ufp/node_modules/request/request.js:185:22)
    at Request.emit (events.js:311:20)
    at Request.<anonymous> (/usr/local/lib/node_modules/homebridge-ufp/node_modules/request/request.js:1154:10)
    at Request.emit (events.js:311:20)
    at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/homebridge-ufp/node_modules/request/request.js:1076:12)
    at Object.onceWrapper (events.js:417:28)
    at IncomingMessage.emit (events.js:323:22)
    at endReadableNT (_stream_readable.js:1204:12)
    at processTicksAndRejections (internal/process/task_queues.js:84:21)
(node:640) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:640) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
jonbloom commented 4 years ago

Can you post a redacted config? (Just remove user/passwords).

hfagelnour commented 4 years ago

running into error as well, UDMPro running UNIFI OS 1.6.7, Controller 5.12.67, Protect 1.14.9 , homebridge 0.4.53

config: "platforms": [ { "platform": "Camera-UniFi-Protect", "name": "UniFi Protect", "controllers": [ { "url": "https://192.168.3.1/", "username": "xxxxxxx", "password": "xxxxxxx" } ] },

error log: StatusCodeError: 404 - "Not Found" at new StatusCodeError (/usr/lib/node_modules/homebridge-ufp/node_modules/request-promise-core/lib/errors.js:32:15) at Request.plumbing.callback (/usr/lib/node_modules/homebridge-ufp/node_modules/request-promise-core/lib/plumbing.js:104:33) at Request.RP$callback [as _callback] (/usr/lib/node_modules/homebridge-ufp/node_modules/request-promise-core/lib/plumbing.js:46:31) at Request.self.callback (/usr/lib/node_modules/homebridge-ufp/node_modules/request/request.js:185:22) at Request.emit (events.js:310:20) at Request. (/usr/lib/node_modules/homebridge-ufp/node_modules/request/request.js:1154:10) at Request.emit (events.js:310:20) at IncomingMessage. (/usr/lib/node_modules/homebridge-ufp/node_modules/request/request.js:1076:12) at Object.onceWrapper (events.js:416:28) at IncomingMessage.emit (events.js:322:22) at endReadableNT (_stream_readable.js:1187:12) at processTicksAndRejections (internal/process/task_queues.js:84:21) { name: 'StatusCodeError', statusCode: 404, message: '404 - "Not Found"', error: 'Not Found', options: { jar: true, headers: { 'X-CSRF-Token': '5502462f-0dbc-4ec7-8a6b-5be6ce38d87d' }, rejectUnauthorized: false, resolveWithFullResponse: true, uri: 'https://192.168.3.1//proxy/protect/api/bootstrap', method: 'GET', callback: [Function: RP$callback], transform: undefined, simple: true, transform2xxOnly: false }, response: IncomingMessage { _readableState: ReadableState { objectMode: false, highWaterMark: 16384, buffer: BufferList { head: null, tail: null, length: 0 }, length: 0, pipes: null, pipesCount: 0, flowing: true, ended: true, endEmitted: true, reading: false, sync: true, needReadable: false, emittedReadable: false, readableListening: false, resumeScheduled: false, emitClose: true, autoDestroy: false, destroyed: false, defaultEncoding: 'utf8', awaitDrain: 0, readingMore: true, decoder: null, encoding: null,

},
readable: false,
_events: [Object: null prototype] {
  end: [Array],
  close: [Array],
  data: [Function],
  error: [Function]
},
_eventsCount: 4,
_maxListeners: undefined,
socket: TLSSocket {
  _tlsOptions: [Object],
  _secureEstablished: true,
  _securePending: false,
  _newSessionPending: false,
  _controlReleased: true,
  _SNICallback: null,
  servername: false,
  alpnProtocol: false,
  authorized: false,
  authorizationError: 'DEPTH_ZERO_SELF_SIGNED_CERT',
  encrypted: true,
  _events: [Object: null prototype],
  _eventsCount: 9,
  connecting: false,
  _hadError: false,
  _parent: null,
  _host: null,
  _readableState: [ReadableState],
  readable: true,
  _maxListeners: undefined,
  _writableState: [WritableState],
  writable: false,
  allowHalfOpen: false,
  _sockname: null,
  _pendingData: null,
  _pendingEncoding: '',
  server: undefined,
  _server: null,
  ssl: [TLSWrap],
  _requestCert: true,
  _rejectUnauthorized: false,
  parser: null,
  _httpMessage: [ClientRequest],
  [Symbol(res)]: [TLSWrap],
  [Symbol(asyncId)]: 421,
  [Symbol(kHandle)]: [TLSWrap],
  [Symbol(kSetNoDelay)]: false,
  [Symbol(lastWriteQueueSize)]: 0,
  [Symbol(timeout)]: null,
  [Symbol(kBuffer)]: null,
  [Symbol(kBufferCb)]: null,
  [Symbol(kBufferGen)]: null,
  [Symbol(kCapture)]: false,
  [Symbol(kBytesRead)]: 0,
  [Symbol(kBytesWritten)]: 0,
  [Symbol(connect-options)]: [Object]
},
connection: TLSSocket {
  _tlsOptions: [Object],
  _secureEstablished: true,
  _securePending: false,
  _newSessionPending: false,
  _controlReleased: true,
  _SNICallback: null,
  servername: false,
  alpnProtocol: false,
  authorized: false,
  authorizationError: 'DEPTH_ZERO_SELF_SIGNED_CERT',
  encrypted: true,
  _events: [Object: null prototype],
  _eventsCount: 9,
  connecting: false,
  _hadError: false,
  _parent: null,
  _host: null,
  _readableState: [ReadableState],
  readable: true,
  _maxListeners: undefined,
  _writableState: [WritableState],
  writable: false,
  allowHalfOpen: false,
  _sockname: null,
  _pendingData: null,
  _pendingEncoding: '',
  server: undefined,
  _server: null,
  ssl: [TLSWrap],
  _requestCert: true,
  _rejectUnauthorized: false,
  parser: null,
  _httpMessage: [ClientRequest],
  [Symbol(res)]: [TLSWrap],
  [Symbol(asyncId)]: 421,
  [Symbol(kHandle)]: [TLSWrap],
  [Symbol(kSetNoDelay)]: false,
  [Symbol(lastWriteQueueSize)]: 0,
  [Symbol(timeout)]: null,
  [Symbol(kBuffer)]: null,
  [Symbol(kBufferCb)]: null,
  [Symbol(kBufferGen)]: null,
  [Symbol(kCapture)]: false,
  [Symbol(kBytesRead)]: 0,
  [Symbol(kBytesWritten)]: 0,
  [Symbol(connect-options)]: [Object]
},
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers: {
  vary: 'Origin',
  'x-dns-prefetch-control': 'off',
  'x-frame-options': 'SAMEORIGIN',
  'strict-transport-security': 'max-age=15552000; includeSubDomains',
  'x-download-options': 'noopen',
  'x-content-type-options': 'nosniff',
  'x-xss-protection': '1; mode=block',
  'x-response-time': '5ms',
  'content-type': 'text/plain; charset=utf-8',
  'content-length': '9',
  date: 'Mon, 20 Apr 2020 15:12:13 GMT',
  connection: 'close'
},
rawHeaders: [
  'Vary',
  'Origin',
  'X-DNS-Prefetch-Control',
  'off',
  'X-Frame-Options',
  'SAMEORIGIN',
  'Strict-Transport-Security',
  'max-age=15552000; includeSubDomains',
  'X-Download-Options',
  'noopen',
  'X-Content-Type-Options',
  'nosniff',
  'X-XSS-Protection',
  '1; mode=block',
  'X-Response-Time',
  '5ms',
  'Content-Type',
  'text/plain; charset=utf-8',
  'Content-Length',
  '9',
  'Date',
  'Mon, 20 Apr 2020 15:12:13 GMT',
  'Connection',
  'close'
],
trailers: {},
rawTrailers: [],
aborted: false,
upgrade: false,
url: '',
method: null,
statusCode: 404,
statusMessage: 'Not Found',
client: TLSSocket {
  _tlsOptions: [Object],
  _secureEstablished: true,
  _securePending: false,
  _newSessionPending: false,
  _controlReleased: true,
  _SNICallback: null,
  servername: false,
  alpnProtocol: false,
  authorized: false,
  authorizationError: 'DEPTH_ZERO_SELF_SIGNED_CERT',
  encrypted: true,
  _events: [Object: null prototype],
  _eventsCount: 9,
  connecting: false,
  _hadError: false,
  _parent: null,
  _host: null,
  _readableState: [ReadableState],
  readable: true,
  _maxListeners: undefined,
  _writableState: [WritableState],
  writable: false,
  allowHalfOpen: false,
  _sockname: null,
  _pendingData: null,
  _pendingEncoding: '',
  server: undefined,
  _server: null,
  ssl: [TLSWrap],
  _requestCert: true,
  _rejectUnauthorized: false,
  parser: null,
  _httpMessage: [ClientRequest],
  [Symbol(res)]: [TLSWrap],
  [Symbol(asyncId)]: 421,
  [Symbol(kHandle)]: [TLSWrap],
  [Symbol(kSetNoDelay)]: false,
  [Symbol(lastWriteQueueSize)]: 0,
  [Symbol(timeout)]: null,
  [Symbol(kBuffer)]: null,
  [Symbol(kBufferCb)]: null,
  [Symbol(kBufferGen)]: null,
  [Symbol(kCapture)]: false,
  [Symbol(kBytesRead)]: 0,
  [Symbol(kBytesWritten)]: 0,
  [Symbol(connect-options)]: [Object]
},
_consuming: false,
_dumped: false,
req: ClientRequest {
  _events: [Object: null prototype],
  _eventsCount: 5,
  _maxListeners: undefined,
  outputData: [],
  outputSize: 0,
  writable: true,
  _last: true,
  chunkedEncoding: false,
  shouldKeepAlive: false,
  useChunkedEncodingByDefault: false,
  sendDate: false,
  _removedConnection: false,
  _removedContLen: false,
  _removedTE: false,
  _contentLength: 0,
  _hasBody: true,
  _trailer: '',
  finished: true,
  _headerSent: true,
  socket: [TLSSocket],
  connection: [TLSSocket],
  _header: 'GET //proxy/protect/api/bootstrap HTTP/1.1\r\n' +
    'X-CSRF-Token: 5502462f-0dbc-4ec7-8a6b-5be6ce38d87d\r\n' +
    'host: 192.168.3.1\r\n' +
    'cookie: TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjc3JmVG9rZW4iOiI1NTAyNDYyZi0wZGJjLTRlYzctOGE2Yi01YmU2Y2UzOGQ4N2QiLCJpYXQiOjE1ODczOTU1MzMsImV4cCI6MTU4NzM5OTEzM30.WA9WU5A9bjJXGjM2alaUT0FjybO-0OMR7cCuCdoP8ms\r\n' +
    'Connection: close\r\n' +
    '\r\n',
  _onPendingData: [Function: noopPendingOutput],
  agent: [Agent],
  socketPath: undefined,
  method: 'GET',
  insecureHTTPParser: undefined,
  path: '//proxy/protect/api/bootstrap',
  _ended: true,
  res: [Circular],
  aborted: false,
  timeoutCb: null,
  upgradeOrConnect: false,
  parser: null,
  maxHeadersCount: null,
  reusedSocket: false,
  [Symbol(kCapture)]: false,
  [Symbol(kNeedDrain)]: false,
  [Symbol(corked)]: 0,
  [Symbol(kOutHeaders)]: [Object: null prototype]
},
request: Request {
  _events: [Object: null prototype],
  _eventsCount: 5,
  _maxListeners: undefined,
  headers: [Object],
  rejectUnauthorized: false,
  resolveWithFullResponse: true,
  uri: [Url],
  method: 'GET',
  readable: true,
  writable: true,
  explicitMethod: true,
  _qs: [Querystring],
  _auth: [Auth],
  _oauth: [OAuth],
  _multipart: [Multipart],
  _redirect: [Redirect],
  _tunnel: [Tunnel],
  _rp_resolve: [Function],
  _rp_reject: [Function],
  _rp_promise: [Promise [Object]],
  _rp_callbackOrig: undefined,
  callback: [Function],
  _rp_options: [Object],
  setHeader: [Function],
  hasHeader: [Function],
  getHeader: [Function],
  removeHeader: [Function],
  localAddress: undefined,
  pool: [Object],
  dests: [],
  __isRequestRequest: true,
  _callback: [Function: RP$callback],
  proxy: null,
  tunnel: true,
  setHost: true,
  originalCookieHeader: undefined,
  _jar: true,
  port: 443,
  host: '192.168.3.1',
  path: '//proxy/protect/api/bootstrap',
  httpModule: [Object],
  agentClass: [Function: Agent],
  agent: [Agent],
  _started: true,
  href: 'https://192.168.3.1//proxy/protect/api/bootstrap',
  req: [ClientRequest],
  ntick: true,
  response: [Circular],
  originalHost: '192.168.3.1',
  originalHostHeaderName: 'host',
  responseContent: [Circular],
  _destdata: true,
  _ended: true,
  _callbackCalled: true,
  [Symbol(kCapture)]: false
},
toJSON: [Function: responseToJSON],
caseless: Caseless { dict: [Object] },
body: 'Not Found',
[Symbol(kCapture)]: false

} }

jonbloom commented 4 years ago

@hfagelnour Try removing the trailing slash in your IP for the UDM Pro. Looks like the URL it’s generating has two based on my paths assuming you don’t put a trailing slash. See the README for an example config.

hfagelnour commented 4 years ago

@jonbloom u da ma! this made it ..... cant thank you enough.

jonbloom commented 4 years ago

Awesome. Glad to help and to hear that you've got it running.

@dvlamoen Are you still running into issues? If not, I'd like to close this.

hfagelnour commented 4 years ago

@jonbloom being the greedy i am :) planning to add motion sensors capabilities anytime soon.

jonbloom commented 4 years ago

@hfagelnour No, I'm not. There's this repo that supports it, but currently UniFi OS authentication is broken due to a cookie issue.

hfagelnour commented 4 years ago

Thx for the help and the heads up 🙏🏻

Sent from my iPhone

On Apr 21, 2020, at 1:37 AM, Jon Bloom notifications@github.com wrote:

 @hfagelnour No, I'm not. There's this repo that supports it, but currently UniFi OS authentication is broken due to a cookie issue.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

crxporter commented 4 years ago

@jonbloom - I’ve been lurking for a while and copied some of your code...

Anyway, I’ve just set up unifi OS with motion polling in node red, saving cookies and everything. I have to re-authenticate every 1-3 hours but I’m pulling every 2 seconds, it works great. If you’d like some tips on handling the authentication and cookies I’d be happy to share.

After authentication I’m sending a token and a cookie with all polls (http get). Each response comes back with a new cookie which I use for the next request.