@@ -27,7 +27,10 @@ | |||||
isValid = qp.state === sentState | isValid = qp.state === sentState | ||||
if (oauth2.auth.schema.get("flow") === "accessCode" && !oauth2.auth.code) { | |||||
if (( | |||||
oauth2.auth.schema.get("flow") === "accessCode"|| | |||||
oauth2.auth.schema.get("flow") === "authorizationCode" | |||||
) && !oauth2.auth.code) { | |||||
if (!isValid) { | if (!isValid) { | ||||
oauth2.errCb({ | oauth2.errCb({ | ||||
authId: oauth2.auth.name, | authId: oauth2.auth.name, | ||||
@@ -27,7 +27,10 @@ | |||||
isValid = qp.state === sentState | isValid = qp.state === sentState | ||||
if (oauth2.auth.schema.get("flow") === "accessCode" && !oauth2.auth.code) { | |||||
if (( | |||||
oauth2.auth.schema.get("flow") === "accessCode"|| | |||||
oauth2.auth.schema.get("flow") === "authorizationCode" | |||||
) && !oauth2.auth.code) { | |||||
if (!isValid) { | if (!isValid) { | ||||
oauth2.errCb({ | oauth2.errCb({ | ||||
authId: oauth2.auth.name, | authId: oauth2.auth.name, | ||||
@@ -2,11 +2,6 @@ import React from "react" | |||||
import PropTypes from "prop-types" | import PropTypes from "prop-types" | ||||
import oauth2Authorize from "core/oauth2-authorize" | import oauth2Authorize from "core/oauth2-authorize" | ||||
const IMPLICIT = "implicit" | |||||
const ACCESS_CODE = "accessCode" | |||||
const PASSWORD = "password" | |||||
const APPLICATION = "application" | |||||
export default class Oauth2 extends React.Component { | export default class Oauth2 extends React.Component { | ||||
static propTypes = { | static propTypes = { | ||||
name: PropTypes.string, | name: PropTypes.string, | ||||
@@ -83,7 +78,9 @@ export default class Oauth2 extends React.Component { | |||||
} | } | ||||
render() { | render() { | ||||
let { schema, getComponent, authSelectors, errSelectors, name } = this.props | |||||
let { | |||||
schema, getComponent, authSelectors, errSelectors, name, specSelectors | |||||
} = this.props | |||||
const Input = getComponent("Input") | const Input = getComponent("Input") | ||||
const Row = getComponent("Row") | const Row = getComponent("Row") | ||||
const Col = getComponent("Col") | const Col = getComponent("Col") | ||||
@@ -92,6 +89,14 @@ export default class Oauth2 extends React.Component { | |||||
const JumpToPath = getComponent("JumpToPath", true) | const JumpToPath = getComponent("JumpToPath", true) | ||||
const Markdown = getComponent( "Markdown" ) | const Markdown = getComponent( "Markdown" ) | ||||
const { isOAS3 } = specSelectors | |||||
// Auth type consts | |||||
const IMPLICIT = "implicit" | |||||
const PASSWORD = "password" | |||||
const ACCESS_CODE = isOAS3() ? "authorizationCode" : "accessCode" | |||||
const APPLICATION = isOAS3() ? "clientCredentials" : "application" | |||||
let flow = schema.get("flow") | let flow = schema.get("flow") | ||||
let scopes = schema.get("allowedScopes") || schema.get("scopes") | let scopes = schema.get("allowedScopes") || schema.get("scopes") | ||||
let authorizedAuth = authSelectors.authorized().get(name) | let authorizedAuth = authSelectors.authorized().get(name) | ||||
@@ -22,6 +22,16 @@ export default function authorize ( { auth, authActions, errActions, configs, au | |||||
case "implicit": | case "implicit": | ||||
query.push("response_type=token") | query.push("response_type=token") | ||||
break | break | ||||
case "clientCredentials": | |||||
// OAS3 | |||||
authActions.authorizeApplication(auth) | |||||
return | |||||
case "authorizationCode": | |||||
// OAS3 | |||||
query.push("response_type=code") | |||||
break | |||||
} | } | ||||
if (typeof clientId === "string") { | if (typeof clientId === "string") { | ||||
@@ -10,7 +10,7 @@ export const shownDefinitions = createSelector( | |||||
export const definitionsToAuthorize = createSelector( | export const definitionsToAuthorize = createSelector( | ||||
state, | state, | ||||
() =>( { specSelectors } ) => { | |||||
() => ( { specSelectors } ) => { | |||||
let definitions = specSelectors.securityDefinitions() | let definitions = specSelectors.securityDefinitions() | ||||
let list = List() | let list = List() | ||||
@@ -27,7 +27,7 @@ export const definitionsToAuthorize = createSelector( | |||||
) | ) | ||||
export const getDefinitionsByNames = ( state, securities ) =>( { specSelectors } ) => { | |||||
export const getDefinitionsByNames = ( state, securities ) => ( { specSelectors } ) => { | |||||
let securityDefinitions = specSelectors.securityDefinitions() | let securityDefinitions = specSelectors.securityDefinitions() | ||||
let result = List() | let result = List() | ||||
@@ -64,7 +64,7 @@ export const authorized = createSelector( | |||||
) | ) | ||||
export const isAuthorized = ( state, securities ) =>( { authSelectors } ) => { | |||||
export const isAuthorized = ( state, securities ) => ( { authSelectors } ) => { | |||||
let authorized = authSelectors.authorized() | let authorized = authSelectors.authorized() | ||||
if(!List.isList(securities)) { | if(!List.isList(securities)) { | ||||
@@ -1,29 +1,51 @@ | |||||
import { createSelector } from "reselect" | import { createSelector } from "reselect" | ||||
import { List } from "immutable" | |||||
import { List, Map, fromJS } from "immutable" | |||||
import { isOAS3 as isOAS3Helper } from "../helpers" | import { isOAS3 as isOAS3Helper } from "../helpers" | ||||
// Helpers | // Helpers | ||||
const state = state => state | |||||
function onlyOAS3(selector) { | function onlyOAS3(selector) { | ||||
return (ori, system) => (...args) => { | return (ori, system) => (...args) => { | ||||
const spec = system.getSystem().specSelectors.specJson() | const spec = system.getSystem().specSelectors.specJson() | ||||
if(isOAS3Helper(spec)) { | if(isOAS3Helper(spec)) { | ||||
return selector(...args) | |||||
return selector(system, ...args) | |||||
} else { | } else { | ||||
return ori(...args) | return ori(...args) | ||||
} | } | ||||
} | } | ||||
} | } | ||||
const nullSelector = createSelector(() => null) | |||||
export const definitionsToAuthorize = onlyOAS3(createSelector( | |||||
state, | |||||
({ specSelectors }) => { | |||||
// Coerce our OpenAPI 3.0 definitions into monoflow definitions | |||||
// that look like Swagger2 definitions. | |||||
let definitions = specSelectors.securityDefinitions() | |||||
let list = List() | |||||
definitions.entrySeq().forEach( ([ defName, definition ]) => { | |||||
definition.get("flows").entrySeq().forEach(([flowKey, flowVal]) => { | |||||
let translatedDef = fromJS({ | |||||
flow: flowKey, | |||||
authorizationUrl: flowVal.get("authorizationUrl"), | |||||
tokenUrl: flowVal.get("tokenUrl"), | |||||
scopes: flowVal.get("scopes"), | |||||
type: definition.get("type") | |||||
}) | |||||
const OAS3NullSelector = onlyOAS3(nullSelector) | |||||
list = list.push(new Map({ | |||||
[defName]: translatedDef.filter((v) => { | |||||
// filter out unset values, sometimes `authorizationUrl` | |||||
// and `tokenUrl` come out as `undefined` in the data | |||||
return v !== undefined | |||||
}) | |||||
})) | |||||
}) | |||||
}) | |||||
// Hasta la vista, authentication! | |||||
export const shownDefinitions = OAS3NullSelector | |||||
export const definitionsToAuthorize = OAS3NullSelector | |||||
export const getDefinitionsByNames = OAS3NullSelector | |||||
export const authorized = onlyOAS3(() => List()) | |||||
export const isAuthorized = OAS3NullSelector | |||||
export const getConfigs = OAS3NullSelector | |||||
return list | |||||
} | |||||
)) |
@@ -48,12 +48,16 @@ export const definitions = onlyOAS3(createSelector( | |||||
spec => spec.getIn(["components", "schemas"]) || Map() | spec => spec.getIn(["components", "schemas"]) || Map() | ||||
)) | )) | ||||
export const securityDefinitions = onlyOAS3(createSelector( | |||||
spec, | |||||
spec => spec.getIn(["components", "securitySchemes"]) || Map() | |||||
)) | |||||
export const host = OAS3NullSelector | export const host = OAS3NullSelector | ||||
export const basePath = OAS3NullSelector | export const basePath = OAS3NullSelector | ||||
export const consumes = OAS3NullSelector | export const consumes = OAS3NullSelector | ||||
export const produces = OAS3NullSelector | export const produces = OAS3NullSelector | ||||
export const schemes = OAS3NullSelector | export const schemes = OAS3NullSelector | ||||
export const securityDefinitions = OAS3NullSelector | |||||
// New selectors | // New selectors | ||||
@@ -0,0 +1,116 @@ | |||||
/* eslint-env mocha */ | |||||
import expect, { createSpy } from "expect" | |||||
import { Map, fromJS } from "immutable" | |||||
import { | |||||
definitionsToAuthorize | |||||
} from "corePlugins/oas3/auth-extensions/wrap-selectors" | |||||
describe.only("oas3 plugin - auth extensions - wrapSelectors", function(){ | |||||
describe("execute", function(){ | |||||
it("should add `securities` to the oriAction call", function(){ | |||||
// Given | |||||
const system = { | |||||
getSystem: () => system, | |||||
specSelectors: { | |||||
specJson: () => fromJS({ | |||||
openapi: "3.0.0" | |||||
}), | |||||
securityDefinitions: () => { | |||||
return fromJS({ | |||||
"oauth2AuthorizationCode": { | |||||
"type": "oauth2", | |||||
"flows": { | |||||
"authorizationCode": { | |||||
"authorizationUrl": "http://google.com/", | |||||
"tokenUrl": "http://google.com/", | |||||
"scopes": { | |||||
"myScope": "our only scope" | |||||
} | |||||
} | |||||
} | |||||
}, | |||||
"oauth2Multiflow": { | |||||
"type": "oauth2", | |||||
"flows": { | |||||
"clientCredentials": { | |||||
"tokenUrl": "http://google.com/", | |||||
"scopes": { | |||||
"myScope": "our only scope" | |||||
} | |||||
}, | |||||
"password": { | |||||
"tokenUrl": "http://google.com/", | |||||
"scopes": { | |||||
"myScope": "our only scope" | |||||
} | |||||
}, | |||||
"authorizationCode": { | |||||
"authorizationUrl": "http://google.com/", | |||||
"tokenUrl": "http://google.com/", | |||||
"scopes": { | |||||
"myScope": "our only scope" | |||||
} | |||||
} | |||||
} | |||||
} | |||||
}) | |||||
} | |||||
} | |||||
} | |||||
// When | |||||
let res = definitionsToAuthorize(() => null, system)() | |||||
// Then | |||||
expect(res.toJS()).toEqual([ | |||||
{ | |||||
oauth2AuthorizationCode: { | |||||
flow: "authorizationCode", | |||||
authorizationUrl: "http://google.com/", | |||||
tokenUrl: "http://google.com/", | |||||
scopes: { | |||||
"myScope": "our only scope" | |||||
}, | |||||
type: "oauth2" | |||||
} | |||||
}, | |||||
{ | |||||
oauth2Multiflow: { | |||||
flow: "clientCredentials", | |||||
tokenUrl: "http://google.com/", | |||||
scopes: { | |||||
"myScope": "our only scope" | |||||
}, | |||||
type: "oauth2" | |||||
} | |||||
}, | |||||
{ | |||||
oauth2Multiflow: { | |||||
flow: "password", | |||||
tokenUrl: "http://google.com/", | |||||
scopes: { | |||||
"myScope": "our only scope" | |||||
}, | |||||
type: "oauth2" | |||||
} | |||||
}, | |||||
{ | |||||
oauth2Multiflow: { | |||||
flow: "authorizationCode", | |||||
authorizationUrl: "http://google.com/", | |||||
tokenUrl: "http://google.com/", | |||||
scopes: { | |||||
"myScope": "our only scope" | |||||
}, | |||||
type: "oauth2" | |||||
} | |||||
}, | |||||
]) | |||||
}) | |||||
}) | |||||
}) |