From c6d8d779d05cb2c0c44da982d50d9722ba28d812 Mon Sep 17 00:00:00 2001 From: Christian Egli Date: Wed, 26 Jan 2022 10:56:09 +0100 Subject: [PATCH] feat: do not ask for client secret when using auth code with PKCE (#7438) Co-authored-by: Ignacio Lozano Co-authored-by: Vladimir Gorej Refs #6290 --- src/core/components/auth/oauth2.jsx | 10 ++-- .../auth-code-flow-pkce-without-secret.yaml | 25 ++++++++++ .../auth-code-flow-pkce-without-secret.js | 47 +++++++++++++++++++ 3 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 test/e2e-cypress/static/documents/features/auth-code-flow-pkce-without-secret.yaml create mode 100644 test/e2e-cypress/tests/features/auth-code-flow-pkce-without-secret.js diff --git a/src/core/components/auth/oauth2.jsx b/src/core/components/auth/oauth2.jsx index 7fec252f..a83340b8 100644 --- a/src/core/components/auth/oauth2.jsx +++ b/src/core/components/auth/oauth2.jsx @@ -130,7 +130,11 @@ export default class Oauth2 extends React.Component { const AUTH_FLOW_ACCESS_CODE = isOAS3() ? (oidcUrl ? "authorization_code" : "authorizationCode") : "accessCode" const AUTH_FLOW_APPLICATION = isOAS3() ? (oidcUrl ? "client_credentials" : "clientCredentials") : "application" + let authConfigs = authSelectors.getConfigs() + let isPkceCodeGrant = authConfigs.usePkceWithAuthorizationCodeGrant === "true" || authConfigs.usePkceWithAuthorizationCodeGrant === true + let flow = schema.get("flow") + let flowToDisplay = flow === AUTH_FLOW_ACCESS_CODE && isPkceCodeGrant ? flow + " with PKCE" : flow let scopes = schema.get("allowedScopes") || schema.get("scopes") let authorizedAuth = authSelectors.authorized().get(name) let isAuthorized = !!authorizedAuth @@ -140,7 +144,7 @@ export default class Oauth2 extends React.Component { return (
-

{name} (OAuth2, { schema.get("flow") })

+

{name} (OAuth2, { flowToDisplay })

{ !this.state.appName ? null :
Application: { this.state.appName }
} { description && } @@ -149,7 +153,7 @@ export default class Oauth2 extends React.Component { { oidcUrl &&

OpenID Connect URL: { oidcUrl }

} { ( flow === AUTH_FLOW_IMPLICIT || flow === AUTH_FLOW_ACCESS_CODE ) &&

Authorization URL: { schema.get("authorizationUrl") }

} { ( flow === AUTH_FLOW_PASSWORD || flow === AUTH_FLOW_ACCESS_CODE || flow === AUTH_FLOW_APPLICATION ) &&

Token URL: { schema.get("tokenUrl") }

} -

Flow: { schema.get("flow") }

+

Flow: { flowToDisplay }

{ flow !== AUTH_FLOW_PASSWORD ? null @@ -208,7 +212,7 @@ export default class Oauth2 extends React.Component { } { - ( (flow === AUTH_FLOW_APPLICATION || flow === AUTH_FLOW_ACCESS_CODE || flow === AUTH_FLOW_PASSWORD) && + ( (flow === AUTH_FLOW_APPLICATION || flow === AUTH_FLOW_ACCESS_CODE || flow === AUTH_FLOW_PASSWORD) && !isPkceCodeGrant && { isAuthorized ? ****** diff --git a/test/e2e-cypress/static/documents/features/auth-code-flow-pkce-without-secret.yaml b/test/e2e-cypress/static/documents/features/auth-code-flow-pkce-without-secret.yaml new file mode 100644 index 00000000..dcc0b44c --- /dev/null +++ b/test/e2e-cypress/static/documents/features/auth-code-flow-pkce-without-secret.yaml @@ -0,0 +1,25 @@ +openapi: 3.0.0 + +info: + version: "1.0" + title: PKCE Flow + +paths: + /: + get: + summary: dummy operation + responses: + "200": + description: OK + +components: + securitySchemes: + testAuthCodeFlow: + type: oauth2 + flows: + authorizationCode: + authorizationUrl: /oauth/authorize + tokenUrl: /oauth/token + scopes: + read: read whatever you want + write: write whatever you want diff --git a/test/e2e-cypress/tests/features/auth-code-flow-pkce-without-secret.js b/test/e2e-cypress/tests/features/auth-code-flow-pkce-without-secret.js new file mode 100644 index 00000000..7d14bb9c --- /dev/null +++ b/test/e2e-cypress/tests/features/auth-code-flow-pkce-without-secret.js @@ -0,0 +1,47 @@ +describe("Check client_secret for OAuth2 Authorization Code flow with and without PKCE (#6290)", () => { + it("should not display client_secret field for authorization code flow with PKCE", () => { + cy.visit( + "/?url=/documents/features/auth-code-flow-pkce-without-secret.yaml" + ) + .window() + .then(win => { + // set auth config to use PKCE + let authConfigs = win.ui.authSelectors.getConfigs() + win.ui.authActions.configureAuth({ + ...authConfigs, + usePkceWithAuthorizationCodeGrant: true, + }) + }) + .get("button.authorize") + .click() + .get("h4") + .contains("authorizationCode with PKCE") + .get(".flow") + .contains("authorizationCode with PKCE") + .get("#client_secret") + .should("not.exist") + }) + + it("should display client_secret field for authorization code flow without PKCE", () => { + cy.visit( + "/?url=/documents/features/auth-code-flow-pkce-without-secret.yaml" + ) + .window() + .then(win => { + // set auth config to not use PKCE + let authConfigs = win.ui.authSelectors.getConfigs() + win.ui.authActions.configureAuth({ + ...authConfigs, + usePkceWithAuthorizationCodeGrant: false, + }) + }) + .get("button.authorize") + .click() + .get("h4") + .contains("authorizationCode") + .get(".flow") + .contains("authorizationCode") + .get("#client_secret") + .should("exist") + }) +})