From 1e7f42f20af058fbb961233023bd242ce45379b3 Mon Sep 17 00:00:00 2001 From: David Jimenez Barrantes Date: Thu, 23 Nov 2023 14:09:12 -0600 Subject: [PATCH] [RND-663] Allow case insensitivity in OAuth requests (#328) * Allow case insensitivity in OAuth requests * v0.4.0-pre.4 * removes second it con test description. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../package.json | 6 +-- .../meadowlark-mongodb-backend/package.json | 8 +-- .../package.json | 6 +-- .../package.json | 8 +-- Meadowlark-js/lerna.json | 2 +- Meadowlark-js/package-lock.json | 50 +++++++++---------- .../meadowlark-authz-server/package.json | 4 +- .../packages/meadowlark-core/package.json | 4 +- .../meadowlark-utilities/package.json | 2 +- .../services/meadowlark-fastify/package.json | 8 +-- .../meadowlark-fastify/src/Service.ts | 1 + .../meadowlark-fastify/test/Get.test.ts | 43 ++++------------ Meadowlark-js/tests/e2e/package.json | 4 +- .../AuthenticationValidation.test.ts | 23 +++++++++ .../scenarios/AuthorizationValidation.test.ts | 38 +++++++++++--- 15 files changed, 117 insertions(+), 90 deletions(-) diff --git a/Meadowlark-js/backends/meadowlark-elasticsearch-backend/package.json b/Meadowlark-js/backends/meadowlark-elasticsearch-backend/package.json index 01f00de0..17d78799 100644 --- a/Meadowlark-js/backends/meadowlark-elasticsearch-backend/package.json +++ b/Meadowlark-js/backends/meadowlark-elasticsearch-backend/package.json @@ -1,7 +1,7 @@ { "name": "@edfi/meadowlark-elasticsearch-backend", "main": "dist/index.js", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "description": "Meadowlark backend plugin for elasticsearch", "license": "Apache-2.0", "publishConfig": { @@ -19,8 +19,8 @@ "build:copy-non-ts": "copyfiles -u 1 -e \"**/*.ts\" \"src/**/*\" dist --verbose" }, "dependencies": { - "@edfi/meadowlark-core": "0.4.0-pre.3", - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-core": "0.4.0-pre.4", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "@elastic/elasticsearch": "^8.10.0", "@elastic/transport": "^8.3.4" }, diff --git a/Meadowlark-js/backends/meadowlark-mongodb-backend/package.json b/Meadowlark-js/backends/meadowlark-mongodb-backend/package.json index c9c0c660..2fa7ce6b 100644 --- a/Meadowlark-js/backends/meadowlark-mongodb-backend/package.json +++ b/Meadowlark-js/backends/meadowlark-mongodb-backend/package.json @@ -1,7 +1,7 @@ { "name": "@edfi/meadowlark-mongodb-backend", "main": "dist/index.js", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "description": "Meadowlark backend plugin for MongoDB", "license": "Apache-2.0", "publishConfig": { @@ -19,9 +19,9 @@ "build:copy-non-ts": "copyfiles -u 1 -e \"**/*.ts\" \"src/**/*\" dist --verbose" }, "dependencies": { - "@edfi/meadowlark-authz-server": "0.4.0-pre.3", - "@edfi/meadowlark-core": "0.4.0-pre.3", - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-authz-server": "0.4.0-pre.4", + "@edfi/meadowlark-core": "0.4.0-pre.4", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "async-retry": "^1.3.3", "mongodb": "^5.9.0", "ramda": "0.29.1" diff --git a/Meadowlark-js/backends/meadowlark-opensearch-backend/package.json b/Meadowlark-js/backends/meadowlark-opensearch-backend/package.json index 36894e6f..18b960c4 100644 --- a/Meadowlark-js/backends/meadowlark-opensearch-backend/package.json +++ b/Meadowlark-js/backends/meadowlark-opensearch-backend/package.json @@ -1,7 +1,7 @@ { "name": "@edfi/meadowlark-opensearch-backend", "main": "dist/index.js", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "description": "Meadowlark backend plugin for OpenSearch", "license": "Apache-2.0", "publishConfig": { @@ -19,8 +19,8 @@ "build:copy-non-ts": "copyfiles -u 1 -e \"**/*.ts\" \"src/**/*\" dist --verbose" }, "dependencies": { - "@edfi/meadowlark-core": "0.4.0-pre.3", - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-core": "0.4.0-pre.4", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "@opensearch-project/opensearch": "^2.4.0" }, "devDependencies": { diff --git a/Meadowlark-js/backends/meadowlark-postgresql-backend/package.json b/Meadowlark-js/backends/meadowlark-postgresql-backend/package.json index 88d73d1f..872fdb85 100644 --- a/Meadowlark-js/backends/meadowlark-postgresql-backend/package.json +++ b/Meadowlark-js/backends/meadowlark-postgresql-backend/package.json @@ -1,7 +1,7 @@ { "name": "@edfi/meadowlark-postgresql-backend", "main": "dist/index.js", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "description": "Meadowlark backend plugin for PostgreSQL", "license": "Apache-2.0", "publishConfig": { @@ -19,9 +19,9 @@ "build:copy-non-ts": "copyfiles -u 1 -e \"**/*.ts\" \"src/**/*\" dist --verbose" }, "dependencies": { - "@edfi/meadowlark-authz-server": "0.4.0-pre.3", - "@edfi/meadowlark-core": "0.4.0-pre.3", - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-authz-server": "0.4.0-pre.4", + "@edfi/meadowlark-core": "0.4.0-pre.4", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "pg": "^8.11.3", "pg-format": "^1.0.4", "ramda": "0.29.1" diff --git a/Meadowlark-js/lerna.json b/Meadowlark-js/lerna.json index 576f80e2..0091af26 100644 --- a/Meadowlark-js/lerna.json +++ b/Meadowlark-js/lerna.json @@ -3,7 +3,7 @@ "packages": [ "packages/*" ], - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "npmClient": "npm", "useWorkspaces": true } diff --git a/Meadowlark-js/package-lock.json b/Meadowlark-js/package-lock.json index 406d4818..98345507 100644 --- a/Meadowlark-js/package-lock.json +++ b/Meadowlark-js/package-lock.json @@ -52,11 +52,11 @@ }, "backends/meadowlark-elasticsearch-backend": { "name": "@edfi/meadowlark-elasticsearch-backend", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "license": "Apache-2.0", "dependencies": { - "@edfi/meadowlark-core": "0.4.0-pre.3", - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-core": "0.4.0-pre.4", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "@elastic/elasticsearch": "^8.10.0", "@elastic/transport": "^8.3.4" }, @@ -70,12 +70,12 @@ }, "backends/meadowlark-mongodb-backend": { "name": "@edfi/meadowlark-mongodb-backend", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "license": "Apache-2.0", "dependencies": { - "@edfi/meadowlark-authz-server": "0.4.0-pre.3", - "@edfi/meadowlark-core": "0.4.0-pre.3", - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-authz-server": "0.4.0-pre.4", + "@edfi/meadowlark-core": "0.4.0-pre.4", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "async-retry": "^1.3.3", "mongodb": "^5.9.0", "ramda": "0.29.1" @@ -88,11 +88,11 @@ }, "backends/meadowlark-opensearch-backend": { "name": "@edfi/meadowlark-opensearch-backend", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "license": "Apache-2.0", "dependencies": { - "@edfi/meadowlark-core": "0.4.0-pre.3", - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-core": "0.4.0-pre.4", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "@opensearch-project/opensearch": "^2.4.0" }, "devDependencies": { @@ -105,12 +105,12 @@ }, "backends/meadowlark-postgresql-backend": { "name": "@edfi/meadowlark-postgresql-backend", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "license": "Apache-2.0", "dependencies": { - "@edfi/meadowlark-authz-server": "0.4.0-pre.3", - "@edfi/meadowlark-core": "0.4.0-pre.3", - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-authz-server": "0.4.0-pre.4", + "@edfi/meadowlark-core": "0.4.0-pre.4", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "pg": "^8.11.3", "pg-format": "^1.0.4", "ramda": "0.29.1" @@ -22540,11 +22540,11 @@ }, "packages/meadowlark-authz-server": { "name": "@edfi/meadowlark-authz-server", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "license": "Apache-2.0", "dependencies": { "@apideck/better-ajv-errors": "^0.3.6", - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "ajv": "^8.12.0", "dotenv": "^16.3.1", "fast-memoize": "^2.5.2", @@ -22593,11 +22593,11 @@ }, "packages/meadowlark-core": { "name": "@edfi/meadowlark-core", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "license": "Apache-2.0", "dependencies": { "@apideck/better-ajv-errors": "^0.3.6", - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "@isaacs/ttlcache": "^1.4.1", "ajv": "^8.12.0", "ajv-formats": "^2.1.1", @@ -22686,7 +22686,7 @@ }, "packages/meadowlark-utilities": { "name": "@edfi/meadowlark-utilities", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "license": "Apache-2.0", "dependencies": { "pino": "^8.15.4", @@ -22733,12 +22733,12 @@ }, "services/meadowlark-fastify": { "name": "@edfi/meadowlark-fastify", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "license": "Apache-2.0", "dependencies": { - "@edfi/meadowlark-authz-server": "0.4.0-pre.3", - "@edfi/meadowlark-core": "0.4.0-pre.3", - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-authz-server": "0.4.0-pre.4", + "@edfi/meadowlark-core": "0.4.0-pre.4", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "@fastify/rate-limit": "^6.0.1", "dotenv": "^16.3.1", "fastify": "^3.29.5" @@ -22751,10 +22751,10 @@ }, "tests/e2e": { "name": "@edfi/meadowlark-e2e-tests", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "license": "Apache-2.0", "devDependencies": { - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "@testcontainers/mongodb": "^10.2.1", "@testcontainers/postgresql": "^10.2.1", "@types/chance": "^1.1.4", diff --git a/Meadowlark-js/packages/meadowlark-authz-server/package.json b/Meadowlark-js/packages/meadowlark-authz-server/package.json index dc3a3261..d0f8ed17 100644 --- a/Meadowlark-js/packages/meadowlark-authz-server/package.json +++ b/Meadowlark-js/packages/meadowlark-authz-server/package.json @@ -1,7 +1,7 @@ { "name": "@edfi/meadowlark-authz-server", "main": "dist/index.js", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "description": "Meadowlark authorization server", "license": "Apache-2.0", "publishConfig": { @@ -14,7 +14,7 @@ ], "dependencies": { "@apideck/better-ajv-errors": "^0.3.6", - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "ajv": "^8.12.0", "dotenv": "^16.3.1", "fast-memoize": "^2.5.2", diff --git a/Meadowlark-js/packages/meadowlark-core/package.json b/Meadowlark-js/packages/meadowlark-core/package.json index b93b70a2..03d2ec2a 100644 --- a/Meadowlark-js/packages/meadowlark-core/package.json +++ b/Meadowlark-js/packages/meadowlark-core/package.json @@ -1,7 +1,7 @@ { "name": "@edfi/meadowlark-core", "main": "dist/index.js", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "description": "Meadowlark core functionality", "license": "Apache-2.0", "publishConfig": { @@ -14,7 +14,7 @@ ], "dependencies": { "@apideck/better-ajv-errors": "^0.3.6", - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "@isaacs/ttlcache": "^1.4.1", "ajv": "^8.12.0", "ajv-formats": "^2.1.1", diff --git a/Meadowlark-js/packages/meadowlark-utilities/package.json b/Meadowlark-js/packages/meadowlark-utilities/package.json index cb87bdf1..cf6cde93 100644 --- a/Meadowlark-js/packages/meadowlark-utilities/package.json +++ b/Meadowlark-js/packages/meadowlark-utilities/package.json @@ -1,7 +1,7 @@ { "name": "@edfi/meadowlark-utilities", "main": "dist/index.js", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "description": "Meadowlark shared utilities", "license": "Apache-2.0", "publishConfig": { diff --git a/Meadowlark-js/services/meadowlark-fastify/package.json b/Meadowlark-js/services/meadowlark-fastify/package.json index fbe8737b..ec5b1d9c 100644 --- a/Meadowlark-js/services/meadowlark-fastify/package.json +++ b/Meadowlark-js/services/meadowlark-fastify/package.json @@ -1,6 +1,6 @@ { "name": "@edfi/meadowlark-fastify", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "description": "Meadowlark service using Fastify", "license": "Apache-2.0", "publishConfig": { @@ -12,9 +12,9 @@ "/package.json" ], "dependencies": { - "@edfi/meadowlark-authz-server": "0.4.0-pre.3", - "@edfi/meadowlark-core": "0.4.0-pre.3", - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-authz-server": "0.4.0-pre.4", + "@edfi/meadowlark-core": "0.4.0-pre.4", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "@fastify/rate-limit": "^6.0.1", "dotenv": "^16.3.1", "fastify": "^3.29.5" diff --git a/Meadowlark-js/services/meadowlark-fastify/src/Service.ts b/Meadowlark-js/services/meadowlark-fastify/src/Service.ts index 62ba0a2f..82452431 100644 --- a/Meadowlark-js/services/meadowlark-fastify/src/Service.ts +++ b/Meadowlark-js/services/meadowlark-fastify/src/Service.ts @@ -49,6 +49,7 @@ export function buildService(): FastifyInstance { logger: Logger as FastifyLoggerInstance, disableRequestLogging: true, genReqId: () => randomUUID(), + caseSensitive: false, }); } diff --git a/Meadowlark-js/services/meadowlark-fastify/test/Get.test.ts b/Meadowlark-js/services/meadowlark-fastify/test/Get.test.ts index 2929f102..0dbf7b04 100644 --- a/Meadowlark-js/services/meadowlark-fastify/test/Get.test.ts +++ b/Meadowlark-js/services/meadowlark-fastify/test/Get.test.ts @@ -58,52 +58,29 @@ describe('given a GET', () => { }); }); - describe('given a school query without path ending slash', () => { + describe('given a school query', () => { const schoolQueryRequest: InjectOptions = { method: 'GET', - url: '/local/v3.3b/ed-fi/schools?schoolId=123', + url: '', headers: { authorization: 'bearer 1234', 'content-type': 'application/json' }, }; - beforeAll(async () => { - // Act - await service.inject(schoolQueryRequest); - }); - - it('should send the expected FrontendRequest to Meadowlark', async () => { - expect(mockGet.mock.calls).toHaveLength(1); - const mock = mockGet.mock.calls[0][0]; + it.each([ + { url: '/local/v3.3b/ed-fi/schools?schoolId=123', path: '/v3.3b/ed-fi/schools' }, + { url: '/local/v3.3b/ed-fi/schools/?schoolId=123', path: '/v3.3b/ed-fi/schools/' }, + { url: '/local/v3.3b/Ed-Fi/Schools?schoolId=123', path: '/v3.3b/Ed-Fi/Schools' }, + { url: '/local/v3.3b/ED-FI/SCHOOLS/?schoolId=123', path: '/v3.3b/ED-FI/SCHOOLS/' }, + ])('should send the expected FrontendRequest to Meadowlark', async (item) => { + schoolQueryRequest.url = item.url; - expect(mock.body).toBeNull(); - expect(mock.headers.authorization).toBe('bearer 1234'); - expect(mock.path).toBe('/v3.3b/ed-fi/schools'); - expect(mock.queryParameters).toMatchInlineSnapshot(` - { - "schoolId": "123", - } - `); - }); - }); - - describe('given a school query with path ending slash', () => { - const schoolQueryRequest: InjectOptions = { - method: 'GET', - url: '/local/v3.3b/ed-fi/schools/?schoolId=123', - headers: { authorization: 'bearer 1234', 'content-type': 'application/json' }, - }; - - beforeAll(async () => { - // Act await service.inject(schoolQueryRequest); - }); - it('should send the expected FrontendRequest to Meadowlark', async () => { expect(mockGet.mock.calls).toHaveLength(1); const mock = mockGet.mock.calls[0][0]; expect(mock.body).toBeNull(); expect(mock.headers.authorization).toBe('bearer 1234'); - expect(mock.path).toBe('/v3.3b/ed-fi/schools/'); + expect(mock.path).toBe(item.path); expect(mock.queryParameters).toMatchInlineSnapshot(` { "schoolId": "123", diff --git a/Meadowlark-js/tests/e2e/package.json b/Meadowlark-js/tests/e2e/package.json index 4d216032..54e6dffb 100644 --- a/Meadowlark-js/tests/e2e/package.json +++ b/Meadowlark-js/tests/e2e/package.json @@ -1,13 +1,13 @@ { "name": "@edfi/meadowlark-e2e-tests", "main": "dist/index.js", - "version": "0.4.0-pre.3", + "version": "0.4.0-pre.4", "description": "Meadowlark Ed-Fi API end to end tests", "license": "Apache-2.0", "private": true, "files": [], "devDependencies": { - "@edfi/meadowlark-utilities": "0.4.0-pre.3", + "@edfi/meadowlark-utilities": "0.4.0-pre.4", "@testcontainers/mongodb": "^10.2.1", "@testcontainers/postgresql": "^10.2.1", "@types/chance": "^1.1.4", diff --git a/Meadowlark-js/tests/e2e/scenarios/AuthenticationValidation.test.ts b/Meadowlark-js/tests/e2e/scenarios/AuthenticationValidation.test.ts index df48c23b..722b63dc 100644 --- a/Meadowlark-js/tests/e2e/scenarios/AuthenticationValidation.test.ts +++ b/Meadowlark-js/tests/e2e/scenarios/AuthenticationValidation.test.ts @@ -94,4 +94,27 @@ describe("given it's authenticating a client", () => { }); }); }); + + describe('when sending to an uppercase url', () => { + it('should be able to return access token', async () => { + await baseURLRequest() + .post('/OAUTH/TOKEN') + .send({ + grant_type: 'client_credentials', + client_id: client.key, + client_secret: client.secret, + }) + .expect(200) + .then((response) => { + expect(response.body).toEqual( + expect.objectContaining({ + access_token: expect.any(String), + expires_in: expect.any(Number), + refresh_token: 'not available', + token_type: 'bearer', + }), + ); + }); + }); + }); }); diff --git a/Meadowlark-js/tests/e2e/scenarios/AuthorizationValidation.test.ts b/Meadowlark-js/tests/e2e/scenarios/AuthorizationValidation.test.ts index 55747212..dcdbe8cd 100644 --- a/Meadowlark-js/tests/e2e/scenarios/AuthorizationValidation.test.ts +++ b/Meadowlark-js/tests/e2e/scenarios/AuthorizationValidation.test.ts @@ -9,13 +9,39 @@ import { baseURLRequest, rootURLRequest } from '../helpers/Shared'; const ENDPOINT = `/oauth/clients`; describe("given it's managing the client authorization", () => { + let adminToken: string; + let location: string; + let responseBody: any; + const clientData = { + clientName: 'Test Vendor', + roles: ['vendor'], + }; + + describe('when generating a client and sending it to an uppercase url', () => { + beforeAll(async () => { + adminToken = await adminAccessToken(); + await baseURLRequest() + .post(ENDPOINT.toUpperCase()) + .send(clientData) + .expect(201) + .auth(adminToken, { type: 'bearer' }) + .then((response) => { + location = response.headers.location; + responseBody = response.body; + }); + }); + + it('is created', () => { + expect(responseBody).toEqual( + expect.objectContaining({ + clientName: 'Test Vendor', + roles: ['vendor'], + }), + ); + }); + }); + describe('given client already exists ', () => { - let adminToken: string; - let location: string; - const clientData = { - clientName: 'Test Vendor', - roles: ['vendor'], - }; beforeAll(async () => { adminToken = await adminAccessToken(); location = await baseURLRequest()