Merge pull request #2979 from bodnia/fix-oauth2-issue

fixes password, application oauth2 flows
This commit is contained in:
Anna
2017-04-26 17:11:23 +02:00
committed by GitHub
11 changed files with 160 additions and 120 deletions

File diff suppressed because one or more lines are too long

View File

@@ -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":""}

File diff suppressed because one or more lines are too long

View File

@@ -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

File diff suppressed because one or more lines are too long

14
dist/swagger-ui.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -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":""}

View File

@@ -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>

View File

@@ -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
} }

View File

@@ -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 ) })
} }

View File

@@ -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("&")
}