|
| 1 | +<?php namespace Tests; |
| 2 | +/** |
| 3 | + * Copyright 2026 OpenStack Foundation |
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | + * you may not use this file except in compliance with the License. |
| 6 | + * You may obtain a copy of the License at |
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | + * Unless required by applicable law or agreed to in writing, software |
| 9 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 10 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 11 | + * See the License for the specific language governing permissions and |
| 12 | + * limitations under the License. |
| 13 | + **/ |
| 14 | + |
| 15 | +use LaravelDoctrine\ORM\Facades\EntityManager; |
| 16 | +use Models\OAuth2\Client; |
| 17 | + |
| 18 | +/** |
| 19 | + * Class OAuth2EndSessionTest |
| 20 | + * NOTE: deliberately NOT placed in OAuth2ProtocolTestCase.php - that file's *TestCase.php suffix |
| 21 | + * keeps it OUT of the Application Test Suite (PHPUnit only auto-discovers *Test.php), so a test |
| 22 | + * added there would never run in CI. |
| 23 | + * @package Tests |
| 24 | + */ |
| 25 | +final class OAuth2EndSessionTest extends OpenStackIDBaseTestCase |
| 26 | +{ |
| 27 | + public function testEndSessionRedirectsVerbatimToAuthorityLessPostLogoutUri() |
| 28 | + { |
| 29 | + // RFC 8252 SS7.1 authority-less URIs (com.example.app:/logout) fail Laravel's |
| 30 | + // UrlGenerator::isValidUrl() (FILTER_VALIDATE_URL-based), so Redirect::to() inside |
| 31 | + // IndirectResponseQueryStringStrategy used to treat the approved post-logout target as a |
| 32 | + // RELATIVE path and prefix the site URL (Location: http://<idp>/com.example.app:/logout) - |
| 33 | + // corrupting the redirect at the emitter even once the runtime allow-gates accept the |
| 34 | + // authority-less form. The Location header must carry the registered URI verbatim, with the |
| 35 | + // state round-tripped on the query string. |
| 36 | + $client = EntityManager::getRepository(Client::class)->findOneBy(['app_name' => 'oauth2_native_app']); |
| 37 | + $client->setPostLogoutRedirectUris('com.example.app:/logout'); |
| 38 | + EntityManager::persist($client); |
| 39 | + EntityManager::flush(); |
| 40 | + |
| 41 | + $this->call('GET', '/oauth2/end-session', [ |
| 42 | + 'client_id' => $client->getClientId(), |
| 43 | + 'post_logout_redirect_uri' => 'com.example.app:/logout', |
| 44 | + 'state' => 'xyz', |
| 45 | + ]); |
| 46 | + |
| 47 | + $this->assertResponseStatus(302); |
| 48 | + $this->assertEquals('com.example.app:/logout?state=xyz', $this->response->headers->get('Location')); |
| 49 | + } |
| 50 | +} |
0 commit comments