Browse Source

Merge pull request #3074 from bodnia/issue-2897

Issue 2897
bubble
Anna 7 years ago
committed by GitHub
parent
commit
e80b2f5b3f
12 changed files with 110 additions and 31 deletions
  1. +27
    -0
      README.md
  2. +9
    -0
      dev-helpers/index.html
  3. +8
    -8
      dist/swagger-ui-bundle.js
  4. +1
    -1
      dist/swagger-ui-bundle.js.map
  5. +9
    -9
      dist/swagger-ui.js
  6. +1
    -1
      dist/swagger-ui.js.map
  7. +18
    -7
      src/core/components/auth/oauth2.jsx
  8. +2
    -0
      src/core/index.js
  9. +8
    -2
      src/core/oauth2-authorize.js
  10. +16
    -2
      src/core/plugins/auth/actions.js
  11. +6
    -1
      src/core/plugins/auth/reducers.js
  12. +5
    -0
      src/core/plugins/auth/selectors.js

+ 27
- 0
README.md View File

@@ -75,6 +75,33 @@ 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`.

Config Name | Description
--- | ---
client_id | Default clientId. MUST be a string
client_secret | Default clientSecret. MUST be a string
realm | realm query parameter (for oauth1) added to `authorizationUrl` and `tokenUrl` . MUST be a string
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

```
const ui = SwaggerUIBundle({...})

