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
|
||||
|
||||
let oidcUrl = isOAS3() ? schema.get("openIdConnectUrl") : null
|
||||
|
||||
// Auth type consts
|
||||
const IMPLICIT = "implicit"
|
||||
const PASSWORD = "password"
|
||||
const ACCESS_CODE = isOAS3() ? "authorizationCode" : "accessCode"
|
||||
const APPLICATION = isOAS3() ? "clientCredentials" : "application"
|
||||
const ACCESS_CODE = isOAS3() ? (oidcUrl ? "authorization_code" : "authorizationCode") : "accessCode"
|
||||
const APPLICATION = isOAS3() ? (oidcUrl ? "client_credentials" : "clientCredentials") : "application"
|
||||
|
||||
let flow = schema.get("flow")
|
||||
let scopes = schema.get("allowedScopes") || schema.get("scopes")
|
||||
@@ -144,6 +146,7 @@ export default class Oauth2 extends React.Component {
|
||||
|
||||
{ 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 === 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>
|
||||
|
||||
@@ -26,11 +26,13 @@ export default function authorize ( { auth, authActions, errActions, configs, au
|
||||
break
|
||||
|
||||
case "clientCredentials":
|
||||
case "client_credentials":
|
||||
// OAS3
|
||||
authActions.authorizeApplication(auth)
|
||||
return
|
||||
|
||||
case "authorizationCode":
|
||||
case "authorization_code":
|
||||
// OAS3
|
||||
query.push("response_type=code")
|
||||
break
|
||||
|
||||
@@ -8,10 +8,13 @@ import { isOAS3 as isOAS3Helper } from "../helpers"
|
||||
const state = state => state
|
||||
|
||||
function onlyOAS3(selector) {
|
||||
return (ori, system) => (state, ...args) => {
|
||||
return (ori, system) => (...args) => {
|
||||
const spec = system.getSystem().specSelectors.specJson()
|
||||
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 {
|
||||
return ori(...args)
|
||||
}
|
||||
@@ -57,6 +60,32 @@ export const definitionsToAuthorize = onlyOAS3(createSelector(
|
||||
[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
|
||||
|
||||
@@ -150,6 +150,7 @@ const debResolveSubtrees = debounce(async () => {
|
||||
errSelectors,
|
||||
fn: {
|
||||
resolveSubtree,
|
||||
fetch,
|
||||
AST = {}
|
||||
},
|
||||
specSelectors,
|
||||
@@ -206,6 +207,28 @@ const debResolveSubtrees = debounce(async () => {
|
||||
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(specWithCurrentSubtrees, path, spec)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import { fromJS } from "immutable"
|
||||
import { fromJS, Map } from "immutable"
|
||||
import {
|
||||
definitionsToAuthorize
|
||||
} from "corePlugins/oas3/auth-extensions/wrap-selectors"
|
||||
@@ -12,6 +12,7 @@ describe("oas3 plugin - auth extensions - wrapSelectors", function(){
|
||||
// Given
|
||||
const system = {
|
||||
getSystem: () => system,
|
||||
getState: () => new Map(),
|
||||
specSelectors: {
|
||||
specJson: () => fromJS({
|
||||
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"
|
||||
}
|
||||
},
|
||||
{
|
||||
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