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
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@apiture/openapi-down-convert",
"version": "0.14.0",
"version": "0.14.1",
"description": "Tool to down convert OpenAPI 3.1 to OpenAPI 3.0",
"main": "lib/src/index.js",
"bin": {
Expand Down
3 changes: 2 additions & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ async function main(args: string[] = process.argv) {
allOfTransform: Boolean(opts.allOf),
authorizationUrl: opts.authorizationUrl,
tokenUrl: opts.tokenUrl,
scopeDescriptionFile: opts.scopes,
scopeDescriptionFile: opts.oidcToOauth2 || opts.scopes,
convertOpenIdConnectToOAuth2: !! (opts.oidcToOauth2 || opts.scopes),
convertSchemaComments: opts.convertSchemaComments,
};
const converter = new Converter(source, cOpts);
Expand Down
33 changes: 22 additions & 11 deletions src/converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ export interface ConverterOptions {
authorizationUrl?: string;
/** The tokenUrl for openIdConnect -> oauth2 transformation */
tokenUrl?: string;
/**
* If `true`, convert `openIdConnect` security scheme
* to `oauth2`. Some tools (even those which purport to support OAS 3.0)
* do not process the `openIdConnect` security scheme
* (I'm looking at you, openapi-generator)
*/
convertOpenIdConnectToOAuth2?: boolean;
/** Name of YAML/JSON file with scope descriptions.
* This is a simple map in the format
* `{ scope1: "description of scope1", ... }`
Expand All @@ -64,6 +71,7 @@ export class Converter {
private scopeDescriptions = undefined;
private convertSchemaComments = false;
private returnCode = 0;
private convertOpenIdConnectToOAuth2: boolean;

/**
* Construct a new Converter
Expand All @@ -76,17 +84,17 @@ export class Converter {
this.allOfTransform = Boolean(options?.allOfTransform);
this.authorizationUrl = options?.authorizationUrl || 'https://www.example.com/oauth2/authorize';
this.tokenUrl = options?.tokenUrl || 'https://www.example.com/oauth2/token';
this.loadScopeDescriptions(options?.scopeDescriptionFile);
this.convertOpenIdConnectToOAuth2 = options?.convertOpenIdConnectToOAuth2 || !!(options?.scopeDescriptionFile);
if (this.convertOpenIdConnectToOAuth2) {
this.loadScopeDescriptions(options.scopeDescriptionFile);
}
this.convertSchemaComments = options?.convertSchemaComments;
}

/** Load the scopes.yaml file and save in this.scopeDescriptions
* @throws Error if the file cannot be read or parsed as YAML/JSON
*/
private loadScopeDescriptions(scopeDescriptionFile?: string) {
if (!scopeDescriptionFile) {
return;
}
this.scopeDescriptions = yaml.load(fs.readFileSync(scopeDescriptionFile, 'utf8'));
}

Expand Down Expand Up @@ -136,8 +144,8 @@ export class Converter {
this.removeLicenseIdentifier();
this.convertSchemaRef();
this.simplifyNonSchemaRef();
if (this.scopeDescriptions) {
this.convertSecuritySchemes();
if (this.convertOpenIdConnectToOAuth2) {
this.convertOpenIdConnectSecuritySchemesToOAuth2();
}
this.convertJsonSchemaExamples();
this.convertJsonSchemaContentEncoding();
Expand Down Expand Up @@ -373,13 +381,16 @@ export class Converter {
/** HTTP methods */
static readonly HTTP_METHODS = ['delete', 'get', 'head', 'options', 'patch', 'post', 'put', 'trace' ];
/**
* OpenAPI 3.1 defines a new `openIdConnect` security scheme.
* Down-convert the scheme to `oauth2` / authorization code flow.
* OpenAPI 3.0 defines a new `openIdConnect` security scheme
* but not all tools support `openIdConnect`, even if such tools
* claim support for OAS 3.0
* This converts the `openIdConnect` security scheme
* to the `oauth2` security scheme.
* Collect all the scopes used in any security requirements within
* operations and add them to the scheme. Also define the
* URLs to the `authorizationUrl` and `tokenUrl` of `oauth2`.
*/
convertSecuritySchemes() {
convertOpenIdConnectSecuritySchemesToOAuth2() {
const oauth2Scopes = (schemeName: string): object => {
const scopes = {};
const paths = this.openapi30?.paths;
Expand Down Expand Up @@ -410,8 +421,8 @@ export class Converter {
scheme.type = 'oauth2';
const openIdConnectUrl = scheme.openIdConnectUrl;
scheme.description = `OAuth2 Authorization Code Flow. The client may
GET the OpenID Connect configuration JSON from \`${openIdConnectUrl}\`
to get the correct \`authorizationUrl\` and \`tokenUrl\`.`;
GET the OpenID Connect configuration JSON from \`${openIdConnectUrl}\`
to get the correct \`authorizationUrl\` and \`tokenUrl\`.`;
delete scheme.openIdConnectUrl;
const scopes = oauth2Scopes(schemeName);
scheme.flows = {
Expand Down
1 change: 1 addition & 0 deletions test/converter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ describe('resolver test suite', () => {
authorizationUrl: 'https://www.example.com/test/authorize',
tokenUrl: 'https://www.example.com/test/token',
scopeDescriptionFile: path.join(__dirname, 'data/scopes.yaml'),
convertOpenIdConnectToOAuth2: true
};
const converter = new Converter(input, options);
const converted: any = converter.convert();
Expand Down