Repository: kubernetes-client/javascript (ts)

Issue:
Can the ability to customize Authenticators be opened up?
I've noticed that `KubeConfig` provides several static `Authenticator` implementations. However, I need to add additional authentication methods for my internal use cases. Could you make the `authenticators` property in `KubeConfig` configurable or provide other methods to extent authentication methods?

Pull request:
Add the ability to inject authenticators.
Fixes #2263 

Patch:
diff --git a/src/config.ts b/src/config.ts
index 482a12a8..2545fe9a 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -65,6 +65,15 @@ export class KubeConfig implements SecurityAuthentication {
         new OpenIDConnectAuth(),
     ];
 
+    // List of custom authenticators that can be added by the user
+    private custom_authenticators: Authenticator[] = [];
+
+    // Optionally add additional external authenticators, you must do this
+    // before you load a kubeconfig file that references them.
+    public addAuthenticator(authenticator: Authenticator): void {
+        this.custom_authenticators.push(authenticator);
+    }
+
     /**
      * The list of all known clusters
      */
@@ -577,10 +586,16 @@ export class KubeConfig implements SecurityAuthentication {
         if (!user) {
             return;
         }
-        const authenticator = KubeConfig.authenticators.find((elt: Authenticator) => {
+        let authenticator = KubeConfig.authenticators.find((elt: Authenticator) => {
             return elt.isAuthProvider(user);
         });
 
+        if (!authenticator) {
+            authenticator = this.custom_authenticators.find((elt: Authenticator) => {
+                return elt.isAuthProvider(user);
+            });
+        }
+
         if (!opts.headers) {
             opts.headers = {};
         }


Test patch:
diff --git a/src/config_test.ts b/src/config_test.ts
index 5e082ee8..9992937a 100644
--- a/src/config_test.ts
+++ b/src/config_test.ts
@@ -9,6 +9,7 @@ import { mock } from 'node:test';
 
 import mockfs from 'mock-fs';
 
+import { Authenticator } from './auth.js';
 import { Headers } from 'node-fetch';
 import { HttpMethod } from './index.js';
 import { assertRequestAgentsEqual, assertRequestOptionsEqual } from './test/match-buffer.js';
@@ -1703,5 +1704,45 @@ describe('KubeConfig', () => {
             }
             validateFileLoad(kc);
         });
+
+        it('should inject a custom Authenticator', async () => {
+            class CustomAuthenticator implements Authenticator {
+                public isAuthProvider(user: User): boolean {
+                    return user.authProvider === 'custom';
+                }
+
+                public async applyAuthentication(user: User, opts: RequestOptions): Promise<void> {
+                    if (user.authProvider === 'custom') {
+                        // Simulate token retrieval
+                        const token = 'test-token';
+                        opts.headers = opts.headers || {};
+                        opts.headers.Authorization = `Bearer ${token}`;
+                    } else {
+                        throw new Error('No custom configuration found');
+                    }
+                }
+            }
+
+            const customAuthenticator = new CustomAuthenticator();
+            const kc = new KubeConfig();
+            kc.addAuthenticator(customAuthenticator);
+
+            const cluster: Cluster = {
+                name: 'test-cluster',
+                server: 'https://localhost:6443',
+                skipTLSVerify: false,
+            };
+            const user: User = {
+                name: 'test-user',
+                authProvider: 'custom',
+            };
+
+            kc.loadFromClusterAndUser(cluster, user);
+
+            const opts: RequestOptions = {};
+            await kc.applyToHTTPSOptions(opts);
+
+            strictEqual(opts.headers!.Authorization, 'Bearer test-token');
+        });
     });
 });