// Method can be called in any place after calling constructor SwaggerUIBundle
ui.initOAuth({
clientId: "your-client-id",
clientSecret: "your-client-secret-if-required",
realm: "your-realms",
appName: "your-app-name",
scopeSeparator: " ",
additionalQueryStringParams: {test: "hello"}
})
```

If you'd like to use the bundle files via npm, check out the [`swagger-ui-dist` package](https://www.npmjs.com/package/swagger-ui-dist).

#### Parameters


+ 9
- 0
dev-helpers/index.html View File

@@ -88,6 +88,15 @@ window.onload = function() {
})

window.ui = ui

ui.initOAuth({
clientId: "your-client-id",
clientSecret: "your-client-secret-if-required",
realm: "your-realms",
appName: "your-app-name",
scopeSeparator: "-",
additionalQueryStringParams: {test: "hello"}
})
}
</script>
</body>


+ 8
- 8
dist/swagger-ui-bundle.js
File diff suppressed because it is too large
View File


+ 1
- 1
dist/swagger-ui-bundle.js.map View File

@@ -1 +1 @@
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;AAu/FA;AA6+FA;;;;;;;;;;;;;;;;;;;;;;;;;;AAoeA;;;;;;AAoIA;AAi7FA;AAmtCA;AAi0IA;AA0oJA;AAktFA;AAo3GA;AAw8DA;AAm9CA;AAijDA;AA6qCA;AA0xEA;;;;;AA0TA;AAmwJA;;;;;;;;;;;;;;AA8sEA;AAyoIA;AAiuJA;AA8kHA;AA8mGA;AAokEA;AAi3DA;AA42EA;AA0rGA;;;;;;AA8lFA;;;;;;AAqrBA;AAonHA;;;;;AAopDA;AA2qFA;AAw2CA;AAqkCA;AA++CA;AA+wEA;AAy8FA;;;;;;;;;AA23BA;AA2zIA;AAg4DA;AAgnDA;AA4sEA","sourceRoot":""}
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;AAu/FA;AA6+FA;;;;;;;;;;;;;;;;;;;;;;;;;;AAseA;;;;;;AAoIA;AAi7FA;AAmtCA;AAi0IA;AA0oJA;AAktFA;AAo3GA;AAw8DA;AAm9CA;AAijDA;AA6qCA;AA0xEA;;;;;AA0TA;AAmwJA;;;;;;;;;;;;;;AA8sEA;AAyoIA;AAiuJA;AA8kHA;AA8mGA;AAokEA;AAi3DA;AA42EA;AA0rGA;;;;;;AA8lFA;;;;;;AAqrBA;AA6pHA;;;;;AAkoDA;AA2qFA;AAw2CA;AAqkCA;AAq9CA;AAkxEA;AAk8FA;;;;;;;;;AA06BA;AA2zIA;AAg4DA;AAgnDA;AA4sEA","sourceRoot":""}

+ 9
- 9
dist/swagger-ui.js
File diff suppressed because it is too large
View File


+ 1
- 1
dist/swagger-ui.js.map View File

@@ -1 +1 @@
{"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AAwyCA;AAoyHA;AAqxHA;AAy4FA;AA2sCA;AAmgCA;AA0iCA;AA64BA","sourceRoot":""}
{"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AA0yCA;AAoyHA;AAqxHA;AA84FA;AAuqCA;AAugCA;AAyjCA;AA65BA","sourceRoot":""}

+ 18
- 7
src/core/components/auth/oauth2.jsx View File

@@ -21,14 +21,16 @@ export default class Oauth2 extends React.Component {

constructor(props, context) {
super(props, context)
let { name, schema, authorized } = this.props
let { name, schema, authorized, authSelectors } = this.props
let auth = authorized && authorized.get(name)
let authConfigs = authSelectors.getConfigs() || {}
let username = auth && auth.get("username") || ""
let clientId = auth && auth.get("clientId") || ""
let clientSecret = auth && auth.get("clientSecret") || ""
let clientId = auth && auth.get("clientId") || authConfigs.clientId || ""
let clientSecret = auth && auth.get("clientSecret") || authConfigs.clientSecret || ""
let passwordType = auth && auth.get("passwordType") || "basic"

this.state = {
appName: authConfigs.appName,
name: name,
schema: schema,
scopes: [],
@@ -41,11 +43,12 @@ export default class Oauth2 extends React.Component {
}

authorize =() => {
let { authActions, errActions, getConfigs } = this.props
let { authActions, errActions, getConfigs, authSelectors } = this.props
let configs = getConfigs()
let authConfigs = authSelectors.getConfigs()

errActions.clear({authId: name,type: "auth", source: "auth"})
oauth2Authorize(this.state, authActions, errActions, configs)
oauth2Authorize({auth: this.state, authActions, errActions, configs, authConfigs })
}

onScopeChange =(e) => {
@@ -98,6 +101,7 @@ export default class Oauth2 extends React.Component {
return (
<div>
<h4>OAuth2.0 <JumpToPath path={[ "securityDefinitions", name ]} /></h4>
{ !this.state.appName ? null : <h5>Application: { this.state.appName } </h5> }
<Markdown options={{html: true, typographer: true, linkify: true, linkTarget: "_blank"}}
source={ schema.get("description") } />

@@ -153,7 +157,11 @@ export default class Oauth2 extends React.Component {
{
isAuthorized ? <code> ****** </code>
: <Col tablet={10} desktop={10}>
<input id="client_id" type="text" required={ flow === PASSWORD } data-name="clientId"
<input id="client_id"
type="text"
required={ flow === PASSWORD }
value={ this.state.clientId }
data-name="clientId"
onChange={ this.onInputChange }/>
</Col>
}
@@ -166,7 +174,10 @@ export default class Oauth2 extends React.Component {
{
isAuthorized ? <code> ****** </code>
: <Col tablet={10} desktop={10}>
<input id="client_secret" type="text" data-name="clientSecret"
<input id="client_secret"
value={ this.state.clientSecret }
type="text"
data-name="clientSecret"
onChange={ this.onInputChange }/>
</Col>
}


+ 2
- 0
src/core/index.js View File

@@ -78,6 +78,8 @@ module.exports = function SwaggerUI(opts) {
var system = store.getSystem()
let queryConfig = parseSeach()

system.initOAuth = system.authActions.configureAuth

const downloadSpec = (fetchedConfig) => {
if(typeof constructorConfig !== "object") {
return system


+ 8
- 2
src/core/oauth2-authorize.js View File

@@ -1,11 +1,12 @@
import win from "core/window"
import { btoa } from "core/utils"

export default function authorize ( auth, authActions, errActions, configs ) {
export default function authorize ( { auth, authActions, errActions, configs, authConfigs={} } ) {
let { schema, scopes, name, clientId } = auth

let { additionalQueryStringParams } = authConfigs
let redirectUrl = configs.oauth2RedirectUrl
let scopeSeparator = " "
let scopeSeparator = authConfigs.scopeSeparator || " "
let state = btoa(new Date())
let flow = schema.get("flow")
let url
@@ -36,10 +37,15 @@ export default function authorize ( auth, authActions, errActions, configs ) {
}

url += "&redirect_uri=" + encodeURIComponent(redirectUrl)
+ "&realm=" + encodeURIComponent(authConfigs.realm);
+ "&scope=" + encodeURIComponent(scopes.join(scopeSeparator))
+ "&state=" + encodeURIComponent(state)
+ "&client_id=" + encodeURIComponent(clientId)

for (let key in additionalQueryStringParams) {
url += "&" + key + "=" + encodeURIComponent(additionalQueryStringParams[key])
}

// pass action authorizeOauth2 and authentication data through window
// to authorize with oauth2
win.swaggerUIRedirectOauth2 = {


+ 16
- 2
src/core/plugins/auth/actions.js View File

@@ -7,6 +7,7 @@ export const LOGOUT = "logout"
export const PRE_AUTHORIZE_OAUTH2 = "pre_authorize_oauth2"
export const AUTHORIZE_OAUTH2 = "authorize_oauth2"
export const VALIDATE = "validate"
export const CONFIGURE_AUTH = "configure_auth"

const scopeSeparator = " "

@@ -117,8 +118,14 @@ export const authorizeAccessCode = ( auth ) => ( { authActions } ) => {

}

export const authorizeRequest = ( data ) => ( { fn, authActions, errActions } ) => {
export const authorizeRequest = ( data ) => ( { fn, authActions, errActions, authSelectors } ) => {
let { body, query={}, headers={}, name, url, auth } = data
let { additionalQueryStringParams } = authSelectors.getConfigs() || {}
let fetchUrl = url

for (let key in additionalQueryStringParams) {
url += "&" + key + "=" + encodeURIComponent(additionalQueryStringParams[key])
}

let _headers = Object.assign({
"Accept":"application/json, text/plain, */*",
@@ -127,7 +134,7 @@ export const authorizeRequest = ( data ) => ( { fn, authActions, errActions } )
}, headers)

fn.fetch({
url: url,
url: fetchUrl,
method: "post",
headers: _headers,
query: query,
@@ -169,3 +176,10 @@ export const authorizeRequest = ( data ) => ( { fn, authActions, errActions } )
message: err.message
} ) })
}

export function configureAuth(payload) {
return {
type: CONFIGURE_AUTH,
payload: payload
}
}

+ 6
- 1
src/core/plugins/auth/reducers.js View File

@@ -5,7 +5,8 @@ import {
SHOW_AUTH_POPUP,
AUTHORIZE,
AUTHORIZE_OAUTH2,
LOGOUT
LOGOUT,
CONFIGURE_AUTH
} from "./actions"

export default {
@@ -57,5 +58,9 @@ export default {
})

return state.set("authorized", result)
},

[CONFIGURE_AUTH]: (state, { payload } ) =>{
return state.set("configs", payload)
}
}

+ 5
- 0
src/core/plugins/auth/selectors.js View File

@@ -79,3 +79,8 @@ export const isAuthorized = ( state, securities ) =>( { authSelectors } ) => {
}).indexOf(false) === -1
}).length
}

export const getConfigs = createSelector(
state,
auth => auth.get( "configs" )
)

Loading…
Cancel
Save