mirror of
https://github.com/FlipsideCrypto/DefinitelyTyped.git
synced 2026-02-06 10:56:53 +00:00
Add new type definition for http-auth (#47878)
* add http-auth type * fix for dtslint
This commit is contained in:
parent
5d9cf12b75
commit
5d2eb256ce
153
types/http-auth/index.d.ts
vendored
Normal file
153
types/http-auth/index.d.ts
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
// Type definitions for http-auth 4.1
|
||||
// Project: https://github.com/http-auth/http-auth
|
||||
// Definitions by: nokazn <https://github.com/nokazn>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// TypeScript Version: 4.0
|
||||
|
||||
/// <reference types="node" />
|
||||
|
||||
import * as http from 'http';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
type Qop = 'auth' | 'none';
|
||||
type Algorithm = 'MD5' | 'MD5-sess';
|
||||
|
||||
type CheckedRequestListener = (req: http.IncomingMessage & { user?: string }, res: http.ServerResponse) => void;
|
||||
type BasicChecker = (username: string, password: string, callback: (isAuthorized: boolean) => void) => void;
|
||||
type DigestChecker = (username: string, callback: (hash?: string) => void) => void;
|
||||
|
||||
interface BasicResult<T extends boolean = boolean> {
|
||||
user?: string;
|
||||
pass?: T;
|
||||
}
|
||||
type DigestResult<T extends boolean = boolean> = BasicResult<T> & {
|
||||
stale?: true;
|
||||
};
|
||||
type ResultEmitter = (result: BasicResult | DigestResult | Error) => void;
|
||||
|
||||
type Nonce = [string, number, number];
|
||||
|
||||
interface ClientOptions {
|
||||
username: string;
|
||||
realm: string;
|
||||
nonce: string;
|
||||
uri: string;
|
||||
algorithm: Algorithm;
|
||||
response: string;
|
||||
qop?: 'auth';
|
||||
nc?: string;
|
||||
cnonce?: string;
|
||||
}
|
||||
|
||||
interface BasicOptions {
|
||||
/**
|
||||
* Authentication realm, by default it is 'users'.
|
||||
* @default 'users'
|
||||
*/
|
||||
realm?: string;
|
||||
|
||||
/**
|
||||
* File where user details are stored.
|
||||
* - Line format is {user:pass} or {user:passHash} for basic access.
|
||||
* - Line format is {user:realm:passHash} for digest access.
|
||||
*/
|
||||
file?: string;
|
||||
|
||||
/**
|
||||
* Message for failed authentication 401 page.
|
||||
* @default '401 Unauthorized'
|
||||
*/
|
||||
msg401?: string;
|
||||
|
||||
/**
|
||||
* Message for failed authentication 407 page.
|
||||
* @default '407 Proxy authentication required
|
||||
*/
|
||||
msg407?: string;
|
||||
|
||||
/**
|
||||
* Content type for failed authentication page.
|
||||
* @default 'text/plain'
|
||||
*/
|
||||
contentType?: string;
|
||||
|
||||
/**
|
||||
* Set this to true, if you want to use it with http-proxy (https://github.com/http-party/node-http-proxy).
|
||||
* @default false
|
||||
*/
|
||||
proxy?: boolean;
|
||||
|
||||
/**
|
||||
* Set this to true, if you don't want req.user to be filled with authentication info.
|
||||
*/
|
||||
skipUser?: boolean;
|
||||
}
|
||||
|
||||
type DigestOptions = BasicOptions & {
|
||||
/**
|
||||
* Quality of protection that is used only for digest access authentication
|
||||
* - 'auth' is set by default.
|
||||
* - 'none' this option is disabling protection.
|
||||
* @default 'auth
|
||||
*/
|
||||
qop?: Qop;
|
||||
|
||||
/**
|
||||
* Algorithm that will be used only for digest access authentication.
|
||||
* 'MD5' or 'MD5-sess' can be set.
|
||||
* @default 'MD5'
|
||||
*/
|
||||
algorithm?: Algorithm;
|
||||
};
|
||||
|
||||
declare abstract class Base extends EventEmitter {
|
||||
constructor(options: BasicOptions, checker?: BasicChecker | DigestChecker);
|
||||
|
||||
on(event: 'success', callback: (result: BasicResult<true> | DigestResult<true>) => void): this;
|
||||
on(event: 'fail', callback: (result: BasicResult<false> | DigestResult<false>) => void): this;
|
||||
on(event: 'error', callback: (err: Error) => void): this;
|
||||
|
||||
check(callback?: CheckedRequestListener): CheckedRequestListener;
|
||||
abstract processLine(userLine: string): void;
|
||||
abstract parseAuthorization(header: string): string | ClientOptions | undefined;
|
||||
abstract findUser(
|
||||
req: http.IncomingMessage,
|
||||
hashOrClientOptions: string | ClientOptions,
|
||||
callback: ResultEmitter,
|
||||
): void;
|
||||
abstract generateHeader(result?: DigestResult): string;
|
||||
private ask(res: http.ServerResponse, result: BasicResult | DigestResult): void;
|
||||
private isAuthenticated(req: http.IncomingMessage, callback: ResultEmitter): void;
|
||||
private loadUsers(): void;
|
||||
}
|
||||
|
||||
declare class Basic extends Base {
|
||||
constructor(options: BasicOptions, checker?: BasicChecker);
|
||||
|
||||
private validate(hash: string, password: string): boolean;
|
||||
|
||||
processLine(userLine: string): void;
|
||||
generateHeader(): string;
|
||||
parseAuthorization(header: string): string | undefined;
|
||||
findUser(req: http.IncomingMessage, hash: string, callback: ResultEmitter): void;
|
||||
}
|
||||
|
||||
declare class Digest extends Base {
|
||||
constructor(options: DigestOptions, checker?: DigestChecker);
|
||||
|
||||
private nonces: Nonce[];
|
||||
private validate(ha2: string, clientOptions: ClientOptions, hash: string): boolean;
|
||||
private removeNonces(nonces: Nonce[]): void;
|
||||
private validateNonce(nonce: string, qop: Qop, nc: string): boolean;
|
||||
private askNonce(): string;
|
||||
|
||||
processLine(userLine: string): void;
|
||||
generateHeader(result: DigestResult): string;
|
||||
parseAuthorization(header: string): string | undefined;
|
||||
findUser(req: http.IncomingMessage, clientOptions: ClientOptions, callback: ResultEmitter): void;
|
||||
}
|
||||
|
||||
declare function basic(options: BasicOptions, checker?: BasicChecker): Basic;
|
||||
declare function digest(options: DigestOptions, checker?: DigestChecker): Digest;
|
||||
|
||||
export { basic, digest, BasicOptions, DigestOptions, BasicChecker, DigestChecker };
|
||||
20
types/http-auth/test/http-auth-tests.basic.ts
Normal file
20
types/http-auth/test/http-auth-tests.basic.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import * as http from 'http';
|
||||
import * as auth from 'http-auth';
|
||||
|
||||
const basic = auth.basic({
|
||||
realm: 'Simon Area.',
|
||||
file: __dirname + '/../data/users.htpasswd', // gevorg:gpass, Sarah:testpass
|
||||
});
|
||||
|
||||
const server = http.createServer();
|
||||
const a = auth.digest({});
|
||||
a.check();
|
||||
// Creating new HTTP server.
|
||||
http.createServer(
|
||||
basic.check((req, res) => {
|
||||
res.end(`Welcome to private area - ${req.user}!`);
|
||||
}),
|
||||
).listen(1337, () => {
|
||||
// Log URL.
|
||||
console.log('Server running at http://127.0.0.1:1337/');
|
||||
});
|
||||
22
types/http-auth/test/http-auth-tests.basic_nofile.ts
Normal file
22
types/http-auth/test/http-auth-tests.basic_nofile.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import * as http from 'http';
|
||||
import * as auth from 'http-auth';
|
||||
|
||||
const basic = auth.basic(
|
||||
{
|
||||
realm: 'Simon Area.',
|
||||
},
|
||||
(username, password, callback) => {
|
||||
// Custom authentication method.
|
||||
callback(username === 'Tina' && password === 'Bullock');
|
||||
},
|
||||
);
|
||||
|
||||
// Creating new HTTP server.
|
||||
http.createServer(
|
||||
basic.check((req, res) => {
|
||||
res.end(`Welcome to private area - ${req.user}!`);
|
||||
}),
|
||||
).listen(1337, () => {
|
||||
// Log URL.
|
||||
console.log('Server running at http://127.0.0.1:1337/');
|
||||
});
|
||||
35
types/http-auth/test/http-auth-tests.digest.ts
Normal file
35
types/http-auth/test/http-auth-tests.digest.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import * as http from 'http';
|
||||
import * as auth from 'http-auth';
|
||||
import * as crypto from 'crypto';
|
||||
|
||||
const md5 = (input: string) => {
|
||||
const hash = crypto.createHash('MD5');
|
||||
hash.update(input);
|
||||
return hash.digest('hex');
|
||||
};
|
||||
|
||||
const digest = auth.digest(
|
||||
{
|
||||
realm: 'Simon Area.',
|
||||
},
|
||||
(username, callback) => {
|
||||
// Expecting md5(username:realm:password) in callback.
|
||||
if (username === 'simon') {
|
||||
callback(md5('simon:Simon Area.:smart'));
|
||||
} else if (username === 'tigran') {
|
||||
callback(md5('tigran:Simon Area.:great'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Creating new HTTP server.
|
||||
http.createServer(
|
||||
digest.check((req, res) => {
|
||||
res.end(`Welcome to private area - ${req.user}!`);
|
||||
}),
|
||||
).listen(1337, () => {
|
||||
// Log URL.
|
||||
console.log('Server running at http://127.0.0.1:1337/');
|
||||
});
|
||||
17
types/http-auth/test/http-auth-tests.digest_nofile.ts
Normal file
17
types/http-auth/test/http-auth-tests.digest_nofile.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import * as http from 'http';
|
||||
import * as auth from 'http-auth';
|
||||
|
||||
const digest = auth.digest({
|
||||
realm: 'Simon Area.',
|
||||
file: __dirname + '/../data/users.htdigest', // vivi:anna, sona:testpass
|
||||
});
|
||||
|
||||
// Creating new HTTP server.
|
||||
http.createServer(
|
||||
digest.check((req, res) => {
|
||||
res.end(`Welcome to private area - ${req.user}!`);
|
||||
}),
|
||||
).listen(1337, () => {
|
||||
// Log URL.
|
||||
console.log('Server running at http://127.0.0.1:1337/');
|
||||
});
|
||||
30
types/http-auth/test/http-auth-tests.events.ts
Normal file
30
types/http-auth/test/http-auth-tests.events.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import * as http from 'http';
|
||||
import * as auth from 'http-auth';
|
||||
|
||||
const basic = auth.basic({
|
||||
realm: 'Simon Area.',
|
||||
file: __dirname + '/../data/users.htpasswd', // gevorg:gpass, Sarah:testpass
|
||||
});
|
||||
|
||||
// Adding event listeners.
|
||||
basic.on('success', result => {
|
||||
console.log(`User authenticated: ${result.user}`);
|
||||
});
|
||||
|
||||
basic.on('fail', result => {
|
||||
console.log(`User authentication failed: ${result.user}`);
|
||||
});
|
||||
|
||||
basic.on('error', error => {
|
||||
console.log(`Authentication error: ${error.message}`);
|
||||
});
|
||||
|
||||
// Creating new HTTP server.
|
||||
http.createServer(
|
||||
basic.check((req, res) => {
|
||||
res.end(`Welcome to private area - ${req.user}!`);
|
||||
}),
|
||||
).listen(1337, () => {
|
||||
// Log URL.
|
||||
console.log('Server running at http://127.0.0.1:1337/');
|
||||
});
|
||||
27
types/http-auth/test/http-auth-tests.https.ts
Normal file
27
types/http-auth/test/http-auth-tests.https.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import * as https from 'https';
|
||||
import * as fs from 'fs';
|
||||
import * as auth from 'http-auth';
|
||||
|
||||
const basic = auth.basic({
|
||||
realm: 'Simon Area.',
|
||||
file: __dirname + '/../data/users.htpasswd', // gevorg:gpass, Sarah:testpass
|
||||
});
|
||||
|
||||
// HTTPS server options.
|
||||
const options = {
|
||||
key: fs.readFileSync(__dirname + '/../data/server.key'),
|
||||
cert: fs.readFileSync(__dirname + '/../data/server.crt'),
|
||||
};
|
||||
|
||||
// Starting server.
|
||||
https
|
||||
.createServer(
|
||||
options,
|
||||
basic.check((req, res) => {
|
||||
res.end(`Welcome to private area - ${req.user}!`);
|
||||
}),
|
||||
)
|
||||
.listen(1337, () => {
|
||||
// Log URL.
|
||||
console.log('Server running at https://127.0.0.1:1337/');
|
||||
});
|
||||
29
types/http-auth/test/http-auth-tests.proxy.ts
Normal file
29
types/http-auth/test/http-auth-tests.proxy.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import * as http from 'http';
|
||||
import * as fs from 'fs';
|
||||
import * as auth from 'http-auth';
|
||||
import * as httpProxy from 'http-proxy';
|
||||
|
||||
const basic = auth.basic({
|
||||
realm: 'Simon Area.',
|
||||
file: __dirname + '/../data/users.htpasswd', // gevorg:gpass, Sarah:testpass
|
||||
proxy: true,
|
||||
});
|
||||
|
||||
// Create your proxy server.
|
||||
const proxy = httpProxy.createProxyServer({});
|
||||
http.createServer(
|
||||
basic.check((req, res) => {
|
||||
proxy.web(req, res, { target: 'http://127.0.0.1:1338' });
|
||||
}),
|
||||
).listen(1337);
|
||||
|
||||
// Create your target server.
|
||||
http.createServer((req, res) => {
|
||||
res.end('Request successfully proxied!');
|
||||
}).listen(1338, () => {
|
||||
// Log URL.
|
||||
console.log('Server running at http://127.0.0.1:1338/');
|
||||
});
|
||||
|
||||
// You can test proxy authentication using curl.
|
||||
// $ curl -x 127.0.0.1:1337 127.0.0.1:1337 -U gevorg
|
||||
25
types/http-auth/tsconfig.json
Normal file
25
types/http-auth/tsconfig.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"lib": ["es6"],
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strictFunctionTypes": true,
|
||||
"strictNullChecks": true,
|
||||
"baseUrl": "../",
|
||||
"typeRoots": ["../"],
|
||||
"types": [],
|
||||
"noEmit": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"files": [
|
||||
"index.d.ts",
|
||||
"test/http-auth-tests.basic.ts",
|
||||
"test/http-auth-tests.basic_nofile.ts",
|
||||
"test/http-auth-tests.digest.ts",
|
||||
"test/http-auth-tests.digest_nofile.ts",
|
||||
"test/http-auth-tests.events.ts",
|
||||
"test/http-auth-tests.https.ts",
|
||||
"test/http-auth-tests.proxy.ts"
|
||||
]
|
||||
}
|
||||
1
types/http-auth/tslint.json
Normal file
1
types/http-auth/tslint.json
Normal file
@ -0,0 +1 @@
|
||||
{ "extends": "dtslint/dt.json" }
|
||||
Loading…
Reference in New Issue
Block a user