Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

http-auth-utils

Package Overview
Dependencies
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

http-auth-utils - npm Package Compare versions

Comparing version 3.0.5 to 4.0.0

11

CHANGELOG.md

@@ -0,1 +1,12 @@

# [4.0.0](https://github.com/nfroidure/http-auth-utils/compare/v3.0.5...v4.0.0) (2023-03-09)
### Bug Fixes
* **src/utils.ts:** handle parsing values with equal signs ([e640f21](https://github.com/nfroidure/http-auth-utils/commit/e640f21e9cd4115831eb968aabbe4c384c0f03ce)), closes [#17](https://github.com/nfroidure/http-auth-utils/issues/17)
* **src/utils.ts:** normalize keys to lowercase ([bfb33f4](https://github.com/nfroidure/http-auth-utils/commit/bfb33f4c22f6596258343505ecdd5205d9a75309))
* **src/utils.ts:** normalize stale value to lowercase ([8d10f8c](https://github.com/nfroidure/http-auth-utils/commit/8d10f8c0da0599eb48df746ebfadb9092760c93b))
## [3.0.5](https://github.com/nfroidure/http-auth-utils/compare/v3.0.4...v3.0.5) (2023-01-05)

@@ -2,0 +13,0 @@

2

dist/index.d.ts
import BASIC from './mechanisms/basic.js';
import DIGEST from './mechanisms/digest.js';
import BEARER from './mechanisms/bearer.js';
export declare type Mechanism = {
export type Mechanism = {
type: string;

@@ -6,0 +6,0 @@ parseWWWAuthenticateRest(rest: string): Record<string, string>;

/**
* @module http-auth-utils/mechanisms/basic
*/
declare type BasicWWWAuthenticateData = {
type BasicWWWAuthenticateData = {
realm: string;
};
declare type BasicAuthorizationData = {
type BasicAuthorizationData = {
username: string;

@@ -9,0 +9,0 @@ password: string;

@@ -5,9 +5,9 @@ /**

declare const AUTHORIZED_ERROR_CODES: readonly ["invalid_request", "invalid_token", "insufficient_scope"];
declare type BearerWWWAuthenticateData = {
type BearerWWWAuthenticateData = {
realm: string;
scope?: string;
error?: typeof AUTHORIZED_ERROR_CODES[number];
error?: (typeof AUTHORIZED_ERROR_CODES)[number];
error_description?: string;
};
declare type BearerAuthorizationData = {
type BearerAuthorizationData = {
hash: string;

@@ -14,0 +14,0 @@ };

/**
* @module http-auth-utils/mechanisms/digest
*/
declare type DigestWWWAuthenticateData = {
type DigestWWWAuthenticateData = {
realm: string;

@@ -13,3 +13,3 @@ domain?: string;

};
declare type DigestAuthorizationData = {
type DigestAuthorizationData = {
username: string;

@@ -61,3 +61,3 @@ realm: string;

* Build the WWW Authenticate header rest.
* @param {Object} data The content from wich to build the rest.
* @param {Object} data The content from which to build the rest.
* @return {String} The built rest.

@@ -113,3 +113,3 @@ * @example

* Build the Authorization header rest.
* @param {Object} data The content from wich to build the rest.
* @param {Object} data The content from which to build the rest.
* @return {String} The rest built.

@@ -116,0 +116,0 @@ * @example

@@ -15,2 +15,3 @@ /**

];
const CASE_INSENSITIVE_WWW_AUTHENTICATE_VALUES = ['stale'];
const REQUIRED_AUTHORIZATION_KEYS = [

@@ -69,7 +70,7 @@ 'username',

parseWWWAuthenticateRest: function parseWWWAuthenticateRest(rest) {
return parseHTTPHeadersQuotedKeyValueSet(rest, AUTHORIZED_WWW_AUTHENTICATE_KEYS, REQUIRED_WWW_AUTHENTICATE_KEYS);
return parseHTTPHeadersQuotedKeyValueSet(rest, AUTHORIZED_WWW_AUTHENTICATE_KEYS, REQUIRED_WWW_AUTHENTICATE_KEYS, CASE_INSENSITIVE_WWW_AUTHENTICATE_VALUES);
},
/**
* Build the WWW Authenticate header rest.
* @param {Object} data The content from wich to build the rest.
* @param {Object} data The content from which to build the rest.
* @return {String} The built rest.

@@ -129,3 +130,3 @@ * @example

* Build the Authorization header rest.
* @param {Object} data The content from wich to build the rest.
* @param {Object} data The content from which to build the rest.
* @return {String} The rest built.

@@ -132,0 +133,0 @@ * @example

@@ -1,2 +0,2 @@

export declare function parseHTTPHeadersQuotedKeyValueSet(contents: string, authorizedKeys: string[], requiredKeys?: string[]): Record<string, string>;
export declare function parseHTTPHeadersQuotedKeyValueSet(contents: string, authorizedKeys: string[], requiredKeys?: string[], valuesToNormalize?: string[]): Record<string, string>;
export declare function buildHTTPHeadersQuotedKeyValueSet(data: Record<string, string>, authorizedKeys: string[], requiredKeys?: string[]): string;

@@ -17,3 +17,3 @@ import { YError } from 'yerror';

// FIXME: Create a real parser
export function parseHTTPHeadersQuotedKeyValueSet(contents, authorizedKeys, requiredKeys = []) {
export function parseHTTPHeadersQuotedKeyValueSet(contents, authorizedKeys, requiredKeys = [], valuesToNormalize = []) {
const matches = contents.trim().match(KEYVALUE_REGEXP);

@@ -24,11 +24,13 @@ if (!matches)

.map((part, partPosition) => {
const pair = part.split(EQUAL);
if (2 !== pair.length) {
throw new YError('E_MALFORMED_QUOTEDKEYVALUE', partPosition, part, pair.length);
const [key, ...rest] = part.split(EQUAL);
const value = rest.join(EQUAL);
if (0 === rest.length) {
throw new YError('E_MALFORMED_QUOTEDKEYVALUE', partPosition, part);
}
return pair;
return [key, value];
})
.reduce(function (parsedValues, [name, value], valuePosition) {
if (-1 === authorizedKeys.indexOf(name)) {
throw new YError('E_UNAUTHORIZED_KEY', valuePosition, name);
const normalizedName = name.toLowerCase();
if (-1 === authorizedKeys.indexOf(normalizedName)) {
throw new YError('E_UNAUTHORIZED_KEY', valuePosition, normalizedName);
}

@@ -46,3 +48,6 @@ /*

*/
parsedValues[name] = value.replace(/^"(.+(?="$))"$/, '$1');
const strippedValue = value.replace(/^"(.+(?="$))"$/, '$1');
parsedValues[normalizedName] = valuesToNormalize.includes(normalizedName)
? strippedValue.toLowerCase()
: strippedValue;
return parsedValues;

@@ -49,0 +54,0 @@ }, {});

@@ -18,2 +18,13 @@ import { describe, test } from '@jest/globals';

});
test('should work with equals in key values', () => {
neatequal(parseHTTPHeadersQuotedKeyValueSet('realm="testrealm@host.com", ' +
'qop="auth, auth-int", ' +
'nonce="dGVzdCBzdHJpbmc=", ' +
'opaque="5ccc069c403ebaf9f0171e9517f40e41"', ['realm', 'qop', 'nonce', 'opaque'], ['realm', 'qop', 'nonce', 'opaque']), {
realm: 'testrealm@host.com',
qop: 'auth, auth-int',
nonce: 'dGVzdCBzdHJpbmc=',
opaque: '5ccc069c403ebaf9f0171e9517f40e41',
});
});
test('should work with parse-able non-quoted data', () => {

@@ -30,2 +41,28 @@ neatequal(parseHTTPHeadersQuotedKeyValueSet('realm="testrealm@host.com", ' +

});
test('should normalize all keys to lowercase', () => {
neatequal(parseHTTPHeadersQuotedKeyValueSet('Realm="testrealm@host.com", ' +
'qop="auth, auth-int", ' +
'nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", ' +
'opaque="5ccc069c403ebaf9f0171e9517f40e41", ' +
'Stale="false"', ['realm', 'qop', 'nonce', 'opaque', 'stale'], ['realm', 'qop', 'nonce', 'opaque', 'stale']), {
realm: 'testrealm@host.com',
qop: 'auth, auth-int',
nonce: 'dcd98b7102dd2f0e8b11d0f600bfb0c093',
opaque: '5ccc069c403ebaf9f0171e9517f40e41',
stale: 'false',
});
});
test('should normalize values to lowercase for given keys', () => {
neatequal(parseHTTPHeadersQuotedKeyValueSet('realm="testrealm-UPPERCASE@host.com", ' +
'qop="auth, auth-int", ' +
'nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", ' +
'opaque="5ccc069c403ebaf9f0171e9517f40e41", ' +
'stale=TRUE', ['realm', 'qop', 'nonce', 'opaque', 'stale'], ['realm', 'qop', 'nonce', 'opaque', 'stale'], ['stale']), {
realm: 'testrealm-UPPERCASE@host.com',
qop: 'auth, auth-int',
nonce: 'dcd98b7102dd2f0e8b11d0f600bfb0c093',
opaque: '5ccc069c403ebaf9f0171e9517f40e41',
stale: 'true',
});
});
test('should fail with bad quoted value pair', () => {

@@ -32,0 +69,0 @@ assert.throws(() => parseHTTPHeadersQuotedKeyValueSet('realm', []), /E_MALFORMED_QUOTEDKEYVALUE/);

{
"name": "http-auth-utils",
"version": "3.0.5",
"description": "Parse, build and deal with HTTP authorization headers.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"metapak": {

@@ -32,5 +27,10 @@ "data": {

},
"name": "http-auth-utils",
"version": "4.0.0",
"description": "Parse, build and deal with HTTP authorization headers.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"architecture": "jsarch 'src/**/*.ts' > ARCHITECTURE.md && git add ARCHITECTURE.md",
"build": "rimraf -f 'dist' && tsc --outDir dist",
"build": "rimraf 'dist' && tsc --outDir dist",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md",

@@ -76,22 +76,23 @@ "cli": "env NODE_ENV=${NODE_ENV:-cli}",

"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.36.0",
"@typescript-eslint/parser": "^5.36.0",
"commitizen": "^4.2.5",
"@types/node": "^18.14.6",
"@typescript-eslint/eslint-plugin": "^5.54.1",
"@typescript-eslint/parser": "^5.54.1",
"commitizen": "^4.3.0",
"conventional-changelog-cli": "^2.2.2",
"coveralls": "^3.1.1",
"cz-conventional-changelog": "^3.3.0",
"esbuild": "^0.15.6",
"esbuild": "^0.17.11",
"esbuild-jest": "^0.5.0",
"eslint": "^8.23.0",
"eslint-config-prettier": "^8.5.0",
"eslint": "^8.35.0",
"eslint-config-prettier": "^8.7.0",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^29.0.1",
"jest": "^29.5.0",
"jsarch": "^6.0.0",
"jsdoc-to-markdown": "^7.1.1",
"jsdoc-to-markdown": "^8.0.0",
"metapak": "^4.0.6",
"metapak-nfroidure": "13.0.0",
"metapak-nfroidure": "13.1.1",
"neatequal": "^1.0.0",
"prettier": "^2.7.1",
"rimraf": "^3.0.2",
"typescript": "^4.8.2"
"prettier": "^2.8.4",
"rimraf": "^4.4.0",
"typescript": "^4.9.5"
},

@@ -133,2 +134,7 @@ "dependencies": {

"url": "https://github.com/jakepruitt"
},
{
"name": "Corentin Girard",
"email": "corentin.girard@datadoghq.com",
"url": "https://github.com/Drarig29"
}

@@ -135,0 +141,0 @@ ],

@@ -541,3 +541,3 @@ [//]: # ( )

| --- | --- | --- |
| data | <code>Object</code> | The content from wich to build the rest. |
| data | <code>Object</code> | The content from which to build the rest. |

@@ -609,3 +609,3 @@ **Example**

| --- | --- | --- |
| data | <code>Object</code> | The content from wich to build the rest. |
| data | <code>Object</code> | The content from which to build the rest. |

@@ -672,4 +672,5 @@ **Example**

- [Jake Pruitt](https://github.com/jakepruitt)
- [Corentin Girard](https://github.com/Drarig29)
# License
[MIT](https://github.com/nfroidure/http-auth-utils/blob/master/LICENSE)

@@ -27,3 +27,3 @@ /**

scope?: string;
error?: typeof AUTHORIZED_ERROR_CODES[number];
error?: (typeof AUTHORIZED_ERROR_CODES)[number];
error_description?: string;

@@ -35,3 +35,3 @@ };

type BearerAuthorizedErrorCodes = typeof AUTHORIZED_ERROR_CODES[number];
type BearerAuthorizedErrorCodes = (typeof AUTHORIZED_ERROR_CODES)[number];

@@ -38,0 +38,0 @@ /* Architecture Note #1.1: Bearer mechanism

@@ -21,2 +21,3 @@ /**

];
const CASE_INSENSITIVE_WWW_AUTHENTICATE_VALUES = ['stale'];
type DigestWWWAuthenticateData = {

@@ -105,2 +106,3 @@ realm: string;

REQUIRED_WWW_AUTHENTICATE_KEYS,
CASE_INSENSITIVE_WWW_AUTHENTICATE_VALUES,
) as DigestWWWAuthenticateData;

@@ -111,3 +113,3 @@ },

* Build the WWW Authenticate header rest.
* @param {Object} data The content from wich to build the rest.
* @param {Object} data The content from which to build the rest.
* @return {String} The built rest.

@@ -181,3 +183,3 @@ * @example

* Build the Authorization header rest.
* @param {Object} data The content from wich to build the rest.
* @param {Object} data The content from which to build the rest.
* @return {String} The rest built.

@@ -184,0 +186,0 @@ * @example

@@ -30,2 +30,21 @@ import { describe, test } from '@jest/globals';

test('should work with equals in key values', () => {
neatequal(
parseHTTPHeadersQuotedKeyValueSet(
'realm="testrealm@host.com", ' +
'qop="auth, auth-int", ' +
'nonce="dGVzdCBzdHJpbmc=", ' +
'opaque="5ccc069c403ebaf9f0171e9517f40e41"',
['realm', 'qop', 'nonce', 'opaque'],
['realm', 'qop', 'nonce', 'opaque'],
),
{
realm: 'testrealm@host.com',
qop: 'auth, auth-int',
nonce: 'dGVzdCBzdHJpbmc=',
opaque: '5ccc069c403ebaf9f0171e9517f40e41',
},
);
});
test('should work with parse-able non-quoted data', () => {

@@ -50,2 +69,45 @@ neatequal(

test('should normalize all keys to lowercase', () => {
neatequal(
parseHTTPHeadersQuotedKeyValueSet(
'Realm="testrealm@host.com", ' +
'qop="auth, auth-int", ' +
'nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", ' +
'opaque="5ccc069c403ebaf9f0171e9517f40e41", ' +
'Stale="false"',
['realm', 'qop', 'nonce', 'opaque', 'stale'],
['realm', 'qop', 'nonce', 'opaque', 'stale'],
),
{
realm: 'testrealm@host.com',
qop: 'auth, auth-int',
nonce: 'dcd98b7102dd2f0e8b11d0f600bfb0c093',
opaque: '5ccc069c403ebaf9f0171e9517f40e41',
stale: 'false',
},
);
});
test('should normalize values to lowercase for given keys', () => {
neatequal(
parseHTTPHeadersQuotedKeyValueSet(
'realm="testrealm-UPPERCASE@host.com", ' +
'qop="auth, auth-int", ' +
'nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", ' +
'opaque="5ccc069c403ebaf9f0171e9517f40e41", ' +
'stale=TRUE',
['realm', 'qop', 'nonce', 'opaque', 'stale'],
['realm', 'qop', 'nonce', 'opaque', 'stale'],
['stale'],
),
{
realm: 'testrealm-UPPERCASE@host.com', // should not be changed
qop: 'auth, auth-int',
nonce: 'dcd98b7102dd2f0e8b11d0f600bfb0c093',
opaque: '5ccc069c403ebaf9f0171e9517f40e41',
stale: 'true',
},
);
});
test('should fail with bad quoted value pair', () => {

@@ -52,0 +114,0 @@ assert.throws(

@@ -24,2 +24,3 @@ import { YError } from 'yerror';

requiredKeys: string[] = [],
valuesToNormalize: string[] = [],
): Record<string, string> {

@@ -31,18 +32,15 @@ const matches = contents.trim().match(KEYVALUE_REGEXP);

.map((part, partPosition) => {
const pair = part.split(EQUAL);
if (2 !== pair.length) {
throw new YError(
'E_MALFORMED_QUOTEDKEYVALUE',
partPosition,
part,
pair.length,
);
const [key, ...rest] = part.split(EQUAL);
const value = rest.join(EQUAL);
if (0 === rest.length) {
throw new YError('E_MALFORMED_QUOTEDKEYVALUE', partPosition, part);
}
return pair;
return [key, value];
})
.reduce(function (parsedValues, [name, value], valuePosition) {
if (-1 === authorizedKeys.indexOf(name)) {
throw new YError('E_UNAUTHORIZED_KEY', valuePosition, name);
const normalizedName = name.toLowerCase();
if (-1 === authorizedKeys.indexOf(normalizedName)) {
throw new YError('E_UNAUTHORIZED_KEY', valuePosition, normalizedName);
}
/*

@@ -59,3 +57,8 @@ * Regular expression for stripping paired starting and ending double quotes off the value:

*/
parsedValues[name] = value.replace(/^"(.+(?="$))"$/, '$1');
const strippedValue = value.replace(/^"(.+(?="$))"$/, '$1');
parsedValues[normalizedName] = valuesToNormalize.includes(normalizedName)
? strippedValue.toLowerCase()
: strippedValue;
return parsedValues;

@@ -62,0 +65,0 @@ }, {});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc