Skip to content

Commit

Permalink
Fixed missing endpoints for feature Organizations for Client Credenti…
Browse files Browse the repository at this point in the history
…als changes (#1046)
  • Loading branch information
tusharpandey13 authored Nov 5, 2024
1 parent edef4d1 commit 8c440b2
Show file tree
Hide file tree
Showing 9 changed files with 260 additions and 118 deletions.
7 changes: 0 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,3 @@ jobs:
- name: Tests
shell: bash
run: npm run test:ci

- name: Upload coverage
if: matrix.node-version == '18.17'
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # [email protected]
with:
token: ${{ secrets.CODECOV_TOKEN }}

12 changes: 0 additions & 12 deletions src/auth/id-token-validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,24 +102,12 @@ export class IDTokenValidator {
'Organization Id (org_id) claim must be a string present in the ID token'
);
}

if (payload.org_id !== organization) {
throw new Error(
`Organization Id (org_id) claim value mismatch in the ID token; expected "${organization}", found "${payload.org_id}"'`
);
}
} else {
if (!payload.org_name || typeof payload.org_name !== 'string') {
throw new Error(
'Organization Name (org_name) claim must be a string present in the ID token'
);
}

if (payload.org_name !== organization.toLowerCase()) {
throw new Error(
`Organization Name (org_name) claim value mismatch in the ID token; expected "${organization}", found "${payload.org_name}"'`
);
}
}
}

