Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 0 additions & 139 deletions src/auth.spec.ts

This file was deleted.

94 changes: 25 additions & 69 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,74 +8,43 @@

import { Buffer } from 'node:buffer';

export = auth;
/**
* Object to represent user credentials.
*/
export interface Credentials {
name: string;
pass: string;
}

/**
* Parse the Authorization header field of a request
* Parse basic auth to object.
*
* @param {string} string
* @return {object}
* @public
*/

function auth(req: auth.IncomingMessageLike): auth.Credentials | undefined {
if (!req) {
throw new TypeError('argument req is required');
export function parse(string: string): Credentials | undefined {
if (typeof string !== 'string') {
return undefined;
}

if (typeof req !== 'object') {
throw new TypeError('argument req is required to be an object');
}

// get header
const header = getAuthorization(req);

// parse header
return auth.parse(header ?? '');
}
const match = CREDENTIALS_REGEXP.exec(string);

namespace auth {
/**
* Object to represent user credentials.
*/
export interface Credentials {
name: string;
pass: string;
if (!match) {
return undefined;
}

export interface IncomingMessageLike {
headers?: {
authorization?: string;
};
}

/**
* Parse basic auth to object.
*
* @param {string} string
* @return {object}
* @public
*/

export function parse(string: string): auth.Credentials | undefined {
if (typeof string !== 'string') {
return undefined;
}
// decode user pass
const userPass = USER_PASS_REGEXP.exec(decodeBase64(match[1]));

// parse header
const match = CREDENTIALS_REGEXP.exec(string);

if (!match) {
return undefined;
}

// decode user pass
const userPass = USER_PASS_REGEXP.exec(decodeBase64(match[1]));

if (!userPass) {
return undefined;
}

// return credentials object
return new CredentialsImpl(userPass[1], userPass[2]);
if (!userPass) {
return undefined;
}

// return credentials object
return new CredentialsImpl(userPass[1], userPass[2]);
}

/**
Expand Down Expand Up @@ -110,20 +79,7 @@ function decodeBase64(str: string): string {
return Buffer.from(str, 'base64').toString();
}

/**
* Get the Authorization header from request object.
* @private
*/

function getAuthorization(req: auth.IncomingMessageLike) {
if (!req.headers || typeof req.headers !== 'object') {
throw new TypeError('argument req is required to have headers property');
}

return req.headers.authorization;
}

class CredentialsImpl implements auth.Credentials {
class CredentialsImpl implements Credentials {
name: string;
pass: string;

Expand Down
39 changes: 14 additions & 25 deletions src/parse.spec.ts
Original file line number Diff line number Diff line change
@@ -1,101 +1,90 @@
import { describe, it, assert } from 'vitest';
import auth from './index';
import { parse } from './index';

function request(authorization: string) {
return {
headers: {
authorization: authorization,
},
};
}

describe('auth.parse(string)', function () {
describe('parse(string)', function () {
describe('with undefined string', function () {
it('should return undefined', function () {
assert.strictEqual((auth as any).parse(), undefined);
assert.strictEqual((parse as any)(), undefined);
});
});

describe('with malformed string', function () {
it('should return undefined', function () {
assert.strictEqual(auth.parse('Something'), undefined);
assert.strictEqual(parse('Something'), undefined);
});
});

describe('with malformed scheme', function () {
it('should return undefined', function () {
assert.strictEqual(auth.parse('basic_Zm9vOmJhcg=='), undefined);
assert.strictEqual(parse('basic_Zm9vOmJhcg=='), undefined);
});
});

describe('with malformed credentials', function () {
it('should return undefined', function () {
assert.strictEqual(auth.parse('basic Zm9vcgo='), undefined);
assert.strictEqual(parse('basic Zm9vcgo='), undefined);
});
});

describe('with valid credentials', function () {
it('should return .name and .pass', function () {
var creds = auth.parse('basic Zm9vOmJhcg==');
var creds = parse('basic Zm9vOmJhcg==');
assert.strictEqual(creds?.name, 'foo');
assert.strictEqual(creds?.pass, 'bar');
});
});

describe('with empty password', function () {
it('should return .name and .pass', function () {
var creds = auth.parse('basic Zm9vOg==');
var creds = parse('basic Zm9vOg==');
assert.strictEqual(creds?.name, 'foo');
assert.strictEqual(creds?.pass, '');
});
});

describe('with empty userid', function () {
it('should return .name and .pass', function () {
var creds = auth.parse('basic OnBhc3M=');
var creds = parse('basic OnBhc3M=');
assert.strictEqual(creds?.name, '');
assert.strictEqual(creds?.pass, 'pass');
});
});

describe('with empty userid and pass', function () {
it('should return .name and .pass', function () {
var creds = auth.parse('basic Og==');
var creds = parse('basic Og==');
assert.strictEqual(creds?.name, '');
assert.strictEqual(creds?.pass, '');
});
});

describe('with colon in pass', function () {
it('should return .name and .pass', function () {
var creds = auth.parse('basic Zm9vOnBhc3M6d29yZA==');
var creds = parse('basic Zm9vOnBhc3M6d29yZA==');
assert.strictEqual(creds?.name, 'foo');
assert.strictEqual(creds?.pass, 'pass:word');
});
});

describe('with scheme "Basic"', function () {
it('should return .name and .pass', function () {
var req = request('Basic Zm9vOmJhcg==');
var creds = auth(req);
var creds = parse('Basic Zm9vOmJhcg==');
assert.strictEqual(creds?.name, 'foo');
assert.strictEqual(creds?.pass, 'bar');
});
});

describe('with scheme "BASIC"', function () {
it('should return .name and .pass', function () {
var req = request('BASIC Zm9vOmJhcg==');
var creds = auth(req);
var creds = parse('BASIC Zm9vOmJhcg==');
assert.strictEqual(creds?.name, 'foo');
assert.strictEqual(creds?.pass, 'bar');
});
});

describe('with scheme "BaSiC"', function () {
it('should return .name and .pass', function () {
var req = request('BaSiC Zm9vOmJhcg==');
var creds = auth(req);
var creds = parse('BaSiC Zm9vOmJhcg==');
assert.strictEqual(creds?.name, 'foo');
assert.strictEqual(creds?.pass, 'bar');
});
Expand Down
Loading