fix(auth): support for oauth2 relative url (#6546)

* Handle relative urls for oauth authorization

The full URL is computed based on the current selected server
if a relative URL is used as authorizationUrl
or tokenUrl


Co-authored-by: Eliot Berriot <contact@eliotberriot.com>
This commit is contained in:
Tim Lai
2020-10-21 15:46:31 -07:00
committed by GitHub
parent 07a0416ff6
commit 0a807d6237
4 changed files with 46 additions and 6 deletions

View File

@@ -11,6 +11,7 @@ export default class Oauth2 extends React.Component {
authSelectors: PropTypes.object.isRequired, authSelectors: PropTypes.object.isRequired,
authActions: PropTypes.object.isRequired, authActions: PropTypes.object.isRequired,
errSelectors: PropTypes.object.isRequired, errSelectors: PropTypes.object.isRequired,
oas3Selectors: PropTypes.object.isRequired,
specSelectors: PropTypes.object.isRequired, specSelectors: PropTypes.object.isRequired,
errActions: PropTypes.object.isRequired, errActions: PropTypes.object.isRequired,
getConfigs: PropTypes.any getConfigs: PropTypes.any
@@ -51,12 +52,19 @@ export default class Oauth2 extends React.Component {
} }
authorize =() => { authorize =() => {
let { authActions, errActions, getConfigs, authSelectors } = this.props let { authActions, errActions, getConfigs, authSelectors, oas3Selectors } = this.props
let configs = getConfigs() let configs = getConfigs()
let authConfigs = authSelectors.getConfigs() let authConfigs = authSelectors.getConfigs()
errActions.clear({authId: name,type: "auth", source: "auth"}) errActions.clear({authId: name,type: "auth", source: "auth"})
oauth2Authorize({auth: this.state, authActions, errActions, configs, authConfigs }) oauth2Authorize({
auth: this.state,
currentServer: oas3Selectors.serverEffectiveValue(oas3Selectors.selectedServer()),
authActions,
errActions,
configs,
authConfigs
})
} }
onScopeChange =(e) => { onScopeChange =(e) => {

View File

@@ -1,8 +1,9 @@
import parseUrl from "url-parse"
import win from "core/window" import win from "core/window"
import Im from "immutable" import Im from "immutable"
import { btoa, sanitizeUrl, generateCodeVerifier, createCodeChallenge } from "core/utils" import { btoa, sanitizeUrl, generateCodeVerifier, createCodeChallenge } from "core/utils"
export default function authorize ( { auth, authActions, errActions, configs, authConfigs={} } ) { export default function authorize ( { auth, authActions, errActions, configs, authConfigs={}, currentServer } ) {
let { schema, scopes, name, clientId } = auth let { schema, scopes, name, clientId } = auth
let flow = schema.get("flow") let flow = schema.get("flow")
let query = [] let query = []
@@ -95,7 +96,17 @@ export default function authorize ( { auth, authActions, errActions, configs, au
} }
const authorizationUrl = schema.get("authorizationUrl") const authorizationUrl = schema.get("authorizationUrl")
const sanitizedAuthorizationUrl = sanitizeUrl(authorizationUrl) let sanitizedAuthorizationUrl
if (currentServer) {
// OpenAPI 3
sanitizedAuthorizationUrl = parseUrl(
sanitizeUrl(authorizationUrl),
currentServer,
true
).toString()
} else {
sanitizedAuthorizationUrl = sanitizeUrl(authorizationUrl)
}
let url = [sanitizedAuthorizationUrl, query.join("&")].join(authorizationUrl.indexOf("?") === -1 ? "?" : "&") let url = [sanitizedAuthorizationUrl, query.join("&")].join(authorizationUrl.indexOf("?") === -1 ? "?" : "&")
// pass action authorizeOauth2 and authentication data through window // pass action authorizeOauth2 and authentication data through window

View File

@@ -174,8 +174,8 @@ export const authorizeRequest = ( data ) => ( { fn, getConfigs, authActions, err
let parsedUrl let parsedUrl
if (specSelectors.isOAS3()) { if (specSelectors.isOAS3()) {
const server = oas3Selectors.selectedServer() let finalServerUrl = oas3Selectors.serverEffectiveValue(oas3Selectors.selectedServer())
parsedUrl = parseUrl(url, oas3Selectors.serverEffectiveValue({ server }), true) parsedUrl = parseUrl(url, finalServerUrl, true)
} else { } else {
parsedUrl = parseUrl(url, specSelectors.url(), true) parsedUrl = parseUrl(url, specSelectors.url(), true)
} }

View File

@@ -41,6 +41,27 @@ describe("oauth2", () => {
windowOpenSpy.mockReset() windowOpenSpy.mockReset()
}) })
it("should build authorize url relative", function () {
const windowOpenSpy = jest.spyOn(win, "open")
let relativeMockSchema = {
flow: "accessCode",
authorizationUrl: "/testAuthorizationUrl"
}
let relativeAuthConfig = {
auth: { schema: { get: (key) => relativeMockSchema[key] } },
authActions: {},
errActions: {},
configs: { oauth2RedirectUrl: "" },
authConfigs: {},
currentServer: "https://currentserver"
}
oauth2Authorize(relativeAuthConfig)
expect(windowOpenSpy.mock.calls.length).toEqual(1)
expect(windowOpenSpy.mock.calls[0][0]).toMatch("https://currentserver/testAuthorizationUrl?response_type=code&redirect_uri=&state=")
windowOpenSpy.mockReset()
})
it("should append query parameters to authorizeUrl with query parameters", () => { it("should append query parameters to authorizeUrl with query parameters", () => {
const windowOpenSpy = jest.spyOn(win, "open") const windowOpenSpy = jest.spyOn(win, "open")
mockSchema.authorizationUrl = "https://testAuthorizationUrl?param=1" mockSchema.authorizationUrl = "https://testAuthorizationUrl?param=1"