Expand Down
61 changes: 60 additions & 1 deletion src/management/__generated/managers/organizations-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {
GetInvitations200ResponseOneOfInner,
GetMembers200Response,
GetOrganizationClientGrants200Response,
GetOrganizationClientGrants200ResponseOneOfInner,
GetOrganizationMemberRoles200Response,
GetOrganizations200Response,
GetOrganizations200ResponseOneOfInner,
Expand All @@ -17,6 +18,7 @@ import type {
PostEnabledConnectionsRequest,
PostInvitationsRequest,
PostMembersRequest,
PostOrganizationClientGrantsRequest,
PostOrganizationMemberRolesRequest,
PostOrganizations201Response,
PostOrganizationsRequest,
Expand All @@ -25,10 +27,10 @@ import type {
GetMembers200ResponseOneOf,
GetMembers200ResponseOneOfInner,
GetOrganizationClientGrants200ResponseOneOf,
GetOrganizationClientGrants200ResponseOneOfInner,
GetOrganizationMemberRoles200ResponseOneOf,
GetOrganizationMemberRoles200ResponseOneOfInner,
GetOrganizations200ResponseOneOf,
DeleteClientGrantsByGrantIdRequest,
DeleteEnabledConnectionsByConnectionIdRequest,
DeleteInvitationsByInvitationIdRequest,
DeleteMembersOperationRequest,
Expand All @@ -49,6 +51,7 @@ import type {
PostEnabledConnectionsOperationRequest,
PostInvitationsOperationRequest,
PostMembersOperationRequest,
PostOrganizationClientGrantsOperationRequest,
PostOrganizationMemberRolesOperationRequest,
} from '../models/index.js';

Expand All @@ -58,6 +61,30 @@ const { BaseAPI } = runtime;
*
*/
export class OrganizationsManager extends BaseAPI {
/**
* Remove a client grant from an organization
*
* @throws {RequiredError}
*/
async deleteClientGrantsByGrantId(
requestParameters: DeleteClientGrantsByGrantIdRequest,
initOverrides?: InitOverride
): Promise<ApiResponse<void>> {
runtime.validateRequiredRequestParams(requestParameters, ['id', 'grant_id']);

const response = await this.request(
{
path: `/organizations/{id}/client-grants/{grant_id}`
.replace('{id}', encodeURIComponent(String(requestParameters.id)))
.replace('{grant_id}', encodeURIComponent(String(requestParameters.grant_id))),
method: 'DELETE',
},
initOverrides
);

return runtime.VoidApiResponse.fromResponse(response);
}

/**
* Delete connections from an organization
*
Expand Down Expand Up @@ -859,6 +886,38 @@ export class OrganizationsManager extends BaseAPI {
return runtime.VoidApiResponse.fromResponse(response);
}

/**
* Associate a client grant with an organization
*
* @throws {RequiredError}
*/
async postOrganizationClientGrants(
requestParameters: PostOrganizationClientGrantsOperationRequest,
bodyParameters: PostOrganizationClientGrantsRequest,
initOverrides?: InitOverride
): Promise<ApiResponse<GetOrganizationClientGrants200ResponseOneOfInner>> {
runtime.validateRequiredRequestParams(requestParameters, ['id']);

const headerParameters: runtime.HTTPHeaders = {};

headerParameters['Content-Type'] = 'application/json';

const response = await this.request(
{
path: `/organizations/{id}/client-grants`.replace(
'{id}',
encodeURIComponent(String(requestParameters.id))
),
method: 'POST',
headers: headerParameters,
body: bodyParameters,
},
initOverrides
);

return runtime.JSONApiResponse.fromResponse(response);
}

/**
* Assign one or more roles to a given user that will be applied in the context of the provided organization
*
Expand Down
35 changes: 35 additions & 0 deletions src/management/__generated/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10513,6 +10513,16 @@ export interface PostMembersRequest {
*/
members: Array<string>;
}
/**
*
*/
export interface PostOrganizationClientGrantsRequest {
/**
* A Client Grant ID to add to the organization.
*
*/
grant_id: string;
}
/**
*
*/
Expand Down Expand Up @@ -14924,6 +14934,21 @@ export interface GetLogsByIdRequest {
*/
id: string;
}
/**
*
*/
export interface DeleteClientGrantsByGrantIdRequest {
/**
* Organization identifier
*
*/
id: string;
/**
* The Client Grant ID to remove from the organization
*
*/
grant_id: string;
}
/**
*
*/
Expand Down Expand Up @@ -15319,6 +15344,16 @@ export interface PostMembersOperationRequest {
*/
id: string;
}
/**
*
*/
export interface PostOrganizationClientGrantsOperationRequest {
/**
* Organization identifier
*
*/
id: string;
}
/**
*
*/
Expand Down
56 changes: 0 additions & 56 deletions test/auth/id-token-validator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,60 +386,4 @@ describe('id-token-validator', () => {
'Organization Name (org_name) claim must be a string present in the ID token'
);
});

it('should throw when org id claim doesnt match org expected', async () => {
const idTokenValidator = new IDTokenValidator({
domain: DOMAIN,
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
});

const jwt = await sign({ payload: { org_id: 'org_1234' } });

await expect(idTokenValidator.validate(jwt, { organization: 'org_123' })).rejects.toThrow(
'Organization Id (org_id) claim value mismatch in the ID token; expected "org_123", found "org_1234'
);
});

it('should throw when org name claim doesnt match org expected', async () => {
const idTokenValidator = new IDTokenValidator({
domain: DOMAIN,
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
});

const jwt = await sign({ payload: { org_name: 'notExpectedOrg' } });

await expect(idTokenValidator.validate(jwt, { organization: 'testorg' })).rejects.toThrow(
'Organization Name (org_name) claim value mismatch in the ID token; expected "testorg", found "notExpectedOrg'
);
});

it('should NOT throw when org_id matches expected organization', async () => {
const idTokenValidator = new IDTokenValidator({
domain: DOMAIN,
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
});

const jwt = await sign({ payload: { org_id: 'org_123' } });

await expect(
idTokenValidator.validate(jwt, { organization: 'org_123' })
).resolves.not.toThrow();
});

it('should NOT throw when org_name matches expected organization', async () => {
const idTokenValidator = new IDTokenValidator({
domain: DOMAIN,
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
});

const jwt = await sign({ payload: { org_name: 'testorg' } });

await expect(
idTokenValidator.validate(jwt, { organization: 'testOrg' })
).resolves.not.toThrow();
});
});
34 changes: 0 additions & 34 deletions test/auth/oauth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,38 +409,4 @@ describe('OAuth (with ID Token validation)', () => {
);
nockDone();
});

