diff --git a/.changeset/clean-lobsters-begin.md b/.changeset/clean-lobsters-begin.md new file mode 100644 index 0000000..4bc1b16 --- /dev/null +++ b/.changeset/clean-lobsters-begin.md @@ -0,0 +1,8 @@ +--- +"@ordermentum/express-asap": major +"@ordermentum/axios-asap": major +"@ordermentum/asap-core": major +"@ordermentum/hapi-asap": major +--- + +Upgrade axios version to 1.0 diff --git a/packages/asap-core/package.json b/packages/asap-core/package.json index a603974..ede8fc5 100644 --- a/packages/asap-core/package.json +++ b/packages/asap-core/package.json @@ -33,7 +33,7 @@ "typecheck": "yarn tsc --noEmit" }, "dependencies": { - "axios": "^0.26.1", + "axios": "^1.7.7", "express": "^4.17.3", "jsonwebtoken": "^8.5.1", "node-cache": "^5.1.2" diff --git a/packages/asap-core/src/authenticator.ts b/packages/asap-core/src/authenticator.ts index 5e7706d..b18d3da 100644 --- a/packages/asap-core/src/authenticator.ts +++ b/packages/asap-core/src/authenticator.ts @@ -127,7 +127,7 @@ export function createAsapAuthenticator({ }); } - const verifyOptions = { + const verifyOptions: jsonWebToken.VerifyOptions = { algorithms: ALLOWED_ALGORITHMS, clockTolerance: CLOCK_TOLERANCE_SECONDS, audience: resourceServerAudience, diff --git a/packages/asap-core/test/file_test.ts b/packages/asap-core/test/file_test.ts index 31cfee4..7fad4e8 100644 --- a/packages/asap-core/test/file_test.ts +++ b/packages/asap-core/test/file_test.ts @@ -1,7 +1,10 @@ import { describe, afterEach, beforeEach } from 'mocha'; import { expect } from 'chai'; import sinon from 'sinon'; -import { createPublicKeyFetcher, createTestPublicKeyFetcher } from '../src/fetchers/file'; +import { + createPublicKeyFetcher, + createTestPublicKeyFetcher, +} from '../src/fetchers/file'; describe('file', () => { let time; @@ -39,6 +42,6 @@ describe('file', () => { const key2 = await fetcher('test/service_2'); expect(key1).to.eqls(key2); }); - }) + }); }); }); diff --git a/packages/asap-core/test/generate_test.ts b/packages/asap-core/test/generate_test.ts index d83e6b0..0e9ea5f 100644 --- a/packages/asap-core/test/generate_test.ts +++ b/packages/asap-core/test/generate_test.ts @@ -137,7 +137,7 @@ describe('createAuthHeaderGenerator', () => { jwtConfig.privateKey = 'this is not a valid key'; expect(() => createAuthHeaderGenerator(jwtConfig)()).to.throw( - /PEM.*no start line/ + /DECODER routines::unsupported/ ); }); diff --git a/packages/axios-asap/package.json b/packages/axios-asap/package.json index 8755a3a..380b770 100644 --- a/packages/axios-asap/package.json +++ b/packages/axios-asap/package.json @@ -12,7 +12,6 @@ "@types/express": "4.17.13", "@types/jsonwebtoken": "8.5.8", "@types/mocha": "9.1.0", - "@types/moxios": "0.4.15", "@types/node": "17.0.21", "@types/sinon": "10.0.11", "chai": "4.3.6", @@ -21,7 +20,7 @@ "lint-staged": "12.3.5", "mocha": "9.2.2", "mocha-sinon": "2.1.2", - "moxios": "0.4.0", + "nock": "13.5.5", "sinon": "13.0.1", "ts-node": "10.7.0", "ts-node-dev": "1.1.8", @@ -35,6 +34,6 @@ }, "dependencies": { "@ordermentum/asap-core": "*", - "axios": "^0.26.1" + "axios": "^1.7.7" } } diff --git a/packages/axios-asap/src/index.ts b/packages/axios-asap/src/index.ts index 889b5e1..f23f62a 100644 --- a/packages/axios-asap/src/index.ts +++ b/packages/axios-asap/src/index.ts @@ -2,7 +2,7 @@ import { createAuthHeaderGenerator, AuthHeaderConfig, } from '@ordermentum/asap-core'; -import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'; +import axios, { AxiosInstance, AxiosRequestConfig, AxiosHeaders } from 'axios'; import http from 'http'; import https from 'https'; @@ -12,9 +12,13 @@ export const createAsapInterceptor = (authConfig: AuthHeaderConfig) => { }); return (config: AxiosRequestConfig) => { const header = headerGenerator(); - const headers = config.headers ?? {}; - headers.Authorization = header; - return { ...config, headers }; + // @ts-expect-error RawAxiosHeaders is not accessible for type defs + const headers: AxiosHeaders = new AxiosHeaders(config.headers ?? {}); + headers.set('Authorization', header); + return { + ...config, + headers, + }; }; }; @@ -30,7 +34,7 @@ const getDefaultAxiosConfig = (): AxiosRequestConfig => { if (!httpsAgent) { httpsAgent = new https.Agent({ keepAlive: true }); } - return { httpAgent, httpsAgent } + return { httpAgent, httpsAgent }; }; export type Options = { diff --git a/packages/axios-asap/test/index_test.ts b/packages/axios-asap/test/index_test.ts index 71f74be..e88eed3 100644 --- a/packages/axios-asap/test/index_test.ts +++ b/packages/axios-asap/test/index_test.ts @@ -1,6 +1,6 @@ import { describe, beforeEach } from 'mocha'; import axios from 'axios'; -import moxios from 'moxios'; +import nock from 'nock'; import { expect } from 'chai'; import { privateKeyPem } from '@ordermentum/asap-test-helpers'; import { createAsapInterceptor, createClient } from '../src'; @@ -19,14 +19,10 @@ describe('createAuthHeaderGenerator', () => { it('sets the header', async () => { const client = axios.create(); - moxios.install(client); client.interceptors.request.use(createAsapInterceptor(jwtConfig)); - moxios.stubRequest('/say/hello', { - status: 200, - responseText: 'hello', - }); + nock('http://localhost').get('/say/hello').reply(200, 'hello'); - const res = await client.get('/say/hello'); + const res = await client.get('http://localhost/say/hello'); expect(res.status).to.equal(200); expect(Object.keys(res?.config?.headers ?? {})).to.include('Authorization'); expect(res?.config?.headers?.Authorization).to.include('Bearer'); @@ -49,13 +45,9 @@ describe('createAuthHeaderGenerator', () => { } ); - moxios.install(client); - moxios.stubRequest('/say/hello', { - status: 200, - responseText: 'hello', - }); + nock('http://localhost').get('/say/hello').reply(200, 'hello'); - const res = await client.get('/say/hello'); + const res = await client.get('http://localhost/say/hello'); expect(res.status).to.equal(200); expect(Object.keys(res?.config?.headers ?? {})).to.include('Authorization'); expect(res?.config?.headers?.Authorization).to.include('Bearer'); @@ -151,5 +143,5 @@ describe('createAuthHeaderGenerator', () => { expect(client1).to.equal(client2); expect(client1.defaults.headers['x-custom-header']).to.equal('1'); expect(client2.defaults.headers['x-custom-header']).to.equal('1'); - }) + }); }); diff --git a/packages/express-asap/package.json b/packages/express-asap/package.json index 092c9e1..42d209b 100644 --- a/packages/express-asap/package.json +++ b/packages/express-asap/package.json @@ -35,7 +35,6 @@ }, "dependencies": { "@ordermentum/asap-core": "*", - "axios": "^0.26.1", "express": "^4.17.3", "jsonwebtoken": "^8.5.1" } diff --git a/packages/express-asap/test/index_test.ts b/packages/express-asap/test/index_test.ts index ae6cab1..72e653c 100644 --- a/packages/express-asap/test/index_test.ts +++ b/packages/express-asap/test/index_test.ts @@ -8,13 +8,22 @@ import createAsapAuthenticationMiddleware from '../src/middleware'; import createAsapIssuerWhitelistMiddleware from '../src/whitelist_middleware'; const app = express(); -app.use( - createAsapAuthenticationMiddleware({ - keyLoader: (_key: string) => Promise.resolve(publicKey), - resourceServerAudience: 'test', - maxLifeTimeSeconds: 60, - }) -); +app + .use( + createAsapAuthenticationMiddleware({ + keyLoader: (_key: string) => Promise.resolve(publicKey), + resourceServerAudience: 'test', + maxLifeTimeSeconds: 60, + }) + ) + .use((req, res, next) => { + // @ts-ignore + if (req.headers.authorization && req.locals?.asapClaims === undefined) { + res.status(401).send('Did not authenticate'); + } else { + next(); + } + }); app.get('/', (_req, res) => { res.status(200); @@ -43,7 +52,7 @@ describe('middleware', () => { tokenExpiryMs: 60 * 1000, }; - const authHeader = createAuthHeaderGenerator(jwtConfig)(); + const authHeader = createAuthHeaderGenerator(jwtConfig)({ admin: true }); const res = await agent.get('/').set('Authorization', authHeader); expect(res.status).to.equal(200); expect(res.text).to.equal('OK'); @@ -58,7 +67,7 @@ describe('middleware', () => { tokenExpiryMs: 60 * 1000, }; - const authHeader = createAuthHeaderGenerator(jwtConfig)(); + const authHeader = createAuthHeaderGenerator(jwtConfig)({ admin: true }); const res = await agent.get('/').set('Authorization', authHeader); expect(res.status).to.equal(401); }); @@ -77,7 +86,7 @@ describe('middleware', () => { return res.send('OK'); }); - const authHeader = createAuthHeaderGenerator(jwtConfig)(); + const authHeader = createAuthHeaderGenerator(jwtConfig)({ admin: true }); const res = await agent.get('/protected').set('Authorization', authHeader); expect(res.status).to.equal(401); }); diff --git a/packages/hapi-asap/package.json b/packages/hapi-asap/package.json index 624074f..17c7227 100644 --- a/packages/hapi-asap/package.json +++ b/packages/hapi-asap/package.json @@ -37,7 +37,6 @@ "@hapi/boom": "^10.0.0", "@hapi/hapi": "^20.2.2", "@ordermentum/asap-core": "*", - "axios": "^0.26.1", "express": "^4.17.3", "jsonwebtoken": "^8.5.1" } diff --git a/packages/hapi-asap/src/middleware.ts b/packages/hapi-asap/src/middleware.ts index 8a0b1c9..514cce0 100644 --- a/packages/hapi-asap/src/middleware.ts +++ b/packages/hapi-asap/src/middleware.ts @@ -47,10 +47,7 @@ const implementation = (_server: Hapi.Server, options?: any) => { * @param opts AuthenticatorOptions * */ -const register = ( - server: Hapi.Server, - options: AuthenticatorOptions -) => { +const register = (server: Hapi.Server, options: AuthenticatorOptions) => { server.auth.scheme('hapi-asap', implementation); server.auth.strategy('hapi-asap', 'hapi-asap', options); }; @@ -60,10 +57,6 @@ const plugin: Hapi.Plugin = { pkg: { name: 'ASAP Authentication', version: '0.1.0' }, }; -export { - register, - AuthenticatorOptions, - plugin -} +export { register, AuthenticatorOptions, plugin }; export default plugin; diff --git a/packages/hapi-asap/test/index_test.ts b/packages/hapi-asap/test/index_test.ts index ef4d68b..6d0be4a 100644 --- a/packages/hapi-asap/test/index_test.ts +++ b/packages/hapi-asap/test/index_test.ts @@ -3,16 +3,24 @@ import { expect } from 'chai'; import { createAuthHeaderGenerator } from '@ordermentum/asap-core'; import { publicKey, privateKeyPem } from '@ordermentum/asap-test-helpers'; import Hapi from '@hapi/hapi'; -import registerPlugin from '../src/middleware'; +import { plugin as hapiAsap } from '../src/middleware'; async function init() { const server = Hapi.server({ - port: 3000, + port: 10000, host: 'localhost', }); - await server.register(registerPlugin); + await server.register({ + plugin: hapiAsap, + options: { + keyLoader: (_key: string) => Promise.resolve(publicKey), + resourceServerAudience: 'test', + maxLifeTimeSeconds: 60, + }, + }); + // await server.register(registerPlugin); server.auth.strategy('asap', 'hapi-asap', { keyLoader: (_key: string) => Promise.resolve(publicKey), resourceServerAudience: 'test', @@ -35,6 +43,7 @@ async function init() { return `Ok`; } + // @ts-expect-error return `${asapClaims?.aud}`; }, }); @@ -50,6 +59,7 @@ async function init() { path: '/required', handler(request, h) { const { asapClaims } = request.auth.artifacts ?? {}; + // @ts-expect-error return `test ${asapClaims?.aud}`; }, }); diff --git a/yarn.lock b/yarn.lock index 10b17fb..650850b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1001,13 +1001,6 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== -"@types/moxios@0.4.15": - version "0.4.15" - resolved "https://registry.yarnpkg.com/@types/moxios/-/moxios-0.4.15.tgz#d8b774f360ba652801b5807e0833f6ff30a17770" - integrity sha512-eHD7i0/Uu7pFGzS4uIed2InJLj5H6xOOsqPjGtRyvyC/jnzRt6q6Xtnm2PQlkcqKHjRybEqjw71dcPnzfDouhw== - dependencies: - axios ">=0.13.0" - "@types/node-cache@4.2.5": version "4.2.5" resolved "https://registry.yarnpkg.com/@types/node-cache/-/node-cache-4.2.5.tgz#dac6be8bf8f486db4eef66f52f7bb9e90b65d2c1" @@ -1375,12 +1368,14 @@ axe-core@^4.0.2: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.1.tgz#7dbdc25989298f9ad006645cd396782443757413" integrity sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw== -axios@>=0.13.0, axios@^0.26.1: - version "0.26.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" - integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== +axios@^1.7.7: + version "1.7.7" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" + integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== dependencies: - follow-redirects "^1.14.8" + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" axobject-query@^2.2.0: version "2.2.0" @@ -2464,10 +2459,10 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== -follow-redirects@^1.14.8: - version "1.14.9" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" - integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== +follow-redirects@^1.15.6: + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== form-data@^4.0.0: version "4.0.0" @@ -2992,6 +2987,11 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -3426,11 +3426,6 @@ mocha@9.2.2, mocha@^9.2.2: yargs-parser "20.2.4" yargs-unparser "2.0.0" -moxios@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/moxios/-/moxios-0.4.0.tgz#fc0da2c65477d725ca6b9679d58370ed0c52f53b" - integrity sha1-/A2ixlR31yXKa5Z51YNw7QxS9Ts= - mri@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" @@ -3482,6 +3477,15 @@ nise@^5.1.1: just-extend "^4.0.2" path-to-regexp "^1.7.0" +nock@13.5.5: + version "13.5.5" + resolved "https://registry.yarnpkg.com/nock/-/nock-13.5.5.tgz#cd1caaca281d42be17d51946367a3d53a6af3e78" + integrity sha512-XKYnqUrCwXC8DGG1xX4YH5yNIrlh9c065uaMZZHUoeUUINTOyt+x/G+ezYk0Ft6ExSREVIs+qBJDK503viTfFA== + dependencies: + debug "^4.1.0" + json-stringify-safe "^5.0.1" + propagate "^2.0.0" + node-cache@*, node-cache@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-5.1.2.tgz#f264dc2ccad0a780e76253a694e9fd0ed19c398d" @@ -3854,6 +3858,11 @@ prop-types@^15.7.2: object-assign "^4.1.1" react-is "^16.13.1" +propagate@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" + integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -3862,6 +3871,11 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"