Skip to content
Merged
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
16 changes: 15 additions & 1 deletion packages/oas/src/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ export const METRICS_ENABLED = 'metrics-enabled';
* "x-readme": {
* "oauth-options": {
* "scopeSeparator": ",",
* "useInsecureClientAuthentication": true
* "useInsecureClientAuthentication": true,
* "usePkce": false
* }
* }
* }
Expand Down Expand Up @@ -257,6 +258,19 @@ export interface Extensions {
* @default false
*/
useInsecureClientAuthentication?: boolean;

/**
* When enabled, uses PKCE (Proof Key for Code Exchange) for the authorization code flow.
* The client secret is replaced with an auto-generated code verifier and code challenge.
* When disabled, uses the standard OAuth 2.0 authorization code flow with client credentials.
*
* @see {@link https://datatracker.ietf.org/doc/html/rfc7636#section-4.1}
* @see {@link https://datatracker.ietf.org/doc/html/rfc7636#section-4.2}
*
* @example true
* @default false
*/
usePkce?: boolean;
};
[PARAMETER_ORDERING]: ('body' | 'cookie' | 'form' | 'header' | 'path' | 'query')[];
[PROXY_ENABLED]: boolean;
Expand Down
64 changes: 64 additions & 0 deletions packages/oas/test/extensions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,40 @@ describe('#getExtension', () => {

expect(oas.getExtension('x-tag-groups')).toStrictEqual(['buster']);
});

it('should locate oauth-options with usePkce under `x-readme`', () => {
const oas = Oas.init({
...petstore,
'x-readme': {
[extensions.OAUTH_OPTIONS]: {
usePkce: true,
},
},
});

const oauthOptions = oas.getExtension(extensions.OAUTH_OPTIONS);
expect(oauthOptions).toStrictEqual({ usePkce: true });
});

it('should support multiple oauth-options properties', () => {
const oas = Oas.init({
...petstore,
'x-readme': {
[extensions.OAUTH_OPTIONS]: {
scopeSeparator: ',',
useInsecureClientAuthentication: true,
usePkce: true,
},
},
});

const oauthOptions = oas.getExtension(extensions.OAUTH_OPTIONS);
expect(oauthOptions).toStrictEqual({
scopeSeparator: ',',
useInsecureClientAuthentication: true,
usePkce: true,
});
});
});

describe('operation-level', () => {
Expand Down Expand Up @@ -152,6 +186,36 @@ describe('#getExtension', () => {

expect(oas.getExtension('x-amazon-apigateway-importexport-version', operation)).toBe('1.0');
});

it('should locate oauth-options with usePkce under `x-readme` at operation level', () => {
const operation = oas.operation('/pet', 'post');
operation.schema['x-readme'] = {
[extensions.OAUTH_OPTIONS]: {
usePkce: true,
},
};

const oauthOptions = oas.getExtension(extensions.OAUTH_OPTIONS, operation);
expect(oauthOptions).toStrictEqual({ usePkce: true });
});

it('should support multiple oauth-options properties at operation level', () => {
const operation = oas.operation('/pet', 'post');
operation.schema['x-readme'] = {
[extensions.OAUTH_OPTIONS]: {
scopeSeparator: ',',
useInsecureClientAuthentication: false,
usePkce: true,
},
};

const oauthOptions = oas.getExtension(extensions.OAUTH_OPTIONS, operation);
expect(oauthOptions).toStrictEqual({
scopeSeparator: ',',
useInsecureClientAuthentication: false,
usePkce: true,
});
});
});
});

Expand Down