未验证 提交 275c8f2c 编写于 作者: M Matthew Morrissette 提交者: GitHub

improvement: oauth "scopes" improvements (#6037)

* improvement: oauth "scopes" init parameter

* improvement: add "select all" and "select none" to oauth scopes popup
上级 4497387d
...@@ -62,6 +62,7 @@ ...@@ -62,6 +62,7 @@
realm: "your-realms", realm: "your-realms",
appName: "your-app-name", appName: "your-app-name",
scopeSeparator: " ", scopeSeparator: " ",
scopes: "openid profile email phone address",
additionalQueryStringParams: {}, additionalQueryStringParams: {},
usePkceWithAuthorizationCodeGrant: false usePkceWithAuthorizationCodeGrant: false
}) })
......
...@@ -23,6 +23,10 @@ const oauthBlockSchema = { ...@@ -23,6 +23,10 @@ const oauthBlockSchema = {
type: "string", type: "string",
name: "scopeSeparator" name: "scopeSeparator"
}, },
OAUTH_SCOPES: {
type: "string",
name: "scopes"
},
OAUTH_ADDITIONAL_PARAMS: { OAUTH_ADDITIONAL_PARAMS: {
type: "object", type: "object",
name: "additionalQueryStringParams" name: "additionalQueryStringParams"
...@@ -44,4 +48,4 @@ ${indent(translatorResult, 2)} ...@@ -44,4 +48,4 @@ ${indent(translatorResult, 2)}
} }
return `` return ``
} }
\ No newline at end of file
...@@ -8,6 +8,7 @@ clientSecret | `OAUTH_CLIENT_SECRET` | **🚨 Never use this parameter in your p ...@@ -8,6 +8,7 @@ clientSecret | `OAUTH_CLIENT_SECRET` | **🚨 Never use this parameter in your p
realm | `OAUTH_REALM` |realm query parameter (for oauth1) added to `authorizationUrl` and `tokenUrl`. MUST be a string realm | `OAUTH_REALM` |realm query parameter (for oauth1) added to `authorizationUrl` and `tokenUrl`. MUST be a string
appName | `OAUTH_APP_NAME` |application name, displayed in authorization popup. MUST be a string appName | `OAUTH_APP_NAME` |application name, displayed in authorization popup. MUST be a string
scopeSeparator | `OAUTH_SCOPE_SEPARATOR` |scope separator for passing scopes, encoded before calling, default value is a space (encoded value `%20`). MUST be a string scopeSeparator | `OAUTH_SCOPE_SEPARATOR` |scope separator for passing scopes, encoded before calling, default value is a space (encoded value `%20`). MUST be a string
scopes | `OAUTH_SCOPES` |string array or scope separator (i.e. space) separated string of initially selected oauth scopes, default is empty array
additionalQueryStringParams | `OAUTH_ADDITIONAL_PARAMS` |Additional query parameters added to `authorizationUrl` and `tokenUrl`. MUST be an object additionalQueryStringParams | `OAUTH_ADDITIONAL_PARAMS` |Additional query parameters added to `authorizationUrl` and `tokenUrl`. MUST be an object
useBasicAuthenticationWithAccessCodeGrant | _Unavailable_ |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 base64encode(client_id + client_secret)`). The default is `false` useBasicAuthenticationWithAccessCodeGrant | _Unavailable_ |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 base64encode(client_id + client_secret)`). The default is `false`
usePkceWithAuthorizationCodeGrant | `OAUTH_USE_PKCE` | Only applies to `authorizatonCode` flows. [Proof Key for Code Exchange](https://tools.ietf.org/html/rfc7636) brings enhanced security for OAuth public clients. The default is `false` usePkceWithAuthorizationCodeGrant | `OAUTH_USE_PKCE` | Only applies to `authorizatonCode` flows. [Proof Key for Code Exchange](https://tools.ietf.org/html/rfc7636) brings enhanced security for OAuth public clients. The default is `false`
...@@ -22,6 +23,7 @@ ui.initOAuth({ ...@@ -22,6 +23,7 @@ ui.initOAuth({
realm: "your-realms", realm: "your-realms",
appName: "your-app-name", appName: "your-app-name",
scopeSeparator: " ", scopeSeparator: " ",
scopes: "openid profile",
additionalQueryStringParams: {test: "hello"}, additionalQueryStringParams: {test: "hello"},
usePkceWithAuthorizationCodeGrant: true usePkceWithAuthorizationCodeGrant: true
}) })
......
...@@ -25,12 +25,16 @@ export default class Oauth2 extends React.Component { ...@@ -25,12 +25,16 @@ export default class Oauth2 extends React.Component {
let clientId = auth && auth.get("clientId") || authConfigs.clientId || "" let clientId = auth && auth.get("clientId") || authConfigs.clientId || ""
let clientSecret = auth && auth.get("clientSecret") || authConfigs.clientSecret || "" let clientSecret = auth && auth.get("clientSecret") || authConfigs.clientSecret || ""
let passwordType = auth && auth.get("passwordType") || "basic" let passwordType = auth && auth.get("passwordType") || "basic"
let scopes = auth && auth.get("scopes") || authConfigs.scopes || []
if (typeof scopes === "string") {
scopes = scopes.split(authConfigs.scopeSeparator || " ")
}
this.state = { this.state = {
appName: authConfigs.appName, appName: authConfigs.appName,
name: name, name: name,
schema: schema, schema: schema,
scopes: [], scopes: scopes,
clientId: clientId, clientId: clientId,
clientSecret: clientSecret, clientSecret: clientSecret,
username: username, username: username,
...@@ -77,6 +81,16 @@ export default class Oauth2 extends React.Component { ...@@ -77,6 +81,16 @@ export default class Oauth2 extends React.Component {
this.setState(state) this.setState(state)
} }
selectScopes =(e) => {
if (e.target.dataset.all) {
this.setState({
scopes: Array.from((this.props.schema.get("allowedScopes") || this.props.schema.get("scopes")).keys())
})
} else {
this.setState({ scopes: [] })
}
}
logout =(e) => { logout =(e) => {
e.preventDefault() e.preventDefault()
let { authActions, errActions, name } = this.props let { authActions, errActions, name } = this.props
...@@ -201,7 +215,11 @@ export default class Oauth2 extends React.Component { ...@@ -201,7 +215,11 @@ export default class Oauth2 extends React.Component {
{ {
!isAuthorized && scopes && scopes.size ? <div className="scopes"> !isAuthorized && scopes && scopes.size ? <div className="scopes">
<h2>Scopes:</h2> <h2>
Scopes:
<a onClick={this.selectScopes} data-all={true}>select all</a>
<a onClick={this.selectScopes}>select none</a>
</h2>
{ scopes.map((description, name) => { { scopes.map((description, name) => {
return ( return (
<Row key={ name }> <Row key={ name }>
...@@ -209,6 +227,7 @@ export default class Oauth2 extends React.Component { ...@@ -209,6 +227,7 @@ export default class Oauth2 extends React.Component {
<Input data-value={ name } <Input data-value={ name }
id={`${name}-${flow}-checkbox-${this.state.name}`} id={`${name}-${flow}-checkbox-${this.state.name}`}
disabled={ isAuthorized } disabled={ isAuthorized }
checked={ this.state.scopes.includes(name) }
type="checkbox" type="checkbox"
onChange={ this.onScopeChange }/> onChange={ this.onScopeChange }/>
<label htmlFor={`${name}-${flow}-checkbox-${this.state.name}`}> <label htmlFor={`${name}-${flow}-checkbox-${this.state.name}`}>
......
...@@ -76,6 +76,15 @@ ...@@ -76,6 +76,15 @@
font-size: 14px; font-size: 14px;
@include text_headline(); @include text_headline();
a
{
font-size: 12px;
color: $auth-select-all-none-link-font-color;
cursor: pointer;
padding-left: 10px;
text-decoration: underline;
}
} }
} }
......
...@@ -54,7 +54,7 @@ $_color-options: #0d5aa7 !default; ...@@ -54,7 +54,7 @@ $_color-options: #0d5aa7 !default;
// Authorize // Authorize
$auth-container-border-color: $gray-50 !default; $auth-container-border-color: $gray-50 !default;
$auth-select-all-none-link-font-color: $color-info !default;
// Buttons // Buttons
$btn-background-color: transparent !default; $btn-background-color: transparent !default;
......
...@@ -70,6 +70,18 @@ module.exports = { ...@@ -70,6 +70,18 @@ module.exports = {
authorizationUrl: { authorizationUrl: {
selector: ".auth-container code" selector: ".auth-container code"
}, },
readPetsScope: {
selector: "input[data-value='read:pets']"
},
writePetsScope: {
selector: "input[data-value='write:pets']"
},
selectAllScopes: {
selector: ".auth-container h2 a[data-all]"
},
selectNoneScopes: {
selector: ".auth-container h2 a:not([data-all])"
},
flow: { flow: {
selector: ".flow code" selector: ".flow code"
}, },
......
...@@ -45,6 +45,16 @@ describe("Render scheme", function () { ...@@ -45,6 +45,16 @@ describe("Render scheme", function () {
.assert.containsText("@authorizationUrl", "http://petstore.swagger.io/oauth/dialog") .assert.containsText("@authorizationUrl", "http://petstore.swagger.io/oauth/dialog")
.assert.containsText("@flow", "implicit") .assert.containsText("@flow", "implicit")
.assert.value("@inputClientID", "your-client-id") .assert.value("@inputClientID", "your-client-id")
schemeContainer.expect.element("@readPetsScope").to.be.selected
schemeContainer.expect.element("@writePetsScope").to.not.be.selected
schemeContainer.click("@selectAllScopes")
schemeContainer.expect.element("@readPetsScope").to.be.selected
schemeContainer.expect.element("@writePetsScope").to.be.selected
schemeContainer.click("@selectNoneScopes")
schemeContainer.expect.element("@readPetsScope").to.not.be.selected
schemeContainer.expect.element("@writePetsScope").to.not.be.selected
client.end() client.end()
}) })
......
...@@ -101,6 +101,7 @@ ...@@ -101,6 +101,7 @@
realm: "your-realms", realm: "your-realms",
appName: "your-app-name", appName: "your-app-name",
scopeSeparator: " ", scopeSeparator: " ",
scopes: "read:pets profile openid",
additionalQueryStringParams: {} additionalQueryStringParams: {}
}) })
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册