@@ -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). | 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 | #### Parameters | ||||
@@ -88,6 +88,15 @@ window.onload = function() { | |||||
}) | }) | ||||
window.ui = ui | 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> | </script> | ||||
</body> | </body> | ||||
@@ -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":""} |
@@ -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":""} |
@@ -21,14 +21,16 @@ export default class Oauth2 extends React.Component { | |||||
constructor(props, context) { | constructor(props, context) { | ||||
super(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 auth = authorized && authorized.get(name) | ||||
let authConfigs = authSelectors.getConfigs() || {} | |||||
let username = auth && auth.get("username") || "" | 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" | let passwordType = auth && auth.get("passwordType") || "basic" | ||||
this.state = { | this.state = { | ||||
appName: authConfigs.appName, | |||||
name: name, | name: name, | ||||
schema: schema, | schema: schema, | ||||
scopes: [], | scopes: [], | ||||
@@ -41,11 +43,12 @@ export default class Oauth2 extends React.Component { | |||||
} | } | ||||
authorize =() => { | authorize =() => { | ||||
let { authActions, errActions, getConfigs } = this.props | |||||
let { authActions, errActions, getConfigs, authSelectors } = this.props | |||||
let configs = getConfigs() | let configs = getConfigs() | ||||
let authConfigs = authSelectors.getConfigs() | |||||
errActions.clear({authId: name,type: "auth", source: "auth"}) | errActions.clear({authId: name,type: "auth", source: "auth"}) | ||||
oauth2Authorize(this.state, authActions, errActions, configs) | |||||
oauth2Authorize({auth: this.state, authActions, errActions, configs, authConfigs }) | |||||
} | } | ||||
onScopeChange =(e) => { | onScopeChange =(e) => { | ||||
@@ -98,6 +101,7 @@ export default class Oauth2 extends React.Component { | |||||
return ( | return ( | ||||
<div> | <div> | ||||
<h4>OAuth2.0 <JumpToPath path={[ "securityDefinitions", name ]} /></h4> | <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"}} | <Markdown options={{html: true, typographer: true, linkify: true, linkTarget: "_blank"}} | ||||
source={ schema.get("description") } /> | source={ schema.get("description") } /> | ||||
@@ -153,7 +157,11 @@ export default class Oauth2 extends React.Component { | |||||
{ | { | ||||
isAuthorized ? <code> ****** </code> | isAuthorized ? <code> ****** </code> | ||||
: <Col tablet={10} desktop={10}> | : <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 }/> | onChange={ this.onInputChange }/> | ||||
</Col> | </Col> | ||||
} | } | ||||
@@ -166,7 +174,10 @@ export default class Oauth2 extends React.Component { | |||||
{ | { | ||||
isAuthorized ? <code> ****** </code> | isAuthorized ? <code> ****** </code> | ||||
: <Col tablet={10} desktop={10}> | : <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 }/> | onChange={ this.onInputChange }/> | ||||
</Col> | </Col> | ||||
} | } | ||||
@@ -78,6 +78,8 @@ module.exports = function SwaggerUI(opts) { | |||||
var system = store.getSystem() | var system = store.getSystem() | ||||
let queryConfig = parseSeach() | let queryConfig = parseSeach() | ||||
system.initOAuth = system.authActions.configureAuth | |||||
const downloadSpec = (fetchedConfig) => { | const downloadSpec = (fetchedConfig) => { | ||||
if(typeof constructorConfig !== "object") { | if(typeof constructorConfig !== "object") { | ||||
return system | return system | ||||
@@ -1,11 +1,12 @@ | |||||
import win from "core/window" | import win from "core/window" | ||||
import { btoa } from "core/utils" | 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 { schema, scopes, name, clientId } = auth | ||||
let { additionalQueryStringParams } = authConfigs | |||||
let redirectUrl = configs.oauth2RedirectUrl | let redirectUrl = configs.oauth2RedirectUrl | ||||
let scopeSeparator = " " | |||||
let scopeSeparator = authConfigs.scopeSeparator || " " | |||||
let state = btoa(new Date()) | let state = btoa(new Date()) | ||||
let flow = schema.get("flow") | let flow = schema.get("flow") | ||||
let url | let url | ||||
@@ -36,10 +37,15 @@ export default function authorize ( auth, authActions, errActions, configs ) { | |||||
} | } | ||||
url += "&redirect_uri=" + encodeURIComponent(redirectUrl) | url += "&redirect_uri=" + encodeURIComponent(redirectUrl) | ||||
+ "&realm=" + encodeURIComponent(authConfigs.realm); | |||||
+ "&scope=" + encodeURIComponent(scopes.join(scopeSeparator)) | + "&scope=" + encodeURIComponent(scopes.join(scopeSeparator)) | ||||
+ "&state=" + encodeURIComponent(state) | + "&state=" + encodeURIComponent(state) | ||||
+ "&client_id=" + encodeURIComponent(clientId) | + "&client_id=" + encodeURIComponent(clientId) | ||||
for (let key in additionalQueryStringParams) { | |||||
url += "&" + key + "=" + encodeURIComponent(additionalQueryStringParams[key]) | |||||
} | |||||
// pass action authorizeOauth2 and authentication data through window | // pass action authorizeOauth2 and authentication data through window | ||||
// to authorize with oauth2 | // to authorize with oauth2 | ||||
win.swaggerUIRedirectOauth2 = { | win.swaggerUIRedirectOauth2 = { | ||||
@@ -7,6 +7,7 @@ export const LOGOUT = "logout" | |||||
export const PRE_AUTHORIZE_OAUTH2 = "pre_authorize_oauth2" | export const PRE_AUTHORIZE_OAUTH2 = "pre_authorize_oauth2" | ||||
export const AUTHORIZE_OAUTH2 = "authorize_oauth2" | export const AUTHORIZE_OAUTH2 = "authorize_oauth2" | ||||
export const VALIDATE = "validate" | export const VALIDATE = "validate" | ||||
export const CONFIGURE_AUTH = "configure_auth" | |||||
const scopeSeparator = " " | 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 { 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({ | let _headers = Object.assign({ | ||||
"Accept":"application/json, text/plain, */*", | "Accept":"application/json, text/plain, */*", | ||||
@@ -127,7 +134,7 @@ export const authorizeRequest = ( data ) => ( { fn, authActions, errActions } ) | |||||
}, headers) | }, headers) | ||||
fn.fetch({ | fn.fetch({ | ||||
url: url, | |||||
url: fetchUrl, | |||||
method: "post", | method: "post", | ||||
headers: _headers, | headers: _headers, | ||||
query: query, | query: query, | ||||
@@ -169,3 +176,10 @@ export const authorizeRequest = ( data ) => ( { fn, authActions, errActions } ) | |||||
message: err.message | message: err.message | ||||
} ) }) | } ) }) | ||||
} | } | ||||
export function configureAuth(payload) { | |||||
return { | |||||
type: CONFIGURE_AUTH, | |||||
payload: payload | |||||
} | |||||
} |
@@ -5,7 +5,8 @@ import { | |||||
SHOW_AUTH_POPUP, | SHOW_AUTH_POPUP, | ||||
AUTHORIZE, | AUTHORIZE, | ||||
AUTHORIZE_OAUTH2, | AUTHORIZE_OAUTH2, | ||||
LOGOUT | |||||
LOGOUT, | |||||
CONFIGURE_AUTH | |||||
} from "./actions" | } from "./actions" | ||||
export default { | export default { | ||||
@@ -57,5 +58,9 @@ export default { | |||||
}) | }) | ||||
return state.set("authorized", result) | return state.set("authorized", result) | ||||
}, | |||||
[CONFIGURE_AUTH]: (state, { payload } ) =>{ | |||||
return state.set("configs", payload) | |||||
} | } | ||||
} | } |
@@ -79,3 +79,8 @@ export const isAuthorized = ( state, securities ) =>( { authSelectors } ) => { | |||||
}).indexOf(false) === -1 | }).indexOf(false) === -1 | ||||
}).length | }).length | ||||
} | } | ||||
export const getConfigs = createSelector( | |||||
state, | |||||
auth => auth.get( "configs" ) | |||||
) |