Merge pull request #2979 from bodnia/fix-oauth2-issue
fixes password, application oauth2 flows
This commit is contained in:
93
dist/swagger-ui-bundle.js
vendored
93
dist/swagger-ui-bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/swagger-ui-bundle.js.map
vendored
2
dist/swagger-ui-bundle.js.map
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;AAu/FA;AA6+FA;;;;;;;;;;;;;;;;;;;;;;;;;;AA0dA;;;;;;AAoIA;AAk7FA;AAmtCA;;;;;AA0uIA;AA+4IA;AAm9FA;AA2rGA;AA8lFA;AA2nFA;AAu9CA;AAyhDA;AAqrCA;AAy4EA;AA8/GA;;;;;;;;;;;;;;AA+mJA;AA4mIA;AAquJA;AAwsHA;AAinGA;AAmiEA;AAy4DA;AAm2DA;AA0nBA;;;;;;AA4iFA;AAk0FA;;;;;AA23CA;AA2qFA;AAw2CA;AAglCA;AA0/CA;AAykFA;AA+1FA;;;;;;;;;AAk4CA;AA2zIA;AAk4DA;AAolDA","sourceRoot":""}
|
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;AAu/FA;AA6+FA;;;;;;;;;;;;;;;;;;;;;;;;;;AA0dA;AAkoJA;AAyiCA;;;;;AAskCA;AAg2IA;AAu5GA;AAg1FA;AAwpEA;AAu+CA;AAs/CA;AA6rCA;AAu5EA;AA+5HA;;;;;;;;;;;;;;AA6wGA;AAyoIA;AAiuJA;AA8kHA;AAonGA;AAukEA;AA02DA;AA+2EA;AAuxGA;;;;;;AAu8EA;AA44FA;;;;;AAi5CA;AA2qFA;AAw2CA;AA2kCA;AAm/CA;AAwwEA;AAq8FA;;;;;;;;;AA82BA;AA2zIA;AAk4DA;AAolDA;;;;;;AA6kCA;AA8iHA;AAipGA","sourceRoot":""}
|
||||||
6
dist/swagger-ui-standalone-preset.js
vendored
6
dist/swagger-ui-standalone-preset.js
vendored
File diff suppressed because one or more lines are too long
2
dist/swagger-ui-standalone-preset.js.map
vendored
2
dist/swagger-ui-standalone-preset.js.map
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"swagger-ui-standalone-preset.js","sources":["webpack:///swagger-ui-standalone-preset.js"],"mappings":"AAAA;;;;;AA4QA;AAitGA","sourceRoot":""}
|
{"version":3,"file":"swagger-ui-standalone-preset.js","sources":["webpack:///swagger-ui-standalone-preset.js"],"mappings":"AAAA;;;;;AA6PA;AAyiGA","sourceRoot":""}
|
||||||
2
dist/swagger-ui.css
vendored
2
dist/swagger-ui.css
vendored
File diff suppressed because one or more lines are too long
14
dist/swagger-ui.js
vendored
14
dist/swagger-ui.js
vendored
File diff suppressed because one or more lines are too long
2
dist/swagger-ui.js.map
vendored
2
dist/swagger-ui.js.map
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AA4wCA;AAoyHA;AAuxHA;AAy4FA;AA8rCA;AAugCA;AA+hCA;AA24BA","sourceRoot":""}
|
{"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AA0xCA;AAoyHA;AAuxHA;AAy4FA;AAktCA;AAmgCA;AA0iCA;AA+3BA","sourceRoot":""}
|
||||||
@@ -26,7 +26,7 @@ export default class Oauth2 extends React.Component {
|
|||||||
let username = auth && auth.get("username") || ""
|
let username = auth && auth.get("username") || ""
|
||||||
let clientId = auth && auth.get("clientId") || ""
|
let clientId = auth && auth.get("clientId") || ""
|
||||||
let clientSecret = auth && auth.get("clientSecret") || ""
|
let clientSecret = auth && auth.get("clientSecret") || ""
|
||||||
let passwordType = auth && auth.get("passwordType") || "none"
|
let passwordType = auth && auth.get("passwordType") || "basic"
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
name: name,
|
name: name,
|
||||||
@@ -108,44 +108,46 @@ export default class Oauth2 extends React.Component {
|
|||||||
<p className="flow">Flow: <code>{ schema.get("flow") }</code></p>
|
<p className="flow">Flow: <code>{ schema.get("flow") }</code></p>
|
||||||
|
|
||||||
{
|
{
|
||||||
flow === PASSWORD && ( !isAuthorized || isAuthorized && this.state.username) && <Row>
|
flow !== PASSWORD ? null
|
||||||
<Col tablet={2} desktop={2}>username:</Col>
|
: <Row>
|
||||||
<Col tablet={10} desktop={10}>
|
<Row>
|
||||||
|
<label htmlFor="oauth_username">username:</label>
|
||||||
{
|
{
|
||||||
isAuthorized ? <span>{ this.state.username }</span>
|
isAuthorized ? <code> { this.state.username } </code>
|
||||||
: <input type="text" data-name="username" onChange={ this.onInputChange }/>
|
: <Col tablet={10} desktop={10}>
|
||||||
}
|
<input id="oauth_username" type="text" data-name="username" onChange={ this.onInputChange }/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
|
||||||
}
|
}
|
||||||
|
</Row>
|
||||||
{
|
{
|
||||||
flow === PASSWORD && !isAuthorized && <Row>
|
|
||||||
<Col tablet={2} desktop={2}>password:</Col>
|
}
|
||||||
<Col tablet={10} desktop={10}>
|
<Row>
|
||||||
<input type="password" data-name="password" onChange={ this.onInputChange }/>
|
<label htmlFor="oauth_password">password:</label>
|
||||||
|
{
|
||||||
|
isAuthorized ? <code> ****** </code>
|
||||||
|
: <Col tablet={10} desktop={10}>
|
||||||
|
<input id="oauth_password" type="password" data-name="password" onChange={ this.onInputChange }/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
|
||||||
}
|
}
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<label htmlFor="password_type">type:</label>
|
||||||
{
|
{
|
||||||
flow === PASSWORD && <Row>
|
isAuthorized ? <code> { this.state.passwordType } </code>
|
||||||
<Col tablet={2} desktop={2}>type:</Col>
|
: <Col tablet={10} desktop={10}>
|
||||||
<Col tablet={10} desktop={10}>
|
<select id="password_type" data-name="passwordType" onChange={ this.onInputChange }>
|
||||||
{
|
|
||||||
isAuthorized ? <span>{ this.state.passwordType }</span>
|
|
||||||
: <select data-name="passwordType" onChange={ this.onInputChange }>
|
|
||||||
<option value="none">None or other</option>
|
|
||||||
<option value="basic">Basic auth</option>
|
<option value="basic">Basic auth</option>
|
||||||
<option value="request">Request body</option>
|
<option value="request-body">Request body</option>
|
||||||
|
<option value="query">Query parameters</option>
|
||||||
</select>
|
</select>
|
||||||
}
|
|
||||||
</Col>
|
</Col>
|
||||||
|
}
|
||||||
|
</Row>
|
||||||
</Row>
|
</Row>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
( flow === APPLICATION || flow === IMPLICIT || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "none") ) &&
|
( flow === APPLICATION || flow === IMPLICIT || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "basic") ) &&
|
||||||
( !isAuthorized || isAuthorized && this.state.clientId) && <Row>
|
( !isAuthorized || isAuthorized && this.state.clientId) && <Row>
|
||||||
<label htmlFor="client_id">client_id:</label>
|
<label htmlFor="client_id">client_id:</label>
|
||||||
{
|
{
|
||||||
@@ -159,7 +161,7 @@ export default class Oauth2 extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
( flow === APPLICATION || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "none") ) && <Row>
|
( flow === APPLICATION || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "basic") ) && <Row>
|
||||||
<label htmlFor="client_secret">client_secret:</label>
|
<label htmlFor="client_secret">client_secret:</label>
|
||||||
{
|
{
|
||||||
isAuthorized ? <code> ****** </code>
|
isAuthorized ? <code> ****** </code>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default function authorize ( auth, authActions, errActions, configs ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flow === "application") {
|
if (flow === "application") {
|
||||||
authActions.authorizeOauth2Application(auth)
|
authActions.authorizeApplication(auth)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import win from "core/window"
|
import win from "core/window"
|
||||||
import { btoa } from "core/utils"
|
import { btoa, buildFormData } from "core/utils"
|
||||||
|
|
||||||
export const SHOW_AUTH_POPUP = "show_popup"
|
export const SHOW_AUTH_POPUP = "show_popup"
|
||||||
export const AUTHORIZE = "authorize"
|
export const AUTHORIZE = "authorize"
|
||||||
@@ -70,25 +70,33 @@ export function authorizeOauth2(payload) {
|
|||||||
|
|
||||||
export const authorizePassword = ( auth ) => ( { fn, authActions, errActions } ) => {
|
export const authorizePassword = ( auth ) => ( { fn, authActions, errActions } ) => {
|
||||||
let { schema, name, username, password, passwordType, clientId, clientSecret } = auth
|
let { schema, name, username, password, passwordType, clientId, clientSecret } = auth
|
||||||
|
let credentials = {
|
||||||
|
grant_type: "password",
|
||||||
|
scopes: encodeURIComponent(auth.scopes.join(scopeSeparator))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let req = {
|
let req = {
|
||||||
url: schema.get("tokenUrl"),
|
url: schema.get("tokenUrl"),
|
||||||
method: "post",
|
method: "post",
|
||||||
headers: {
|
headers: {
|
||||||
"content-type": "application/x-www-form-urlencoded"
|
"Content-Type": "application/x-www-form-urlencoded"
|
||||||
},
|
},
|
||||||
query: {
|
query: {}
|
||||||
grant_type: "password",
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
scopes: encodeURIComponent(auth.scopes.join(scopeSeparator))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( passwordType === "basic") {
|
if ( passwordType === "basic") {
|
||||||
req.headers.authorization = "Basic " + btoa(clientId + ":" + clientSecret)
|
req.headers.Authorization = "Basic " + btoa(username + ":" + password)
|
||||||
} else if ( passwordType === "request") {
|
} else {
|
||||||
req.query = Object.assign(req.query, { client_id: clientId, client_secret: clientSecret })
|
credentials = Object.assign({}, credentials, {username} , {password})
|
||||||
|
if ( passwordType === "query") {
|
||||||
|
if ( clientId ) { req.query.client_id = clientId }
|
||||||
|
if ( clientSecret ) { req.query.client_secret = clientSecret }
|
||||||
|
} else {
|
||||||
|
credentials = Object.assign({}, credentials, {client_id: clientId}, {client_secret: clientSecret})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
req.body = buildFormData(credentials)
|
||||||
return fn.fetch(req)
|
return fn.fetch(req)
|
||||||
.then(( response ) => {
|
.then(( response ) => {
|
||||||
let token = JSON.parse(response.data)
|
let token = JSON.parse(response.data)
|
||||||
@@ -120,20 +128,30 @@ export const authorizePassword = ( auth ) => ( { fn, authActions, errActions } )
|
|||||||
.catch(err => { errActions.newAuthErr( err ) })
|
.catch(err => { errActions.newAuthErr( err ) })
|
||||||
}
|
}
|
||||||
|
|
||||||
export const authorizeOauth2Application = ( auth ) => ( { fn, authActions, errActions } ) => {
|
export const authorizeApplication = ( auth ) => ( { fn, authActions, errActions } ) => {
|
||||||
let { schema, scopes, name, clientId, clientSecret } = auth
|
let { schema, scopes, name, clientId, clientSecret } = auth
|
||||||
|
let credentials = {
|
||||||
|
grant_type: "client_credentials",
|
||||||
|
client_id: clientId,
|
||||||
|
client_secret: clientSecret,
|
||||||
|
scope: scopes.join(scopeSeparator)
|
||||||
|
}
|
||||||
|
|
||||||
fn.fetch(schema.get("tokenUrl"), {
|
|
||||||
method: "post", headers: {
|
return fn.fetch({
|
||||||
|
url: schema.get("tokenUrl"),
|
||||||
|
method: "post",
|
||||||
|
headers: {
|
||||||
"Accept":"application/json, text/plain, */*",
|
"Accept":"application/json, text/plain, */*",
|
||||||
"Content-Type": "application/x-www-form-urlencoded"
|
"Content-Type": "application/x-www-form-urlencoded"
|
||||||
},
|
},
|
||||||
body: "grant_type=client_credentials" +
|
body: buildFormData(credentials)
|
||||||
"&client_id=" + encodeURIComponent(clientId) +
|
|
||||||
"&client_secret=" + encodeURIComponent(clientSecret) +
|
|
||||||
"&scope=" + encodeURIComponent(scopes.join(scopeSeparator))
|
|
||||||
})
|
})
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
|
let token = JSON.parse(response.data)
|
||||||
|
let error = token && ( token.error || "" )
|
||||||
|
let parseError = token && ( token.parseError || "" )
|
||||||
|
|
||||||
if ( !response.ok ) {
|
if ( !response.ok ) {
|
||||||
errActions.newAuthErr( {
|
errActions.newAuthErr( {
|
||||||
authId: name,
|
authId: name,
|
||||||
@@ -142,12 +160,19 @@ export const authorizeOauth2Application = ( auth ) => ( { fn, authActions, errAc
|
|||||||
message: response.statusText
|
message: response.statusText
|
||||||
} )
|
} )
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
response.json()
|
|
||||||
.then(function (json){
|
|
||||||
authActions.authorizeOauth2({ auth, token: json})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( error || parseError ) {
|
||||||
|
errActions.newAuthErr({
|
||||||
|
authId: name,
|
||||||
|
level: "error",
|
||||||
|
source: "auth",
|
||||||
|
message: JSON.stringify(token)
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
authActions.authorizeOauth2({ auth, token })
|
||||||
})
|
})
|
||||||
.catch(err => { errActions.newAuthErr( err ) })
|
.catch(err => { errActions.newAuthErr( err ) })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -566,3 +566,15 @@ export const sorters = {
|
|||||||
method: (a, b) => a.get("method").localeCompare(b.get("method"))
|
method: (a, b) => a.get("method").localeCompare(b.get("method"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const buildFormData = (data) => {
|
||||||
|
let formArr = []
|
||||||
|
|
||||||
|
for (let name in data) {
|
||||||
|
let val = data[name]
|
||||||
|
if (val !== undefined && val !== "") {
|
||||||
|
formArr.push([name, "=", encodeURIComponent(val).replace(/%20/g,"+")].join(""))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return formArr.join("&")
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user