spec/actions.js: Add OIDC metadata fetching components/auth/oauth2: Add OIDC URL to the Authorization popup
This commit is contained in:
@@ -122,11 +122,13 @@ export default class Oauth2 extends React.Component {
|
|||||||
|
|
||||||
const { isOAS3 } = specSelectors
|
const { isOAS3 } = specSelectors
|
||||||
|
|
||||||
|
let oidcUrl = isOAS3() ? schema.get("openIdConnectUrl") : null
|
||||||
|
|
||||||
// Auth type consts
|
// Auth type consts
|
||||||
const IMPLICIT = "implicit"
|
const IMPLICIT = "implicit"
|
||||||
const PASSWORD = "password"
|
const PASSWORD = "password"
|
||||||
const ACCESS_CODE = isOAS3() ? "authorizationCode" : "accessCode"
|
const ACCESS_CODE = isOAS3() ? (oidcUrl ? "authorization_code" : "authorizationCode") : "accessCode"
|
||||||
const APPLICATION = isOAS3() ? "clientCredentials" : "application"
|
const APPLICATION = isOAS3() ? (oidcUrl ? "client_credentials" : "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")
|
||||||
@@ -144,6 +146,7 @@ export default class Oauth2 extends React.Component {
|
|||||||
|
|
||||||
{ isAuthorized && <h6>Authorized</h6> }
|
{ isAuthorized && <h6>Authorized</h6> }
|
||||||
|
|
||||||
|
{ oidcUrl && <p>OpenID Connect URL: <code>{ oidcUrl }</code></p> }
|
||||||
{ ( flow === IMPLICIT || flow === ACCESS_CODE ) && <p>Authorization URL: <code>{ schema.get("authorizationUrl") }</code></p> }
|
{ ( flow === IMPLICIT || flow === ACCESS_CODE ) && <p>Authorization URL: <code>{ schema.get("authorizationUrl") }</code></p> }
|
||||||
{ ( flow === PASSWORD || flow === ACCESS_CODE || flow === APPLICATION ) && <p>Token URL:<code> { schema.get("tokenUrl") }</code></p> }
|
{ ( flow === PASSWORD || flow === ACCESS_CODE || flow === APPLICATION ) && <p>Token URL:<code> { schema.get("tokenUrl") }</code></p> }
|
||||||
<p className="flow">Flow: <code>{ schema.get("flow") }</code></p>
|
<p className="flow">Flow: <code>{ schema.get("flow") }</code></p>
|
||||||
|
|||||||
@@ -26,11 +26,13 @@ export default function authorize ( { auth, authActions, errActions, configs, au
|
|||||||
break
|
break
|
||||||
|
|
||||||
case "clientCredentials":
|
case "clientCredentials":
|
||||||
|
case "client_credentials":
|
||||||
// OAS3
|
// OAS3
|
||||||
authActions.authorizeApplication(auth)
|
authActions.authorizeApplication(auth)
|
||||||
return
|
return
|
||||||
|
|
||||||
case "authorizationCode":
|
case "authorizationCode":
|
||||||
|
case "authorization_code":
|
||||||
// OAS3
|
// OAS3
|
||||||
query.push("response_type=code")
|
query.push("response_type=code")
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -8,10 +8,13 @@ import { isOAS3 as isOAS3Helper } from "../helpers"
|
|||||||
const state = state => state
|
const state = state => state
|
||||||
|
|
||||||
function onlyOAS3(selector) {
|
function onlyOAS3(selector) {
|
||||||
return (ori, system) => (state, ...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(system, ...args)
|
// Pass the spec plugin state to Reselect to trigger on securityDefinitions update
|
||||||
|
let resolvedSchemes = system.getState().getIn(["spec", "resolvedSubtrees",
|
||||||
|
"components", "securitySchemes"])
|
||||||
|
return selector(system, resolvedSchemes, ...args)
|
||||||
} else {
|
} else {
|
||||||
return ori(...args)
|
return ori(...args)
|
||||||
}
|
}
|
||||||
@@ -57,6 +60,32 @@ export const definitionsToAuthorize = onlyOAS3(createSelector(
|
|||||||
[defName]: definition
|
[defName]: definition
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
if(type === "openIdConnect" && definition.get("openIdConnectData")) {
|
||||||
|
let oidcData = definition.get("openIdConnectData")
|
||||||
|
let grants = oidcData.get("grant_types_supported") || ["authorization_code", "implicit"]
|
||||||
|
grants.forEach((grant) => {
|
||||||
|
// Convert from OIDC list of scopes to the OAS-style map with empty descriptions
|
||||||
|
let translatedScopes = oidcData.get("scopes_supported") &&
|
||||||
|
oidcData.get("scopes_supported").reduce((acc, cur) => acc.set(cur, ""), new Map())
|
||||||
|
|
||||||
|
let translatedDef = fromJS({
|
||||||
|
flow: grant,
|
||||||
|
authorizationUrl: oidcData.get("authorization_endpoint"),
|
||||||
|
tokenUrl: oidcData.get("token_endpoint"),
|
||||||
|
scopes: translatedScopes,
|
||||||
|
type: "oauth2",
|
||||||
|
openIdConnectUrl: definition.get("openIdConnectUrl")
|
||||||
|
})
|
||||||
|
|
||||||
|
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
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return list
|
return list
|
||||||
|
|||||||
@@ -150,6 +150,7 @@ const debResolveSubtrees = debounce(async () => {
|
|||||||
errSelectors,
|
errSelectors,
|
||||||
fn: {
|
fn: {
|
||||||
resolveSubtree,
|
resolveSubtree,
|
||||||
|
fetch,
|
||||||
AST = {}
|
AST = {}
|
||||||
},
|
},
|
||||||
specSelectors,
|
specSelectors,
|
||||||
@@ -206,6 +207,28 @@ const debResolveSubtrees = debounce(async () => {
|
|||||||
errActions.newThrownErrBatch(preparedErrors)
|
errActions.newThrownErrBatch(preparedErrors)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (spec && specSelectors.isOAS3() && path[0] === "components" && path[1] === "securitySchemes") {
|
||||||
|
// Resolve OIDC URLs if present
|
||||||
|
await Promise.all(Object.values(spec)
|
||||||
|
.filter((scheme) => scheme.type === "openIdConnect")
|
||||||
|
.map(async (oidcScheme) => {
|
||||||
|
const req = {
|
||||||
|
url: oidcScheme.openIdConnectUrl,
|
||||||
|
requestInterceptor: requestInterceptor,
|
||||||
|
responseInterceptor: responseInterceptor
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const res = await fetch(req)
|
||||||
|
if (res instanceof Error || res.status >= 400) {
|
||||||
|
console.error(res.statusText + " " + req.url)
|
||||||
|
} else {
|
||||||
|
oidcScheme.openIdConnectData = JSON.parse(res.text)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
set(resultMap, path, spec)
|
set(resultMap, path, spec)
|
||||||
set(specWithCurrentSubtrees, path, spec)
|
set(specWithCurrentSubtrees, path, spec)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
import { fromJS } from "immutable"
|
import { fromJS, Map } from "immutable"
|
||||||
import {
|
import {
|
||||||
definitionsToAuthorize
|
definitionsToAuthorize
|
||||||
} from "corePlugins/oas3/auth-extensions/wrap-selectors"
|
} from "corePlugins/oas3/auth-extensions/wrap-selectors"
|
||||||
@@ -12,6 +12,7 @@ describe("oas3 plugin - auth extensions - wrapSelectors", function(){
|
|||||||
// Given
|
// Given
|
||||||
const system = {
|
const system = {
|
||||||
getSystem: () => system,
|
getSystem: () => system,
|
||||||
|
getState: () => new Map(),
|
||||||
specSelectors: {
|
specSelectors: {
|
||||||
specJson: () => fromJS({
|
specJson: () => fromJS({
|
||||||
openapi: "3.0.0"
|
openapi: "3.0.0"
|
||||||
@@ -53,7 +54,39 @@ describe("oas3 plugin - auth extensions - wrapSelectors", function(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"oidc": {
|
||||||
|
"type": "openIdConnect",
|
||||||
|
"openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration",
|
||||||
|
"openIdConnectData": {
|
||||||
|
"authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
|
||||||
|
"token_endpoint": "https://oauth2.googleapis.com/token",
|
||||||
|
"scopes_supported": [
|
||||||
|
"openid",
|
||||||
|
"email",
|
||||||
|
"profile"
|
||||||
|
],
|
||||||
|
"grant_types_supported": [
|
||||||
|
"authorization_code",
|
||||||
|
"refresh_token",
|
||||||
|
"urn:ietf:params:oauth:grant-type:device_code",
|
||||||
|
"urn:ietf:params:oauth:grant-type:jwt-bearer"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"oidcNoGrant": {
|
||||||
|
"type": "openIdConnect",
|
||||||
|
"openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration",
|
||||||
|
"openIdConnectData": {
|
||||||
|
"authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
|
||||||
|
"token_endpoint": "https://oauth2.googleapis.com/token",
|
||||||
|
"scopes_supported": [
|
||||||
|
"openid",
|
||||||
|
"email",
|
||||||
|
"profile"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,6 +139,96 @@ describe("oas3 plugin - auth extensions - wrapSelectors", function(){
|
|||||||
type: "oauth2"
|
type: "oauth2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
oidc: {
|
||||||
|
flow: "authorization_code",
|
||||||
|
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
||||||
|
tokenUrl: "https://oauth2.googleapis.com/token",
|
||||||
|
openIdConnectUrl: "https://accounts.google.com/.well-known/openid-configuration",
|
||||||
|
scopes: {
|
||||||
|
"openid": "",
|
||||||
|
"email": "",
|
||||||
|
"profile": "",
|
||||||
|
},
|
||||||
|
type: "oauth2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oidc: {
|
||||||
|
flow: "refresh_token",
|
||||||
|
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
||||||
|
tokenUrl: "https://oauth2.googleapis.com/token",
|
||||||
|
openIdConnectUrl: "https://accounts.google.com/.well-known/openid-configuration",
|
||||||
|
scopes: {
|
||||||
|
"openid": "",
|
||||||
|
"email": "",
|
||||||
|
"profile": "",
|
||||||
|
},
|
||||||
|
type: "oauth2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oidc: {
|
||||||
|
flow: "urn:ietf:params:oauth:grant-type:device_code",
|
||||||
|
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
||||||
|
tokenUrl: "https://oauth2.googleapis.com/token",
|
||||||
|
openIdConnectUrl: "https://accounts.google.com/.well-known/openid-configuration",
|
||||||
|
scopes: {
|
||||||
|
"openid": "",
|
||||||
|
"email": "",
|
||||||
|
"profile": "",
|
||||||
|
},
|
||||||
|
type: "oauth2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oidc: {
|
||||||
|
flow: "urn:ietf:params:oauth:grant-type:jwt-bearer",
|
||||||
|
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
||||||
|
tokenUrl: "https://oauth2.googleapis.com/token",
|
||||||
|
openIdConnectUrl: "https://accounts.google.com/.well-known/openid-configuration",
|
||||||
|
scopes: {
|
||||||
|
"openid": "",
|
||||||
|
"email": "",
|
||||||
|
"profile": "",
|
||||||
|
},
|
||||||
|
type: "oauth2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
|
||||||
|
// grant_types_supported
|
||||||
|
// OPTIONAL. JSON array containing a list of the OAuth 2.0 Grant Type values that
|
||||||
|
// this OP supports. Dynamic OpenID Providers MUST support the authorization_code
|
||||||
|
// and implicit Grant Type values and MAY support other Grant Types. If omitted,
|
||||||
|
// the default value is ["authorization_code", "implicit"].
|
||||||
|
oidcNoGrant: {
|
||||||
|
flow: "authorization_code",
|
||||||
|
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
||||||
|
tokenUrl: "https://oauth2.googleapis.com/token",
|
||||||
|
openIdConnectUrl: "https://accounts.google.com/.well-known/openid-configuration",
|
||||||
|
scopes: {
|
||||||
|
"openid": "",
|
||||||
|
"email": "",
|
||||||
|
"profile": "",
|
||||||
|
},
|
||||||
|
type: "oauth2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oidcNoGrant: {
|
||||||
|
flow: "implicit",
|
||||||
|
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
||||||
|
tokenUrl: "https://oauth2.googleapis.com/token",
|
||||||
|
openIdConnectUrl: "https://accounts.google.com/.well-known/openid-configuration",
|
||||||
|
scopes: {
|
||||||
|
"openid": "",
|
||||||
|
"email": "",
|
||||||
|
"profile": "",
|
||||||
|
},
|
||||||
|
type: "oauth2"
|
||||||
|
}
|
||||||
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user