From fc8ad8168d01a26414df939826c691b60361259f Mon Sep 17 00:00:00 2001 From: Eric Turcotte Date: Wed, 12 Jul 2017 23:26:20 -0500 Subject: [PATCH 1/8] Renamed authorizeAccessCode() to authorizeAccessCodeWithQueryParams() Added authorizeAccessCodeWithBasicAuthentication() that sends the client_id and client_secret using HTTP basic authentication Authorization: Basic base64encoded[client_id:client_secret] According to the OAuth2 spec, this is the preferred method. It also enables Authorization Servers that only support basic authentication during the authorization_code grant. https://tools.ietf.org/html/rfc6749#section-2.3.1 --- src/core/plugins/auth/actions.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/core/plugins/auth/actions.js b/src/core/plugins/auth/actions.js index 221d80a8..5524413e 100644 --- a/src/core/plugins/auth/actions.js +++ b/src/core/plugins/auth/actions.js @@ -111,7 +111,7 @@ export const authorizeApplication = ( auth ) => ( { authActions } ) => { return authActions.authorizeRequest({body: buildFormData(form), name, url: schema.get("tokenUrl"), auth, headers }) } -export const authorizeAccessCode = ( { auth, redirectUrl } ) => ( { authActions } ) => { +export const authorizeAccessCodeWithQueryParams = ( { auth, redirectUrl } ) => ( { authActions } ) => { let { schema, name, clientId, clientSecret } = auth let form = { grant_type: "authorization_code", @@ -124,6 +124,21 @@ export const authorizeAccessCode = ( { auth, redirectUrl } ) => ( { authActions return authActions.authorizeRequest({body: buildFormData(form), name, url: schema.get("tokenUrl"), auth}) } +export const authorizeAccessCodeWithBasicAuthentication = ( { auth, redirectUrl } ) => ( { authActions } ) => { + let { schema, name, clientId, clientSecret } = auth + let headers = { + Authorization: "Basic " + btoa(clientId + ":" + clientSecret) + } + let form = { + grant_type: "authorization_code", + code: auth.code, + client_id: clientId, + redirect_uri: redirectUrl + } + + return authActions.authorizeRequest({body: buildFormData(form), name, url: schema.get("tokenUrl"), auth, headers}) +} + export const authorizeRequest = ( data ) => ( { fn, authActions, errActions, authSelectors } ) => { let { body, query={}, headers={}, name, url, auth } = data let { additionalQueryStringParams } = authSelectors.getConfigs() || {} From b06971bf81db5944b66d1a651a0d2a6611e7f727 Mon Sep 17 00:00:00 2001 From: Eric Turcotte Date: Wed, 12 Jul 2017 23:35:34 -0500 Subject: [PATCH 2/8] If config useBasicAuthenticationWithAccessCodeGrant is truthy, send client id and secret as HTTP basic auth during authorization_code grant --- README.md | 7 +++++-- src/core/oauth2-authorize.js | 12 +++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 28943fab..6618688c 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,8 @@ To use swagger-ui's bundles, you should take a look at the [source of swagger-ui #### OAuth2 configuration You can configure OAuth2 authorization by calling `initOAuth` method with passed configs under the instance of `SwaggerUIBundle` -default `client_id` and `client_secret`, `realm`, an application name `appName`, `scopeSeparator`, `additionalQueryStringParams`. +default `client_id` and `client_secret`, `realm`, an application name `appName`, `scopeSeparator`, `additionalQueryStringParams`, +`useBasicAuthenticationWithAccessCodeGrant`. Config Name | Description --- | --- @@ -107,6 +108,7 @@ realm | realm query parameter (for oauth1) added to `authorizationUrl` and `toke appName | application name, displayed in authorization popup. MUST be a string scopeSeparator | scope separator for passing scopes, encoded before calling, default value is a space (encoded value `%20`). MUST be a string additionalQueryStringParams | Additional query parameters added to `authorizationUrl` and `tokenUrl`. MUST be an object +useBasicAuthenticationWithAccessCodeGrant | Only activated for the `accessCode` flow. During the `authorization_code` request to the `tokenUrl`, pass the [Client Password](https://tools.ietf.org/html/rfc6749#section-2.3.1) using the HTTP Basic Authentication scheme (`Authorization` header with `Basic base64encoded[client_id:client_secret]`). The default is `false` ``` const ui = SwaggerUIBundle({...}) @@ -118,7 +120,8 @@ ui.initOAuth({ realm: "your-realms", appName: "your-app-name", scopeSeparator: " ", - additionalQueryStringParams: {test: "hello"} + additionalQueryStringParams: {test: "hello"}, + useBasicAuthenticationWithAccessCodeGrant: true }) ``` diff --git a/src/core/oauth2-authorize.js b/src/core/oauth2-authorize.js index 5d654318..06935357 100644 --- a/src/core/oauth2-authorize.js +++ b/src/core/oauth2-authorize.js @@ -68,11 +68,21 @@ export default function authorize ( { auth, authActions, errActions, configs, au // pass action authorizeOauth2 and authentication data through window // to authorize with oauth2 + + let callback; + if (flow === "implicit") { + callback = authActions.preAuthorizeImplicit + } else if (authConfigs.useBasicAuthenticationWithAccessCodeGrant) { + callback = authActions.authorizeAccessCodeWithBasicAuthentication + } else { + callback = authActions.authorizeAccessCodeWithQueryParams + } + win.swaggerUIRedirectOauth2 = { auth: auth, state: state, redirectUrl: redirectUrl, - callback: flow === "implicit" ? authActions.preAuthorizeImplicit : authActions.authorizeAccessCode, + callback: callback, errCb: errActions.newAuthErr } From badfea61c3deae549b5d5a26a967b2e4a2efc5ef Mon Sep 17 00:00:00 2001 From: Eric Turcotte Date: Thu, 13 Jul 2017 10:53:36 -0500 Subject: [PATCH 3/8] Renamed authorizeAccessCodeWithQueryParams->authorizeAccessCodeWithFormParams since that is technically correct --- src/core/oauth2-authorize.js | 2 +- src/core/plugins/auth/actions.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/oauth2-authorize.js b/src/core/oauth2-authorize.js index 06935357..f09d379c 100644 --- a/src/core/oauth2-authorize.js +++ b/src/core/oauth2-authorize.js @@ -75,7 +75,7 @@ export default function authorize ( { auth, authActions, errActions, configs, au } else if (authConfigs.useBasicAuthenticationWithAccessCodeGrant) { callback = authActions.authorizeAccessCodeWithBasicAuthentication } else { - callback = authActions.authorizeAccessCodeWithQueryParams + callback = authActions.authorizeAccessCodeWithFormParams } win.swaggerUIRedirectOauth2 = { diff --git a/src/core/plugins/auth/actions.js b/src/core/plugins/auth/actions.js index 5524413e..dfd2ea04 100644 --- a/src/core/plugins/auth/actions.js +++ b/src/core/plugins/auth/actions.js @@ -111,7 +111,7 @@ export const authorizeApplication = ( auth ) => ( { authActions } ) => { return authActions.authorizeRequest({body: buildFormData(form), name, url: schema.get("tokenUrl"), auth, headers }) } -export const authorizeAccessCodeWithQueryParams = ( { auth, redirectUrl } ) => ( { authActions } ) => { +export const authorizeAccessCodeWithFormParams = ( { auth, redirectUrl } ) => ( { authActions } ) => { let { schema, name, clientId, clientSecret } = auth let form = { grant_type: "authorization_code", From a09e0b8b4ae69c4562bf1fcae46cf5d2a69d00c5 Mon Sep 17 00:00:00 2001 From: Eric Turcotte Date: Thu, 13 Jul 2017 11:16:47 -0500 Subject: [PATCH 4/8] Removed semicolon --- src/core/oauth2-authorize.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/oauth2-authorize.js b/src/core/oauth2-authorize.js index f09d379c..2e36010e 100644 --- a/src/core/oauth2-authorize.js +++ b/src/core/oauth2-authorize.js @@ -69,7 +69,7 @@ export default function authorize ( { auth, authActions, errActions, configs, au // pass action authorizeOauth2 and authentication data through window // to authorize with oauth2 - let callback; + let callback if (flow === "implicit") { callback = authActions.preAuthorizeImplicit } else if (authConfigs.useBasicAuthenticationWithAccessCodeGrant) { From 53c11700ba6bc10e5a1a0d1a30226f542dcb6f13 Mon Sep 17 00:00:00 2001 From: shockey Date: Tue, 1 Aug 2017 16:41:16 -0700 Subject: [PATCH 5/8] MOAR OpenAPI specification revisions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e3384151..7c37e7a7 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ This repo publishes to two different NPM packages: For the older version of swagger-ui, refer to the [*2.x branch*](https://github.com/swagger-api/swagger-ui/tree/2.x). ## Compatibility -The OpenAPI Specification has undergone 4 revisions since initial creation in 2010. Compatibility between swagger-ui and the OpenAPI Specification is as follows: +The OpenAPI Specification has undergone 5 revisions since initial creation in 2010. Compatibility between swagger-ui and the OpenAPI Specification is as follows: Swagger UI Version | Release Date | OpenAPI Spec compatibility | Notes ------------------ | ------------ | -------------------------- | ----- From 88a6e075ddc2aa33e58ae1d9b622bb4cc561f773 Mon Sep 17 00:00:00 2001 From: Kyle Date: Tue, 1 Aug 2017 16:54:30 -0700 Subject: [PATCH 6/8] Remove `useBasicAuthenticationWithAccessCodeGrant` ... from `initOAuth` example --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 707f8beb..54839f58 100644 --- a/README.md +++ b/README.md @@ -120,8 +120,7 @@ ui.initOAuth({ realm: "your-realms", appName: "your-app-name", scopeSeparator: " ", - additionalQueryStringParams: {test: "hello"}, - useBasicAuthenticationWithAccessCodeGrant: true + additionalQueryStringParams: {test: "hello"} }) ``` From c29e05d7263a62760d0796065a043c34ec665316 Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Tue, 1 Aug 2017 19:34:56 -0700 Subject: [PATCH 7/8] Display tag externalDocs --- src/core/components/operations.jsx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/core/components/operations.jsx b/src/core/components/operations.jsx index c9031651..e4022754 100644 --- a/src/core/components/operations.jsx +++ b/src/core/components/operations.jsx @@ -66,6 +66,8 @@ export default class Operations extends React.Component { taggedOps.map( (tagObj, tag) => { let operations = tagObj.get("operations") let tagDescription = tagObj.getIn(["tagDetails", "description"], null) + let tagExternalDocsDescription = tagObj.getIn(["tagDetails", "externalDocs", "description"]) + let tagExternalDocsUrl = tagObj.getIn(["tagDetails", "externalDocs", "url"]) let isShownKey = ["operations-tag", tag] let showTag = layoutSelectors.isShown(isShownKey, docExpansion === "full" || docExpansion === "list") @@ -89,6 +91,22 @@ export default class Operations extends React.Component { } +
+ { !tagExternalDocsDescription ? null : + + { tagExternalDocsDescription } + { tagExternalDocsUrl ? ": " : null } + { tagExternalDocsUrl ? + e.stopPropagation()} + target={"_blank"} + >{tagExternalDocsUrl} : null + } + + } +
+