From fe5f02f4e119613045ea96329dbcd6b59f8c2eac Mon Sep 17 00:00:00 2001 From: Curtis Conard Date: Mon, 21 Apr 2025 12:20:20 -0400 Subject: [PATCH 1/8] fix authcode redirect loop and ip restriction middleware for internal auth --- .../Api/HL/Middleware/CookieAuthMiddleware.php | 18 +++++++++++++----- .../IPRestrictionRequestMiddleware.php | 5 +++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Glpi/Api/HL/Middleware/CookieAuthMiddleware.php b/src/Glpi/Api/HL/Middleware/CookieAuthMiddleware.php index 36145648241..f2ade8b3fcc 100644 --- a/src/Glpi/Api/HL/Middleware/CookieAuthMiddleware.php +++ b/src/Glpi/Api/HL/Middleware/CookieAuthMiddleware.php @@ -43,15 +43,23 @@ public function process(MiddlewareInput $input, callable $next): void { $auth = new \Auth(); if ($auth->getAlternateAuthSystemsUserLogin(\Auth::COOKIE)) { - // User could be authenticated by a cookie - // Need to use cookies for session and start it manually - ini_set('session.use_cookies', '1'); - Session::start(); + $t = ''; + } + if (session_status() !== PHP_SESSION_NONE) { + $t = ''; + } + + // User could be authenticated by a cookie + // Need to use cookies for session and start it manually + ini_set('session.use_cookies', '1'); + Session::start(); + + if (($user_id = Session::getLoginUserID()) !== false) { // unset the response to indicate a successful auth $input->response = null; $input->client = [ 'client_id' => 'internal', // Internal just means the user was authenticated internally either by cookie or an already existing session. - 'users_id' => Session::getLoginUserID(), + 'users_id' => $user_id, 'scopes' => [] ]; } else { diff --git a/src/Glpi/Api/HL/Middleware/IPRestrictionRequestMiddleware.php b/src/Glpi/Api/HL/Middleware/IPRestrictionRequestMiddleware.php index f5400b5e0f2..17632b4f30c 100644 --- a/src/Glpi/Api/HL/Middleware/IPRestrictionRequestMiddleware.php +++ b/src/Glpi/Api/HL/Middleware/IPRestrictionRequestMiddleware.php @@ -53,13 +53,14 @@ public function process(MiddlewareInput $input, callable $next): void $request_ip = $_SERVER['REMOTE_ADDR']; - $allowed_ips = $DB->request([ + $result = $DB->request([ 'SELECT' => ['allowed_ips'], 'FROM' => 'glpi_oauthclients', 'WHERE' => [ 'identifier' => $client['client_id'] ] - ])->current()['allowed_ips']; + ])->current(); + $allowed_ips = $result['allowed_ips'] ?? []; if (empty($allowed_ips)) { // No IP restriction From 166f41514b95da0afeedc4ce757f4a7dba41d7a2 Mon Sep 17 00:00:00 2001 From: Curtis Conard Date: Tue, 22 Apr 2025 11:14:30 -0400 Subject: [PATCH 2/8] start authcode oauth e2e test --- tests/cypress/e2e/oauth_authcode.cy.js | 117 +++++++++++++++++++++++++ tests/src/autoload/functions.php | 16 ++++ 2 files changed, 133 insertions(+) create mode 100644 tests/cypress/e2e/oauth_authcode.cy.js diff --git a/tests/cypress/e2e/oauth_authcode.cy.js b/tests/cypress/e2e/oauth_authcode.cy.js new file mode 100644 index 00000000000..b3f73d74458 --- /dev/null +++ b/tests/cypress/e2e/oauth_authcode.cy.js @@ -0,0 +1,117 @@ +/** + * --------------------------------------------------------------------- + * + * GLPI - Gestionnaire Libre de Parc Informatique + * + * http://glpi-project.org + * + * @copyright 2015-2025 Teclib' and contributors. + * @licence https://www.gnu.org/licenses/gpl-3.0.html + * + * --------------------------------------------------------------------- + * + * LICENSE + * + * This file is part of GLPI. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * --------------------------------------------------------------------- + */ + +describe('OAuth - Authorization Code Grant', () => { + const oauthclient_id = '9246d35072ff62193330003a8106d947fafe5ac036d11a51ebc7ca11b9bc135e'; + const oauthclient_secret = 'd2c4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1'; + + function doAuthCodeGrant(expect_already_logged_in = false, remember_me = false) { + function doGLPILogin(redirect_url, username_field, password_field, csrf_token) { + // cy.findByRole('textbox', {'name': "Login"}).type('e2e_tests'); + // cy.findByLabelText("Password").type('glpi'); + // if (remember_me) { + // cy.findByRole('checkbox', {name: "Remember me"}).check(); + // } else { + // cy.findByRole('checkbox', {name: "Remember me"}).uncheck(); + // } + // cy.getDropdownByLabelText("Login source").selectDropdownValue('GLPI internal database'); + // cy.findByRole('button', {name: "Sign in"}).click(); + + // Do login as request instead of visit + const body = { + [username_field]: 'e2e_tests', + [password_field]: 'glpi', + auth: 0, + _glpi_csrf_token: csrf_token, + redirect: redirect_url, + noAUTO: 0 + }; + if (remember_me) { + body.login_remember = 1; + } + cy.request({ + method: 'POST', + url: '/front/login.php', + form: true, + body: body, + }).then((response) => { + expect(response.status).to.eq(200); + }); + } + + function doAuthorization() { + + } + + cy.request({ + method: 'GET', + url: '/api.php/Authorize', + qs: { + response_type: 'code', + client_id: oauthclient_id, + scope: 'api user', + redirect_uri: '/api.php/oauth2/redirection', + //state: 'test_state' + }, + }).then((response) => { + expect(response.status).to.eq(200); + expect(response.allRequestResponses).to.have.length(2); + + expect(response.allRequestResponses[1]['Request URL']).to.contain( + encodeURIComponent(`/api.php/v2/authorize?scope=api+user&client_id=${oauthclient_id}&response_type=code&redirect_uri=${encodeURIComponent('/api.php/oauth2/redirection')}`) + ); + + if (!expect_already_logged_in) { + // Should be on a GLPI login page + const parsed_html = Cypress.$(`
${response.body}
`); + expect(parsed_html.find('title').text()).to.eq('Authentication - GLPI'); + const redirect_url = parsed_html.find('input[name="redirect"]').val(); + const username_field = parsed_html.find('#login_name').attr('name'); + const password_field = parsed_html.find('#login_password').attr('name'); + const csrf_token = parsed_html.find('input[name="_glpi_csrf_token"]').val(); + doGLPILogin(redirect_url, username_field, password_field, csrf_token); + } + doAuthorization(); + }); + } + + it('Should authorize without cookie - no remember me', () => { + doAuthCodeGrant(); + }); + // it('Should authorize without cookie - remember me', () => { + // doAuthCodeGrant(false, true); + // }); + // it('Should authorize with cookie', () => { + // cy.login(); + // doAuthCodeGrant(true); + // }); +}); diff --git a/tests/src/autoload/functions.php b/tests/src/autoload/functions.php index 1b5d84a4f64..e676d4d2834 100644 --- a/tests/src/autoload/functions.php +++ b/tests/src/autoload/functions.php @@ -669,6 +669,14 @@ function loadDataset() 'is_active' => 1, 'is_confidential' => 1, 'name' => 'Test OAuth Client', + ], + [ + 'redirect_uri' => ["/api.php/oauth2/redirection"], + 'grants' => ['authorization_code'], + 'scopes' => ['api', 'user'], + 'is_active' => 1, + 'is_confidential' => 1, + 'name' => 'Test E2E OAuth Client', ] ], 'CartridgeItem' => [ @@ -756,6 +764,14 @@ function loadDataset() } Search::$search = []; Config::setConfigurationValues('phpunit', ['dataset' => $data['_version']]); + + // Set well known OAuth client ID and secret to be used in E2E tests where we cannot find the secret + $e2e_oauth = getItemByTypeName('OAuthClient', 'Test E2E OAuth Client'); + $e2e_oauth->update([ + 'id' => $e2e_oauth->getID(), + 'identifier' => '9246d35072ff62193330003a8106d947fafe5ac036d11a51ebc7ca11b9bc135e', + 'secret' => 'd2c4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1' + ]); } $DB->commit(); From 22e5c48d0cdecbc80ff5c1482750ef086e019543 Mon Sep 17 00:00:00 2001 From: Curtis Conard Date: Thu, 24 Apr 2025 09:10:35 -0400 Subject: [PATCH 3/8] remove phpunit test --- .../Api/HL/Controller/CoreControllerTest.php | 49 ------------------- tests/cypress/e2e/oauth_authcode.cy.js | 10 ++-- 2 files changed, 4 insertions(+), 55 deletions(-) diff --git a/phpunit/functional/Glpi/Api/HL/Controller/CoreControllerTest.php b/phpunit/functional/Glpi/Api/HL/Controller/CoreControllerTest.php index 5a2c3d5dcbd..d95b0a57598 100644 --- a/phpunit/functional/Glpi/Api/HL/Controller/CoreControllerTest.php +++ b/phpunit/functional/Glpi/Api/HL/Controller/CoreControllerTest.php @@ -320,55 +320,6 @@ public function testOAuthPasswordGrantHeader() }); } - public function testOAuthAuthCodeGrant() - { - // Not a complete end to end test. Not sure how that could be done. Should probably be using Cypress. - global $DB; - - // Create an OAuth client - $client = new \OAuthClient(); - $client_id = $client->add([ - 'name' => __FUNCTION__, - 'is_active' => 1, - 'is_confidential' => 1, - ]); - $this->assertGreaterThan(0, $client_id); - - $client->update([ - 'id' => $client_id, - 'grants' => ['authorization_code'], - 'redirect_uri' => ["/api.php/oauth2/redirection"], - ]); - - // get client ID and secret - $it = $DB->request([ - 'SELECT' => ['identifier', 'secret', 'redirect_uri'], - 'FROM' => \OAuthClient::getTable(), - 'WHERE' => ['id' => $client_id], - ]); - $this->assertCount(1, $it); - $client_data = $it->current(); - - // Test authorize endpoint - $request = new Request('GET', '/Authorize', [], null); - $request = $request->withQueryParams([ - 'response_type' => 'code', - 'client_id' => $client_data['identifier'], - 'scope' => '', - 'redirect_uri' => json_decode($client_data['redirect_uri'])[0], - ]); - - $this->api->call($request, function ($call) { - /** @var \HLAPICallAsserter $call */ - $call->response - ->status(fn ($status) => $this->assertEquals(302, $status)) - ->headers(function ($headers) { - global $CFG_GLPI; - $this->assertMatchesRegularExpression('/^' . preg_quote($CFG_GLPI['url_base'], '/') . '\/\?redirect=/', $headers['Location']); - }); - }); - } - public function testOAuthClientCredentialsGrant(): void { global $DB; diff --git a/tests/cypress/e2e/oauth_authcode.cy.js b/tests/cypress/e2e/oauth_authcode.cy.js index b3f73d74458..113d5158c99 100644 --- a/tests/cypress/e2e/oauth_authcode.cy.js +++ b/tests/cypress/e2e/oauth_authcode.cy.js @@ -35,7 +35,7 @@ describe('OAuth - Authorization Code Grant', () => { const oauthclient_secret = 'd2c4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1'; function doAuthCodeGrant(expect_already_logged_in = false, remember_me = false) { - function doGLPILogin(redirect_url, username_field, password_field, csrf_token) { + function doGLPILogin(redirect_url, csrf_token) { // cy.findByRole('textbox', {'name': "Login"}).type('e2e_tests'); // cy.findByLabelText("Password").type('glpi'); // if (remember_me) { @@ -48,8 +48,8 @@ describe('OAuth - Authorization Code Grant', () => { // Do login as request instead of visit const body = { - [username_field]: 'e2e_tests', - [password_field]: 'glpi', + login_name: 'e2e_tests', + login_password: 'glpi', auth: 0, _glpi_csrf_token: csrf_token, redirect: redirect_url, @@ -95,10 +95,8 @@ describe('OAuth - Authorization Code Grant', () => { const parsed_html = Cypress.$(`
${response.body}
`); expect(parsed_html.find('title').text()).to.eq('Authentication - GLPI'); const redirect_url = parsed_html.find('input[name="redirect"]').val(); - const username_field = parsed_html.find('#login_name').attr('name'); - const password_field = parsed_html.find('#login_password').attr('name'); const csrf_token = parsed_html.find('input[name="_glpi_csrf_token"]').val(); - doGLPILogin(redirect_url, username_field, password_field, csrf_token); + doGLPILogin(redirect_url, csrf_token); } doAuthorization(); }); From 75cbd8d51ebdaefd17b3dd12a2b423f4c276fe49 Mon Sep 17 00:00:00 2001 From: Curtis Conard Date: Thu, 24 Apr 2025 13:14:26 -0400 Subject: [PATCH 4/8] use visit --- install/empty_data.php | 11 ++++ src/Glpi/Application/Environment.php | 2 +- tests/cypress/e2e/oauth_authcode.cy.js | 70 +++++--------------------- tests/src/autoload/functions.php | 16 ------ 4 files changed, 25 insertions(+), 74 deletions(-) diff --git a/install/empty_data.php b/install/empty_data.php index cc0b2f3e89c..7020aafdf03 100644 --- a/install/empty_data.php +++ b/install/empty_data.php @@ -9522,6 +9522,17 @@ public function getEmptyData(): array 'is_recursive' => 1, 'is_dynamic' => 0, ]; + + $tables['glpi_oauthclients'][] = [ + 'name' => 'Test E2E OAuth Client', + 'redirect_uri' => json_encode(["/api.php/oauth2/redirection"]), + 'grants' => json_encode(['authorization_code']), + 'scopes' => json_encode(['api', 'user']), + 'is_active' => 1, + 'is_confidential' => 1, + 'identifier' => '9246d35072ff62193330003a8106d947fafe5ac036d11a51ebc7ca11b9bc135e', + 'secret' => 'd2c4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1' + ]; } return $tables; diff --git a/src/Glpi/Application/Environment.php b/src/Glpi/Application/Environment.php index 4ec3c25703c..9e459c6ccb7 100644 --- a/src/Glpi/Application/Environment.php +++ b/src/Glpi/Application/Environment.php @@ -178,7 +178,7 @@ public function shouldExpectRessourcesToChange(): bool // In others environments, we must match for changes. return match ($this) { default => false, - self::DEVELOPMENT => true, + self::DEVELOPMENT, self::TESTING => true, }; } diff --git a/tests/cypress/e2e/oauth_authcode.cy.js b/tests/cypress/e2e/oauth_authcode.cy.js index 113d5158c99..ea53622840e 100644 --- a/tests/cypress/e2e/oauth_authcode.cy.js +++ b/tests/cypress/e2e/oauth_authcode.cy.js @@ -35,71 +35,27 @@ describe('OAuth - Authorization Code Grant', () => { const oauthclient_secret = 'd2c4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1'; function doAuthCodeGrant(expect_already_logged_in = false, remember_me = false) { - function doGLPILogin(redirect_url, csrf_token) { - // cy.findByRole('textbox', {'name': "Login"}).type('e2e_tests'); - // cy.findByLabelText("Password").type('glpi'); - // if (remember_me) { - // cy.findByRole('checkbox', {name: "Remember me"}).check(); - // } else { - // cy.findByRole('checkbox', {name: "Remember me"}).uncheck(); - // } - // cy.getDropdownByLabelText("Login source").selectDropdownValue('GLPI internal database'); - // cy.findByRole('button', {name: "Sign in"}).click(); - - // Do login as request instead of visit - const body = { - login_name: 'e2e_tests', - login_password: 'glpi', - auth: 0, - _glpi_csrf_token: csrf_token, - redirect: redirect_url, - noAUTO: 0 - }; + function doGLPILogin() { + cy.findByRole('textbox', {'name': "Login"}).type('e2e_tests'); + cy.findByLabelText("Password").type('glpi'); if (remember_me) { - body.login_remember = 1; + cy.findByRole('checkbox', {name: "Remember me"}).check(); + } else { + cy.findByRole('checkbox', {name: "Remember me"}).uncheck(); } - cy.request({ - method: 'POST', - url: '/front/login.php', - form: true, - body: body, - }).then((response) => { - expect(response.status).to.eq(200); - }); + cy.getDropdownByLabelText("Login source").selectDropdownValue('GLPI internal database'); + cy.findByRole('button', {name: "Sign in"}).click(); } function doAuthorization() { } - cy.request({ - method: 'GET', - url: '/api.php/Authorize', - qs: { - response_type: 'code', - client_id: oauthclient_id, - scope: 'api user', - redirect_uri: '/api.php/oauth2/redirection', - //state: 'test_state' - }, - }).then((response) => { - expect(response.status).to.eq(200); - expect(response.allRequestResponses).to.have.length(2); - - expect(response.allRequestResponses[1]['Request URL']).to.contain( - encodeURIComponent(`/api.php/v2/authorize?scope=api+user&client_id=${oauthclient_id}&response_type=code&redirect_uri=${encodeURIComponent('/api.php/oauth2/redirection')}`) - ); - - if (!expect_already_logged_in) { - // Should be on a GLPI login page - const parsed_html = Cypress.$(`
${response.body}
`); - expect(parsed_html.find('title').text()).to.eq('Authentication - GLPI'); - const redirect_url = parsed_html.find('input[name="redirect"]').val(); - const csrf_token = parsed_html.find('input[name="_glpi_csrf_token"]').val(); - doGLPILogin(redirect_url, csrf_token); - } - doAuthorization(); - }); + cy.visit(`/api.php/Authorize?response_type=code&client_id=${oauthclient_id}&scope=api user&redirect_uri=/api.php/oauth2/redirection`); + if (!expect_already_logged_in) { + doGLPILogin(); + } + doAuthorization(); } it('Should authorize without cookie - no remember me', () => { diff --git a/tests/src/autoload/functions.php b/tests/src/autoload/functions.php index e676d4d2834..1b5d84a4f64 100644 --- a/tests/src/autoload/functions.php +++ b/tests/src/autoload/functions.php @@ -669,14 +669,6 @@ function loadDataset() 'is_active' => 1, 'is_confidential' => 1, 'name' => 'Test OAuth Client', - ], - [ - 'redirect_uri' => ["/api.php/oauth2/redirection"], - 'grants' => ['authorization_code'], - 'scopes' => ['api', 'user'], - 'is_active' => 1, - 'is_confidential' => 1, - 'name' => 'Test E2E OAuth Client', ] ], 'CartridgeItem' => [ @@ -764,14 +756,6 @@ function loadDataset() } Search::$search = []; Config::setConfigurationValues('phpunit', ['dataset' => $data['_version']]); - - // Set well known OAuth client ID and secret to be used in E2E tests where we cannot find the secret - $e2e_oauth = getItemByTypeName('OAuthClient', 'Test E2E OAuth Client'); - $e2e_oauth->update([ - 'id' => $e2e_oauth->getID(), - 'identifier' => '9246d35072ff62193330003a8106d947fafe5ac036d11a51ebc7ca11b9bc135e', - 'secret' => 'd2c4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1' - ]); } $DB->commit(); From e4c67743447495b63ff5e4695d56eb3be7fa6300 Mon Sep 17 00:00:00 2001 From: Curtis Conard Date: Fri, 25 Apr 2025 15:57:29 -0400 Subject: [PATCH 5/8] missed secret encrypt --- install/empty_data.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/empty_data.php b/install/empty_data.php index 7020aafdf03..8084c0703f9 100644 --- a/install/empty_data.php +++ b/install/empty_data.php @@ -9531,7 +9531,7 @@ public function getEmptyData(): array 'is_active' => 1, 'is_confidential' => 1, 'identifier' => '9246d35072ff62193330003a8106d947fafe5ac036d11a51ebc7ca11b9bc135e', - 'secret' => 'd2c4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1' + 'secret' => (new GLPIKey())->encrypt('d2c4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1e4f3b8a0e1f7b5c6a9d1') ]; } From 6401f73cb27953e2160d5d5641ec6e77412bc923 Mon Sep 17 00:00:00 2001 From: Curtis Conard Date: Fri, 25 Apr 2025 15:57:49 -0400 Subject: [PATCH 6/8] need to set session path in some cases --- src/Glpi/Api/HL/Middleware/CookieAuthMiddleware.php | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/Glpi/Api/HL/Middleware/CookieAuthMiddleware.php b/src/Glpi/Api/HL/Middleware/CookieAuthMiddleware.php index f2ade8b3fcc..5dafccca590 100644 --- a/src/Glpi/Api/HL/Middleware/CookieAuthMiddleware.php +++ b/src/Glpi/Api/HL/Middleware/CookieAuthMiddleware.php @@ -41,17 +41,10 @@ class CookieAuthMiddleware extends AbstractMiddleware implements AuthMiddlewareI { public function process(MiddlewareInput $input, callable $next): void { - $auth = new \Auth(); - if ($auth->getAlternateAuthSystemsUserLogin(\Auth::COOKIE)) { - $t = ''; - } - if (session_status() !== PHP_SESSION_NONE) { - $t = ''; - } - // User could be authenticated by a cookie // Need to use cookies for session and start it manually ini_set('session.use_cookies', '1'); + Session::setPath(); Session::start(); if (($user_id = Session::getLoginUserID()) !== false) { From 77e9871a23b30c788130ccaecb577be096525a08 Mon Sep 17 00:00:00 2001 From: Curtis Conard Date: Fri, 25 Apr 2025 15:58:13 -0400 Subject: [PATCH 7/8] complete tests --- tests/cypress/e2e/oauth_authcode.cy.js | 52 ++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/tests/cypress/e2e/oauth_authcode.cy.js b/tests/cypress/e2e/oauth_authcode.cy.js index ea53622840e..d4399c863a1 100644 --- a/tests/cypress/e2e/oauth_authcode.cy.js +++ b/tests/cypress/e2e/oauth_authcode.cy.js @@ -48,7 +48,43 @@ describe('OAuth - Authorization Code Grant', () => { } function doAuthorization() { - + // Should be on a page asking the user to approve or reject the authorization request + cy.findByRole('heading', {name: 'Test E2E OAuth Client wants to access your GLPI account'}).should('be.visible'); + cy.findByText('Access to the API').should('be.visible'); + cy.findByText('Access to the user\'s information').should('be.visible'); + cy.findByRole('button', {name: 'Deny'}).should('be.visible'); + // Clicking the Accept button would go to a 401 error page, because we didn't give a real redirect URL, which Cypress will have issues with because it isn't an HTML page + // We only care that the redirect URL includes the code parameter + cy.url().then((url) => { + cy.request({ + url: `${url}&accept=1`, + failOnStatusCode: false + }).then((response) => { + expect(response.status).to.eq(401); + expect(response.redirects[0]).to.include('code='); + // extract the code from the URL + const code = response.redirects[0].split('code=')[1]; + // Request the token now + cy.request({ + method: 'POST', + url: '/api.php/token', + body: { + grant_type: 'authorization_code', + client_id: oauthclient_id, + client_secret: oauthclient_secret, + code: code, + redirect_uri: '/api.php/oauth2/redirection' + }, + headers: { + 'Content-Type': 'application/json' + } + }).then((response) => { + expect(response.status).to.eq(200); + expect(response.body.access_token).to.exist; + expect(response.body.refresh_token).to.exist; + }); + }); + }); } cy.visit(`/api.php/Authorize?response_type=code&client_id=${oauthclient_id}&scope=api user&redirect_uri=/api.php/oauth2/redirection`); @@ -61,11 +97,11 @@ describe('OAuth - Authorization Code Grant', () => { it('Should authorize without cookie - no remember me', () => { doAuthCodeGrant(); }); - // it('Should authorize without cookie - remember me', () => { - // doAuthCodeGrant(false, true); - // }); - // it('Should authorize with cookie', () => { - // cy.login(); - // doAuthCodeGrant(true); - // }); + it('Should authorize without cookie - remember me', () => { + doAuthCodeGrant(false, true); + }); + it('Should authorize with cookie', () => { + cy.login(); + doAuthCodeGrant(true); + }); }); From 616743ad16f213ecb86e0bf3c242bbba37ada128 Mon Sep 17 00:00:00 2001 From: Curtis Conard Date: Mon, 28 Apr 2025 20:43:10 -0400 Subject: [PATCH 8/8] ignore e2e oauth client during update test --- tests/src/Command/TestUpdatedDataCommand.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/src/Command/TestUpdatedDataCommand.php b/tests/src/Command/TestUpdatedDataCommand.php index adc6295aeba..e07e536db5c 100644 --- a/tests/src/Command/TestUpdatedDataCommand.php +++ b/tests/src/Command/TestUpdatedDataCommand.php @@ -171,6 +171,11 @@ public function __construct($dbhost, $dbuser, $dbpassword, $dbdefault) continue; } + // Ignore e2e oauth client + if ($table_name === 'glpi_oauthclients' && $row_data['name'] === 'Test E2E OAuth Client') { + continue; + } + foreach ($row_data as $key => $value) { if (in_array($key, $excluded_fields)) { continue; // Ignore fields that would be subject to legitimate changes