it('should throw for invalid organization id', async () => {
const { nockDone } = await nockBack('auth/fixtures/oauth.json', {
before: await withIdToken({
...opts,
payload: { org_id: 'org_123' },
}),
});
const oauth = new OAuth(opts);
await expect(
oauth.refreshTokenGrant(
{ refresh_token: 'test-refresh-token' },
{ idTokenValidateOptions: { organization: 'org_1235' } }
)
).rejects.toThrowError(/\(org_id\) claim value mismatch in the ID token/);
nockDone();
});

it('should throw for invalid organization name', async () => {
const { nockDone } = await nockBack('auth/fixtures/oauth.json', {
before: await withIdToken({
...opts,
payload: { org_name: 'org123' },
}),
});
const oauth = new OAuth(opts);
await expect(
oauth.refreshTokenGrant(
{ refresh_token: 'test-refresh-token' },
{ idTokenValidateOptions: { organization: 'org1235' } }
)
).rejects.toThrowError(/\(org_name\) claim value mismatch in the ID token/);
nockDone();
});
});
47 changes: 39 additions & 8 deletions test/management/organizations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@ import {
GetOrganizationClientGrantsRequest,
GetOrganizationClientGrants200Response,
ApiResponse,
DeleteClientGrantsByGrantIdRequest,
GetOrganizationClientGrants200ResponseOneOfInner,
} from '../../src/index.js';

describe('OrganizationsManager', () => {
let organizations: OrganizationsManager;
import { checkMethod } from '../utils/index.js';

describe('OrganizationsManager', () => {
let request: nock.Scope;
const token = 'TOKEN';

beforeAll(() => {
const client = new ManagementClient({
domain: 'tenant.auth0.com',
token: token,
});
organizations = client.organizations;
const client = new ManagementClient({
domain: 'tenant.auth0.com',
token: token,
});
const organizations: OrganizationsManager = client.organizations;

describe('#constructor', () => {
it('should throw an error when no base URL is provided', () => {
Expand Down Expand Up @@ -1474,4 +1474,35 @@ describe('OrganizationsManager', () => {
});
});
});

describe('#deleteClientGrantsById', () => {
const requestParameters: DeleteClientGrantsByGrantIdRequest = {
id: 'org_123',
grant_id: 'grant_id',
};
const operation = organizations.deleteClientGrantsByGrantId(requestParameters);
const expectedResponse = undefined;
const uri = `/organizations/{id}/client-grants/{grant_id}`
.replace('{id}', encodeURIComponent(String(requestParameters.id)))
.replace('{grant_id}', encodeURIComponent(String(requestParameters.grant_id)));
const method = 'delete';

checkMethod({ operation, expectedResponse, uri, method });
});

describe('#postOrganizationClientGrants', () => {
const requestParameters = { id: 'org_123' };
const requestBody = { grant_id: 'grant_id' };
const operation = organizations.postOrganizationClientGrants(requestParameters, requestBody);
const expectedResponse: GetOrganizationClientGrants200ResponseOneOfInner = <
GetOrganizationClientGrants200ResponseOneOfInner
>{};
const uri = `/organizations/{id}/client-grants`.replace(
'{id}',
encodeURIComponent(String(requestParameters.id))
);
const method = 'post';

checkMethod({ operation, expectedResponse, uri, method, requestBody });
});
});
1 change: 1 addition & 0 deletions test/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './extractParts.js';
export * from './withIdToken.js';
export * from './wrapperTestUtils.js';
Loading

0 comments on commit 8c440b2

Please sign in to comment.