isundil 1 mese fa
parent
commit
e965a5fb01

+ 1 - 1
dist/ldapAuthenticationHandler.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"ldapAuthenticationHandler.d.ts","sourceRoot":"","sources":["../src/ldapAuthenticationHandler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGpD,MAAM,WAAW,+BAA+B;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,GAAC,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAC,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,GAAC,IAAI,CAAC;CAC3B;AAOD,qBAAa,yBAA0B,YAAW,sBAAsB;IACpE,OAAO,CAAC,aAAa,CAAkC;gBAEpC,aAAa,EAAE,+BAA+B;IAIjE,OAAO,CAAC,aAAa;YAQP,OAAO;IA0CR,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAOpF,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;CAMrF"}
+{"version":3,"file":"ldapAuthenticationHandler.d.ts","sourceRoot":"","sources":["../src/ldapAuthenticationHandler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGpD,MAAM,WAAW,+BAA+B;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,GAAC,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAC,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,GAAC,IAAI,CAAC;CAC3B;AAOD,qBAAa,yBAA0B,YAAW,sBAAsB;IACpE,OAAO,CAAC,aAAa,CAAkC;gBAEpC,aAAa,EAAE,+BAA+B;IAIjE,OAAO,CAAC,aAAa;YAQP,OAAO;IA0CR,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAMpF,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;CAMrF"}

+ 0 - 1
dist/ldapAuthenticationHandler.js

@@ -54,7 +54,6 @@ export class LdapAuthenticationHandler {
     }
     async tryLogin(username, password, totp) {
         const account = await this.tryBind(username, password);
-        console.log(account);
         if (!account)
             return null;
         return TotpChecker.ValidateTotp(account.totp, totp);

File diff suppressed because it is too large
+ 0 - 0
dist/ldapAuthenticationHandler.js.map


+ 7 - 4
dist/totpChecker.d.ts

@@ -1,7 +1,8 @@
+export type TotpAlgorithm = "SHA-1" | "SHA-256" | "SHA-512";
 export interface ToTpGeneratorOptions {
     digits?: number;
     period?: number;
-    algorithm?: "SHA-1" | "SHA-256" | "SHA-512";
+    algorithm?: TotpAlgorithm;
     label?: string;
     secretLength?: number;
     issuer: string;
@@ -11,8 +12,10 @@ export interface ToTpSecretAndUrl {
     secret: string;
 }
 export declare class TotpChecker {
-    static ValidateTotp(totpSecret: string | null, code: string | undefined): Promise<boolean>;
-    static EncodeBase32(input: Buffer): string;
-    static GenerateCode(optionsOrIssuer: ToTpGeneratorOptions | string): ToTpSecretAndUrl;
+    static ValidateTotp(totpSecret: string | null, code: string | undefined, period?: number, digits?: number, algorithm?: TotpAlgorithm): Promise<boolean>;
+    private static DoGenerateCode;
+    private static getCurrentPeriod;
+    static GenerateCode(totpSecret: string, period?: number, digits?: number, algorithm?: TotpAlgorithm): string;
+    static GenerateUrl(optionsOrIssuer: ToTpGeneratorOptions | string): ToTpSecretAndUrl;
 }
 //# sourceMappingURL=totpChecker.d.ts.map

+ 1 - 1
dist/totpChecker.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"totpChecker.d.ts","sourceRoot":"","sources":["../src/totpChecker.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,GAAC,SAAS,GAAC,SAAS,CAAA;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAClB;AAID,qBAAa,WAAW;WACA,YAAY,CAAC,UAAU,EAAE,MAAM,GAAC,IAAI,EAAE,IAAI,EAAE,MAAM,GAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;WAQrF,YAAY,CAAC,KAAK,EAAE,MAAM;WAO1B,YAAY,CAAC,eAAe,EAAE,oBAAoB,GAAC,MAAM,GAAG,gBAAgB;CAa7F"}
+{"version":3,"file":"totpChecker.d.ts","sourceRoot":"","sources":["../src/totpChecker.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAE5D,MAAM,WAAW,oBAAoB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAClB;AAID,qBAAa,WAAW;WACA,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;IAkBpK,OAAO,CAAC,MAAM,CAAC,cAAc;IAwB7B,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIjB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,aAAa,GAAG,MAAM;WAIrG,WAAW,CAAC,eAAe,EAAE,oBAAoB,GAAG,MAAM,GAAG,gBAAgB;CAc9F"}

+ 42 - 9
dist/totpChecker.js

@@ -1,27 +1,60 @@
+import base32Decode from 'base32-decode';
 import crypto from 'crypto';
 const RFC_4648 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
 export class TotpChecker {
-    static async ValidateTotp(totpSecret, code) {
+    static async ValidateTotp(totpSecret, code, period, digits, algorithm) {
         if (!totpSecret && !code)
             return true;
         if ((!totpSecret && code) || (totpSecret && !code))
             return false;
-        return true;
+        let currentPeriod = TotpChecker.getCurrentPeriod(period);
+        const input = Buffer.from(code.replace(/[^0-9]/g, "").trim());
+        return TotpChecker.DoGenerateCode(totpSecret, [currentPeriod - 1, currentPeriod, currentPeriod + 1], digits || 6, algorithm || "SHA-1")
+            .find(x => {
+            try {
+                return crypto.timingSafeEqual(Buffer.from(x), input);
+            }
+            catch (err) {
+                return false;
+            }
+        }) !== undefined;
     }
-    static EncodeBase32(input) {
-        let secret = [];
-        for (let i of input)
-            secret.push(RFC_4648[i % RFC_4648.length]);
-        return secret.join("");
+    static DoGenerateCode(totpSecret, period, digits, algorithm) {
+        const secretAsBase64 = Buffer.from(base32Decode(totpSecret, "RFC4648"));
+        return (Array.isArray(period) ? period : [period]).map(i => {
+            // Encode period as a Buffer
+            var periodAsBuffer = Buffer.alloc(8);
+            periodAsBuffer.write((i.toString(16)).padStart(16, '0'), 0, 'hex');
+            return periodAsBuffer;
+        }).map(period => {
+            // Encode period using algorithm and secret
+            return crypto.createHmac(algorithm, secretAsBase64)
+                .update(period)
+                .digest();
+        }).map(hash => {
+            // Truncate output hash
+            let offset = hash[hash.length - 1] & 0xF;
+            var truncatedHash = ((hash[offset + 0] & 0x7F) << 24 |
+                (hash[offset + 1] & 0xFF) << 16 |
+                (hash[offset + 2] & 0xFF) << 8 |
+                (hash[offset + 3] & 0xFF)) % (10 ** digits);
+            return (`${truncatedHash}`.padStart(digits, '0'));
+        });
     }
-    static GenerateCode(optionsOrIssuer) {
+    static getCurrentPeriod(period) {
+        return Math.floor(Date.now() / ((period || 30) * 1000));
+    }
+    static GenerateCode(totpSecret, period, digits, algorithm) {
+        return TotpChecker.DoGenerateCode(totpSecret, this.getCurrentPeriod(period), digits || 6, algorithm || "SHA-1").shift();
+    }
+    static GenerateUrl(optionsOrIssuer) {
         let options = typeof optionsOrIssuer === "string" ? { issuer: optionsOrIssuer } : optionsOrIssuer;
         options.digits = options.digits || 6;
         options.period = options.period || 30;
         options.algorithm = options.algorithm || "SHA-1";
         options.label = encodeURIComponent(options.label || options.issuer);
         options.secretLength = options.secretLength || 13;
-        const secretStr = TotpChecker.EncodeBase32(crypto.randomBytes(options.secretLength));
+        const secretStr = Array.from(crypto.randomBytes(options.secretLength)).map(x => RFC_4648[x % RFC_4648.length]).join("");
         return {
             url: `otpauth://totp/${options.issuer}?issuer=${options.issuer}&secret=${secretStr}&digits=${options.digits}&period=${options.period}&algorithm=${options.algorithm}`,
             secret: secretStr

File diff suppressed because it is too large
+ 0 - 1
dist/totpChecker.js.map


+ 1 - 1
dist/yesManAuthenticationHandler.js

@@ -9,7 +9,7 @@ export class YesManAuthenticationHandler {
             return Promise.resolve(null);
         if (!password)
             return Promise.resolve(false);
-        return TotpChecker.ValidateTotp(this.useTotp ? TotpChecker.EncodeBase32(Buffer.from(username)) : null, totp);
+        return Promise.resolve(this.useTotp ? TotpChecker.ValidateTotp("YES", totp) : true);
     }
     needTotp(username, _password) {
         return Promise.resolve(username ? this.useTotp : null);

+ 1 - 1
dist/yesManAuthenticationHandler.js.map

@@ -1 +1 @@
-{"version":3,"file":"yesManAuthenticationHandler.js","sourceRoot":"","sources":["../src/yesManAuthenticationHandler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,OAAO,2BAA2B;IAC5B,OAAO,CAAU;IAEzB,YAAmB,OAAgB;QAC/B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IACM,QAAQ,CAAC,QAAgB,EAAE,QAAgB,EAAE,IAAa;QAC7D,IAAI,CAAC,QAAQ;YACT,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,QAAQ;YACT,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAClC,OAAO,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACjH,CAAC;IACM,QAAQ,CAAC,QAAgB,EAAE,SAAiB;QAC/C,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC;CACJ"}
+{"version":3,"file":"yesManAuthenticationHandler.js","sourceRoot":"","sources":["../src/yesManAuthenticationHandler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,OAAO,2BAA2B;IAC5B,OAAO,CAAU;IAEzB,YAAmB,OAAgB;QAC/B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IACM,QAAQ,CAAC,QAAgB,EAAE,QAAgB,EAAE,IAAa;QAC7D,IAAI,CAAC,QAAQ;YACT,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,QAAQ;YACT,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAClC,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACxF,CAAC;IACM,QAAQ,CAAC,QAAgB,EAAE,SAAiB;QAC/C,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC;CACJ"}

+ 1 - 1
src/totpChecker.ts

@@ -21,7 +21,7 @@ export interface ToTpSecretAndUrl {
 const RFC_4648 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
 
 export class TotpChecker {
-    public static async ValidateTotp(totpSecret: string | null, code: string | undefined, period: number, digits?: number, algorithm?: TotpAlgorithm): Promise<boolean> {
+    public static async ValidateTotp(totpSecret: string | null, code: string | undefined, period?: number, digits?: number, algorithm?: TotpAlgorithm): Promise<boolean> {
         if (!totpSecret && !code)
             return true;
         if ((!totpSecret && code) || (totpSecret && !code))

+ 1 - 1
src/yesManAuthenticationHandler.ts

@@ -12,7 +12,7 @@ export class YesManAuthenticationHandler implements IAuthenticationHandler {
             return Promise.resolve(null);
         if (!password)
             return Promise.resolve(false);
-        return TotpChecker.ValidateTotp(this.useTotp ? TotpChecker.EncodeBase32(Buffer.from(username)) : null, totp);
+        return Promise.resolve(this.useTotp ? TotpChecker.ValidateTotp("YES", totp) : true);
     }
     public needTotp(username: string, _password: string): Promise<boolean | null> {
         return Promise.resolve(username ? this.useTotp : null);

Some files were not shown because too many files changed in this diff