0

I have a master application that accepts plugin modules, except for some functionality (authentication) where for some reason it seems hell-bent to prevent plugins from adding authentication methods. Despite that, I still need to do exactly that - add a new authentication method, but via a plugin.

The master application has a typescript module that exports an Authenticator class,

export class Authenticator {
   constructor(arg) { dostuff(arg); }
}

I need to somehow intercept the constructor argument and store it in my plugin. The Authenticator class is instantiated in private code, but fortunately, after my plugin is initialized - so I get a chance to run some code; is there any way to dynamically modify the Authenticator class object (i.e. the class itself) so that I may capture the argument, when it is actually instantiated? Note that I can't use a decorator (I'd need to modify the main app), and I can't instantiate a proxy instead of the Authenticator (again, I would need to modify the main app in order to do so). I've tried modifying Authenticator.constructor or Authenticator.prototype.constructor but neither works apparently. Is there any other way?

Virgil
  • 3,022
  • 2
  • 19
  • 36
  • 1
    No, this is not possible. The constructor is the `Authenticator` itself, to intercept calls to that function you must replace it by something else. If this is typescript code that gets transpiled to commonjs, you might be able to mess with the `module.exports`. – Bergi Feb 10 '20 at 21:50
  • What is `doStuff`? Maybe you can intercept that. – Bergi Feb 10 '20 at 21:53
  • Does [this](https://stackoverflow.com/a/43726273/1048572) help? – Bergi Feb 10 '20 at 21:53
  • 1
    So, in general the answer is **No**, to suggest an appropriate workaround we need to know the exact details. Links to the code of library and the instantiation code would be good. – Bergi Feb 10 '20 at 21:55
  • You could patch the library containing the Authenticator class with something like `patch-package`. – sdgluck Feb 10 '20 at 22:14
  • The `doStuff` is just setting some private members. This is the code: https://github.com/elastic/kibana/blob/8e8a6ef7542ccf590031e0285f277712f0cb0b72/x-pack/plugins/security/server/authentication/authenticator.ts - I need to capture "options" in my plugin. Patching the deployed (source) code is a last-resort option, but I was hoping there's a way to do it dynamically/from the plugin – Virgil Feb 11 '20 at 07:02
  • And here's how plugins are created/ the stuff that I need to intercept: https://github.com/elastic/kibana/blob/8e8a6ef7542ccf590031e0285f277712f0cb0b72/src/core/server/plugins/plugin_context.ts#L111 - as you see, it's doing a deep copy of the "deps" object, so if I change `createCookieStorageFactory` I only change it for my plugin, not for the internal one. And factory can't be created twice (explicit exception). Auth handler can't be registered twice (Explicit exception). Etc. - like I said, hell-bent of preventing what I want to do :) – Virgil Feb 11 '20 at 07:08
  • @Bergi I really thought your link can help since the code does `this.providers = <...>` ... but, prior to that it also uses `Object.defineProperty` to set the "providers" property on the "this" object, effectively preventing the getter/setter trick. Looks like the final answer is that I _really_ can't do what I want without patching existing application code(outside my plugin). Patching works, one extra line of code in the generated .js file and I'm good, but I was trying to avoid it. – Virgil Feb 11 '20 at 07:25
  • @Virgil Where do you see `Object.defineProperty`, is that what the `private readonly` thing is getting transpiled to? – Bergi Feb 11 '20 at 08:09
  • Yes - first `_defineProperty(this, "providers", void 0);` then assignment with the actual value. – Virgil Feb 11 '20 at 08:37

0 Answers0