Skip to content

OAS 3.0 Authorization #1159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Oct 21, 2017
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"dependencies": {
"babel-runtime": "^6.23.0",
"btoa": "1.1.2",
"cookie": "^0.3.1",
"deep-extend": "^0.4.1",
"fast-json-patch": "1.1.8",
"isomorphic-fetch": "2.2.1",
Expand Down
29 changes: 28 additions & 1 deletion src/execute/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import isPlainObject from 'lodash/isPlainObject'
import isArray from 'lodash/isArray'
import btoa from 'btoa'
import url from 'url'
import cookie from 'cookie'
import http, {mergeInQueryOrForm} from '../http'
import createError from '../specmap/lib/create-error'

Expand Down Expand Up @@ -109,7 +110,8 @@ export function buildRequest(options) {
// This breaks CORSs... removing this line... probably breaks oAuth. Need to address that
// This also breaks tests
// 'access-control-allow-origin': '*'
}
},
cookies: {}
}

if (requestInterceptor) {
Expand All @@ -124,6 +126,11 @@ export function buildRequest(options) {

// Mostly for testing
if (!operationId) {
// Not removing req.cookies causes testing issues and would
// change our interface, so we're always sure to remove it.
// See the same statement lower down in this function for
// more context.
delete req.cookies
return req
}

Expand Down Expand Up @@ -198,6 +205,26 @@ export function buildRequest(options) {
req = swagger2BuildRequest(versionSpecificOptions, req)
}


// If the cookie convenience object exists in our request,
// serialize its content and then delete the cookie object.
if (req.cookies && Object.keys(req.cookies).length) {
const cookieString = Object.keys(req.cookies).reduce((prev, cookieName) => {
const cookieValue = req.cookies[cookieName]
const prefix = prev ? '&' : ''
const stringified = cookie.serialize(cookieName, cookieValue)
return prev + prefix + stringified
}, '')
req.headers.Cookie = cookieString
}

if (req.cookies) {
// even if no cookies were defined, we need to remove
// the cookies key from our request, or many many legacy
// tests will break.
delete req.cookies
}

// Will add the query object into the URL, if it exists
// ... will also create a FormData instance, if multipart/form-data (eg: a file)
mergeInQueryOrForm(req)
Expand Down
79 changes: 78 additions & 1 deletion src/execute/oas3/build-request.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
// This function runs after the common function,
// `src/execute/index.js#buildRequest`
import assign from 'lodash/assign'
import get from 'lodash/get'
import btoa from 'btoa'

export default function (options, req) {
const {
operation,
requestBody
requestBody,
securities,
spec
} = options

let {
requestContentType
} = options

req = applySecurities({request: req, securities, operation, spec})

const requestBodyDef = operation.requestBody || {}
const requestBodyMediaTypes = Object.keys(requestBodyDef.content || {})

Expand Down Expand Up @@ -64,3 +71,73 @@ export default function (options, req) {

return req
}

// Add security values, to operations - that declare their need on them
// Adapted from the Swagger2 implementation
export function applySecurities({request, securities = {}, operation = {}, spec}) {
const result = assign({}, request)
const {authorized = {}} = securities
const security = operation.security || spec.security || []
const isAuthorized = authorized && !!Object.keys(authorized).length
const securityDef = get(spec, ['components', 'securitySchemes']) || {}

result.headers = result.headers || {}
result.query = result.query || {}

if (!Object.keys(securities).length || !isAuthorized || !security ||
(Array.isArray(operation.security) && !operation.security.length)) {
return request
}

security.forEach((securityObj, index) => {
for (const key in securityObj) {
const auth = authorized[key]
const schema = securityDef[key]

if (!auth) {
continue
}

const value = auth.value || auth
const {type} = schema

if (auth) {
if (type === 'apiKey') {
if (schema.in === 'query') {
result.query[schema.name] = value
}
if (schema.in === 'header') {
result.headers[schema.name] = value
}
if (schema.in === 'cookie') {
result.cookies[schema.name] = value
}
}
else if (type === 'http') {
if (schema.scheme === 'basic') {
const {username, password} = value
const encoded = btoa(`${username}:${password}`)
result.headers.Authorization = `Basic ${encoded}`
}

if (schema.scheme === 'bearer') {
result.headers.Authorization = `Bearer ${value}`
}
}
else if (type === 'oauth2') {
const token = auth.token || {}
const accessToken = token.access_token
let tokenType = token.token_type

if (!tokenType || tokenType.toLowerCase() === 'bearer') {
tokenType = 'Bearer'
}

result.headers.Authorization = `${tokenType} ${accessToken}`
}
}
}
})

return result
}
11 changes: 11 additions & 0 deletions src/execute/oas3/parameter-builders.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,19 @@ function query({req, value, parameter}) {
}
}

const PARAMETER_HEADER_BLACKLIST = [
'accept',
'authorization',
'content-type'
]

function header({req, parameter, value}) {
req.headers = req.headers || {}

if (PARAMETER_HEADER_BLACKLIST.indexOf(parameter.name.toLowerCase()) > -1) {
return
}

if (typeof value !== 'undefined') {
req.headers[parameter.name] = stylize({
key: parameter.name,
Expand Down
2 changes: 1 addition & 1 deletion src/execute/swagger2/build-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import btoa from 'btoa'
import assign from 'lodash/assign'
import http, {mergeInQueryOrForm} from '../../http'
import http from '../../http'


export default function (options, req) {
Expand Down
Loading