2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								< ? php  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  Tests\Auth ;  
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-18 00:56:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								use  BookStack\Activity\ActivityType ;  
						 
					
						
							
								
									
										
										
										
											2023-04-28 06:40:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								use  BookStack\Facades\Theme ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								use  BookStack\Theming\ThemeEvents ;  
						 
					
						
							
								
									
										
										
										
											2023-05-18 00:56:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								use  BookStack\Users\Models\Role ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								use  BookStack\Users\Models\User ;  
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								use  GuzzleHttp\Psr7\Response ;  
						 
					
						
							
								
									
										
										
										
											2022-07-23 22:10:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								use  Illuminate\Testing\TestResponse ;  
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								use  Tests\Helpers\OidcJwtHelper ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								use  Tests\TestCase ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  OidcTest  extends  TestCase  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2022-02-24 22:16:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    protected  string  $keyFilePath ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    protected  $keyFile ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-31 04:29:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    protected  function  setUp () :  void 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        parent :: setUp (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Set default config for OpenID Connect
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> keyFile  =  tmpfile (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> keyFilePath  =  'file://'  .  stream_get_meta_data ( $this -> keyFile )[ 'uri' ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        file_put_contents ( $this -> keyFilePath ,  OidcJwtHelper :: publicPemKey ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'auth.method'                  =>  'oidc' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'auth.defaults.guard'          =>  'oidc' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.name'                    =>  'SingleSignOn-Testing' , 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 18:50:58 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            'oidc.display_name_claims'     =>  'name' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'oidc.client_id'               =>  OidcJwtHelper :: defaultClientId (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.client_secret'           =>  'testpass' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.jwt_public_key'          =>  $this -> keyFilePath , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.issuer'                  =>  OidcJwtHelper :: defaultIssuer (), 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'oidc.authorization_endpoint'  =>  'https://oidc.local/auth' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'oidc.token_endpoint'          =>  'https://oidc.local/token' , 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-18 06:24:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            'oidc.userinfo_endpoint'       =>  'https://oidc.local/userinfo' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'oidc.discover'                =>  false , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.dump_user_details'       =>  false , 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-02 23:56:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            'oidc.additional_scopes'       =>  '' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.user_to_groups'          =>  false , 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-06 23:32:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            'oidc.groups_claim'            =>  'group' , 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-02 23:56:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'oidc.remove_from_groups'      =>  false , 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-27 00:43:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            'oidc.external_id_claim'       =>  'sub' , 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-08 01:45:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            'oidc.end_session_endpoint'    =>  false , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-31 04:29:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    protected  function  tearDown () :  void 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        parent :: tearDown (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( file_exists ( $this -> keyFilePath ))  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            unlink ( $this -> keyFilePath ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_login_option_shows_on_login_page () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $req  =  $this -> get ( '/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $req -> assertSeeText ( 'SingleSignOn-Testing' ); 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-23 22:10:18 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> withHtml ( $req ) -> assertElementExists ( 'form[action$="/oidc/login"][method=POST] button' ); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_oidc_routes_are_only_active_if_oidc_enabled () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 'auth.method'  =>  'standard' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $routes  =  [ '/login'  =>  'post' ,  '/callback'  =>  'get' ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        foreach  ( $routes  as  $uri  =>  $method )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $req  =  $this -> call ( $method ,  '/oidc'  .  $uri ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> assertPermissionError ( $req ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_forgot_password_routes_inaccessible () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> get ( '/password/email' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertPermissionError ( $resp ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> post ( '/password/email' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertPermissionError ( $resp ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> get ( '/password/reset/abc123' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertPermissionError ( $resp ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> post ( '/password/reset' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertPermissionError ( $resp ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_standard_login_routes_inaccessible () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> post ( '/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertPermissionError ( $resp ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_logout_route_functions () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-21 19:08:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        $this -> actingAs ( $this -> users -> editor ()); 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-15 05:13:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        $this -> post ( '/logout' ); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_user_invite_routes_inaccessible () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> get ( '/register/invite/abc123' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertPermissionError ( $resp ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> post ( '/register/invite/abc123' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertPermissionError ( $resp ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_user_register_routes_inaccessible () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> get ( '/register' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertPermissionError ( $resp ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> post ( '/register' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertPermissionError ( $resp ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_login () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $req  =  $this -> post ( '/oidc/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $redirect  =  $req -> headers -> get ( 'location' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertStringStartsWith ( 'https://oidc.local/auth' ,  $redirect ,  'Login redirects to SSO location' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( $this -> isAuthenticated ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertStringContainsString ( 'scope=openid%20profile%20email' ,  $redirect ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertStringContainsString ( 'client_id='  .  OidcJwtHelper :: defaultClientId (),  $redirect ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertStringContainsString ( 'redirect_uri='  .  urlencode ( url ( '/oidc/callback' )),  $redirect ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_login_success_flow () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Start auth
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> post ( '/oidc/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $state  =  session () -> get ( 'oidc_state' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-08 21:16:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        $transactions  =  $this -> mockHttpClient ([ $this -> getMockAuthorizationResponse ([ 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'email'  =>  'benny@example.com' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'sub'    =>  'benny1010101' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ])]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Callback from auth provider
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // App calls token endpoint to get id token
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> get ( '/oidc/callback?code=SplxlOBeZQQYbYS6WxSbIA&state='  .  $state ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/' ); 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-08 21:16:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 1 ,  $transactions -> requestCount ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $tokenRequest  =  $transactions -> latestRequest (); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 'https://oidc.local/token' ,  ( string )  $tokenRequest -> getUri ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 'POST' ,  $tokenRequest -> getMethod ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 'Basic '  .  base64_encode ( OidcJwtHelper :: defaultClientId ()  .  ':testpass' ),  $tokenRequest -> getHeader ( 'Authorization' )[ 0 ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertStringContainsString ( 'grant_type=authorization_code' ,  $tokenRequest -> getBody ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertStringContainsString ( 'code=SplxlOBeZQQYbYS6WxSbIA' ,  $tokenRequest -> getBody ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertStringContainsString ( 'redirect_uri='  .  urlencode ( url ( '/oidc/callback' )),  $tokenRequest -> getBody ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertTrue ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertDatabaseHas ( 'users' ,  [ 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'email'             =>  'benny@example.com' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'external_auth_id'  =>  'benny1010101' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'email_confirmed'   =>  false , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $user  =  User :: query () -> where ( 'email' ,  '=' ,  'benny@example.com' ) -> first (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertActivityExists ( ActivityType :: AUTH_LOGIN ,  null ,  " oidc; ( { $user -> id } ) Barry Scott " ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-02 23:56:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    public  function  test_login_uses_custom_additional_scopes_if_defined () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.additional_scopes'  =>  'groups, badgers' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $redirect  =  $this -> post ( '/oidc/login' ) -> headers -> get ( 'location' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertStringContainsString ( 'scope=openid%20profile%20email%20groups%20badgers' ,  $redirect ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    public  function  test_callback_fails_if_no_state_present_or_matching () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> get ( '/oidc/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=abc124' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertSessionError ( 'Login using SingleSignOn-Testing failed, system did not provide successful authorization' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> post ( '/oidc/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> get ( '/oidc/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=abc124' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertSessionError ( 'Login using SingleSignOn-Testing failed, system did not provide successful authorization' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_dump_user_details_option_outputs_as_expected () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ( 'oidc.dump_user_details' ,  true ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'email'  =>  'benny@example.com' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'sub'    =>  'benny505' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertStatus ( 200 ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertJson ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'email'  =>  'benny@example.com' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'sub'    =>  'benny505' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'iss'    =>  OidcJwtHelper :: defaultIssuer (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'aud'    =>  OidcJwtHelper :: defaultClientId (), 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_auth_fails_if_no_email_exists_in_user_data () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-18 06:24:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        config () -> set ( 'oidc.userinfo_endpoint' ,  null ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> runLogin ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'email'  =>  '' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'sub'    =>  'benny505' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertSessionError ( 'Could not find an email address, for this user, in the data provided by the external authentication system' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_auth_fails_if_already_logged_in () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> asEditor (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> runLogin ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'email'  =>  'benny@example.com' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'sub'    =>  'benny505' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertSessionError ( 'Already logged in' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_auth_login_as_existing_user () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-21 19:08:34 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $editor  =  $this -> users -> editor (); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $editor -> external_auth_id  =  'benny505' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $editor -> save (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> runLogin ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'email'  =>  'benny@example.com' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'sub'    =>  'benny505' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertTrue ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( $editor -> id ,  auth () -> user () -> id ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_auth_login_as_existing_user_email_with_different_auth_id_fails () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-21 19:08:34 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $editor  =  $this -> users -> editor (); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $editor -> external_auth_id  =  'editor101' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $editor -> save (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-02-24 22:16:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'email'  =>  $editor -> email , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'sub'    =>  'benny505' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-24 22:16:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> followRedirects ( $resp ); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-02-24 22:16:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $resp -> assertSeeText ( 'A user with the email '  .  $editor -> email  .  ' already exists but with different credentials.' ); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_auth_login_with_invalid_token_fails () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-24 22:16:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'sub'  =>  null , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-24 22:16:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> followRedirects ( $resp ); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-18 06:24:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $resp -> assertSeeText ( 'ID token validation failed with error: Missing token subject value' ); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-18 06:24:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    public  function  test_auth_fails_if_endpoints_start_with_https () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $endpointConfigKeys  =  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.token_endpoint'  =>  'tokenEndpoint' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.authorization_endpoint'  =>  'authorizationEndpoint' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.userinfo_endpoint'  =>  'userinfoEndpoint' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        foreach  ( $endpointConfigKeys  as  $endpointConfigKey  =>  $endpointName )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $logger  =  $this -> withTestLogger (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $original  =  config () -> get ( $endpointConfigKey ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $new  =  str_replace ( 'https://' ,  'http://' ,  $original ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            config () -> set ( $endpointConfigKey ,  $new ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> withoutExceptionHandling (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $err  =  null ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            try  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                $resp  =  $this -> runLogin (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                $resp -> assertRedirect ( '/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }  catch  ( \Exception  $exception )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                $err  =  $exception ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> assertEquals ( " Endpoint value for  \" { $endpointName } \"  must start with https:// " ,  $err -> getMessage ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            config () -> set ( $endpointConfigKey ,  $original ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    public  function  test_auth_login_with_autodiscovery () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> withAutodiscovery (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-08 21:16:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $transactions  =  $this -> mockHttpClient ([ 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            $this -> getAutoDiscoveryResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getJwksResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> runLogin (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertTrue ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-08 21:16:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $discoverRequest  =  $transactions -> requestAt ( 0 ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $keysRequest  =  $transactions -> requestAt ( 1 ); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 'GET' ,  $keysRequest -> getMethod ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 'GET' ,  $discoverRequest -> getMethod ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( OidcJwtHelper :: defaultIssuer ()  .  '/.well-known/openid-configuration' ,  $discoverRequest -> getUri ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( OidcJwtHelper :: defaultIssuer ()  .  '/oidc/keys' ,  $keysRequest -> getUri ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_auth_fails_if_autodiscovery_fails () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> withAutodiscovery (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> mockHttpClient ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            new  Response ( 404 ,  [],  'Not found' ), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-02-24 22:16:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> followRedirects ( $this -> runLogin ()); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-24 22:16:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $resp -> assertSeeText ( 'Login using SingleSignOn-Testing failed, system did not provide successful authorization' ); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_autodiscovery_calls_are_cached () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> withAutodiscovery (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-08 21:16:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $transactions  =  $this -> mockHttpClient ([ 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            $this -> getAutoDiscoveryResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getJwksResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getAutoDiscoveryResponse ([ 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                'issuer'  =>  'https://auto.example.com' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            ]), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getJwksResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Initial run
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> post ( '/oidc/login' ); 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-08 21:16:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 2 ,  $transactions -> requestCount ()); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        // Second run, hits cache
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> post ( '/oidc/login' ); 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-08 21:16:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 2 ,  $transactions -> requestCount ()); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Third run, different issuer, new cache key
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 'oidc.issuer'  =>  'https://auto.example.com' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> post ( '/oidc/login' ); 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-08 21:16:09 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 4 ,  $transactions -> requestCount ()); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-28 22:00:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    public  function  test_auth_login_with_autodiscovery_with_keys_that_do_not_have_alg_property () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> withAutodiscovery (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $keyArray  =  OidcJwtHelper :: publicJwkKeyArray (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        unset ( $keyArray [ 'alg' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> mockHttpClient ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getAutoDiscoveryResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            new  Response ( 200 ,  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'Content-Type'   =>  'application/json' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'Cache-Control'  =>  'no-cache, no-store' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'Pragma'         =>  'no-cache' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ],  json_encode ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'keys'  =>  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    $keyArray , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ], 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ])), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> runLogin (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertTrue ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-23 19:50:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    public  function  test_auth_login_with_autodiscovery_with_keys_that_do_not_have_use_property () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Based on reading the OIDC discovery spec:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // > This contains the signing key(s) the RP uses to validate signatures from the OP. The JWK Set MAY also
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // > contain the Server's encryption key(s), which are used by RPs to encrypt requests to the Server. When
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // > both signing and encryption keys are made available, a use (Key Use) parameter value is REQUIRED for all
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // > keys in the referenced JWK Set to indicate each key's intended usage.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // We can assume that keys without use are intended for signing.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> withAutodiscovery (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $keyArray  =  OidcJwtHelper :: publicJwkKeyArray (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        unset ( $keyArray [ 'use' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> mockHttpClient ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getAutoDiscoveryResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            new  Response ( 200 ,  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'Content-Type'   =>  'application/json' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'Cache-Control'  =>  'no-cache, no-store' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'Pragma'         =>  'no-cache' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ],  json_encode ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'keys'  =>  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    $keyArray , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ], 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ])), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> runLogin (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertTrue ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-27 00:43:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    public  function  test_auth_uses_configured_external_id_claim_option () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.external_id_claim'  =>  'super_awesome_id' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'email'             =>  'benny@example.com' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'sub'               =>  'benny1010101' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'super_awesome_id'  =>  'xXBennyTheGeezXx' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        /** @var User $user */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $user  =  User :: query () -> where ( 'email' ,  '=' ,  'benny@example.com' ) -> first (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 'xXBennyTheGeezXx' ,  $user -> external_auth_id ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 18:50:58 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    public  function  test_auth_uses_mulitple_display_name_claims_if_configured () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 'oidc.display_name_claims'  =>  'first_name|last_name' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> runLogin ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'email'       =>  'benny@example.com' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'sub'         =>  'benny1010101' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'first_name'  =>  'Benny' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'last_name'   =>  'Jenkins' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertDatabaseHas ( 'users' ,  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'name'  =>  'Benny Jenkins' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'email'  =>  'benny@example.com' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-02 23:56:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    public  function  test_login_group_sync () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.user_to_groups'      =>  true , 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-07 00:41:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            'oidc.groups_claim'        =>  'groups' , 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-02 23:56:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'oidc.remove_from_groups'  =>  false , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $roleA  =  Role :: factory () -> create ([ 'display_name'  =>  'Wizards' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $roleB  =  Role :: factory () -> create ([ 'display_name'  =>  'ZooFolks' ,  'external_auth_id'  =>  'zookeepers' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $roleC  =  Role :: factory () -> create ([ 'display_name'  =>  'Another Role' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'email'   =>  'benny@example.com' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'sub'     =>  'benny1010101' , 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-30 00:46:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            'groups'  =>  [ 'Wizards' ,  'Zookeepers' ], 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-02 23:56:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        /** @var User $user */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $user  =  User :: query () -> where ( 'email' ,  '=' ,  'benny@example.com' ) -> first (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertTrue ( $user -> hasRole ( $roleA -> id )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertTrue ( $user -> hasRole ( $roleB -> id )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( $user -> hasRole ( $roleC -> id )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_login_group_sync_with_nested_groups_in_token () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.user_to_groups'      =>  true , 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-07 00:41:32 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'oidc.groups_claim'        =>  'my.custom.groups.attr' , 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-02 23:56:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'oidc.remove_from_groups'  =>  false , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $roleA  =  Role :: factory () -> create ([ 'display_name'  =>  'Wizards' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'email'   =>  'benny@example.com' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'sub'     =>  'benny1010101' , 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-30 00:46:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'my'      =>  [ 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-02 23:56:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                'custom'  =>  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    'groups'  =>  [ 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-30 00:46:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                        'attr'  =>  [ 'Wizards' ], 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    ], 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ], 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ], 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-02 23:56:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        /** @var User $user */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $user  =  User :: query () -> where ( 'email' ,  '=' ,  'benny@example.com' ) -> first (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertTrue ( $user -> hasRole ( $roleA -> id )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 00:41:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    public  function  test_oidc_logout_form_active_when_oidc_active () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> runLogin (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> get ( '/' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> withHtml ( $resp ) -> assertElementExists ( 'header form[action$="/oidc/logout"] button' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-08 01:45:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    public  function  test_logout_with_autodiscovery_with_oidc_logout_enabled () 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 00:41:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-08 01:45:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 'oidc.end_session_endpoint'  =>  true ]); 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 00:41:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> withAutodiscovery (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $transactions  =  $this -> mockHttpClient ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getAutoDiscoveryResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getJwksResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> asEditor () -> post ( '/oidc/logout' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( 'https://auth.example.com/oidc/logout?post_logout_redirect_uri='  .  urlencode ( url ( '/' ))); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 2 ,  $transactions -> requestCount ()); 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-08 01:45:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 00:41:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-08 01:45:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    public  function  test_logout_with_autodiscovery_with_oidc_logout_disabled () 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 00:41:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> withAutodiscovery (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 'oidc.end_session_endpoint'  =>  false ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> mockHttpClient ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getAutoDiscoveryResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getJwksResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> asEditor () -> post ( '/oidc/logout' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/' ); 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-08 01:45:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 00:41:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_logout_without_autodiscovery_but_with_endpoint_configured () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 'oidc.end_session_endpoint'  =>  'https://example.com/logout' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> asEditor () -> post ( '/oidc/logout' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( 'https://example.com/logout?post_logout_redirect_uri='  .  urlencode ( url ( '/' ))); 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-08 01:45:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_logout_without_autodiscovery_with_configured_endpoint_adds_to_query_if_existing () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 'oidc.end_session_endpoint'  =>  'https://example.com/logout?a=b' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> asEditor () -> post ( '/oidc/logout' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( 'https://example.com/logout?a=b&post_logout_redirect_uri='  .  urlencode ( url ( '/' ))); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 00:41:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_logout_with_autodiscovery_and_auto_initiate_returns_to_auto_prevented_login () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> withAutodiscovery (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'auth.auto_initiate'  =>  true , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'services.google.client_id'  =>  false , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'services.github.client_id'  =>  false , 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-08 01:45:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'oidc.end_session_endpoint'  =>  true , 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 00:41:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> mockHttpClient ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getAutoDiscoveryResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getJwksResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> asEditor () -> post ( '/oidc/logout' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $redirectUrl  =  url ( '/login?prevent_auto_init=true' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( 'https://auth.example.com/oidc/logout?post_logout_redirect_uri='  .  urlencode ( $redirectUrl )); 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-08 01:45:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_logout_endpoint_url_overrides_autodiscovery_endpoint () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 'oidc.end_session_endpoint'  =>  'https://a.example.com' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> withAutodiscovery (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $transactions  =  $this -> mockHttpClient ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getAutoDiscoveryResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getJwksResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> asEditor () -> post ( '/oidc/logout' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( 'https://a.example.com?post_logout_redirect_uri='  .  urlencode ( url ( '/' ))); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 2 ,  $transactions -> requestCount ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_logout_with_autodiscovery_does_not_use_rp_logout_if_no_url_via_autodiscovery () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 'oidc.end_session_endpoint'  =>  true ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> withAutodiscovery (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> mockHttpClient ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getAutoDiscoveryResponse ([ 'end_session_endpoint'  =>  null ]), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getJwksResponse (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> asEditor () -> post ( '/oidc/logout' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertFalse ( auth () -> check ()); 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 00:41:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_logout_redirect_contains_id_token_hint_if_existing () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 'oidc.end_session_endpoint'  =>  'https://example.com/logout' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-12 20:08:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        // Fix times so our token is predictable
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $claimOverrides  =  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'iat'  =>  time (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'exp'  =>  time ()  +  720 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'auth_time'  =>  time () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> runLogin ( $claimOverrides ); 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 00:41:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> asEditor () -> post ( '/oidc/logout' ); 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-12 20:08:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $query  =  'id_token_hint='  .  urlencode ( OidcJwtHelper :: idToken ( $claimOverrides ))  .   '&post_logout_redirect_uri='  .  urlencode ( url ( '/' )); 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 00:41:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( 'https://example.com/logout?'  .  $query ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-28 06:40:14 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    public  function  test_oidc_id_token_pre_validate_theme_event_without_return () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $args  =  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $callback  =  function  ( ... $eventArgs )  use  ( & $args )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $args  =  $eventArgs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Theme :: listen ( ThemeEvents :: OIDC_ID_TOKEN_PRE_VALIDATE ,  $callback ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'email'  =>  'benny@example.com' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'sub'    =>  'benny1010101' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'name'   =>  'Benny' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertDatabaseHas ( 'users' ,  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'external_auth_id'  =>  'benny1010101' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertArrayHasKey ( 'iss' ,  $args [ 0 ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertArrayHasKey ( 'sub' ,  $args [ 0 ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 'Benny' ,  $args [ 0 ][ 'name' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 'benny1010101' ,  $args [ 0 ][ 'sub' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertArrayHasKey ( 'access_token' ,  $args [ 1 ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertArrayHasKey ( 'expires_in' ,  $args [ 1 ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertArrayHasKey ( 'refresh_token' ,  $args [ 1 ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_oidc_id_token_pre_validate_theme_event_with_return () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $callback  =  function  ( ... $eventArgs )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  array_merge ( $eventArgs [ 0 ],  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'email'  =>  'lenny@example.com' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'sub'  =>  'lenny1010101' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'name'  =>  'Lenny' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Theme :: listen ( ThemeEvents :: OIDC_ID_TOKEN_PRE_VALIDATE ,  $callback ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'email'  =>  'benny@example.com' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'sub'    =>  'benny1010101' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'name'   =>  'Benny' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertDatabaseHas ( 'users' ,  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'email'  =>  'lenny@example.com' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'external_auth_id'  =>  'lenny1010101' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'name'  =>  'Lenny' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-28 00:41:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    public  function  test_pkce_used_on_authorize_and_access () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Start auth
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> post ( '/oidc/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $state  =  session () -> get ( 'oidc_state' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $pkceCode  =  session () -> get ( 'oidc_pkce_code' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertGreaterThan ( 30 ,  strlen ( $pkceCode )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $expectedCodeChallenge  =  trim ( strtr ( base64_encode ( hash ( 'sha256' ,  $pkceCode ,  true )),  '+/' ,  '-_' ),  '=' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $redirect  =  $resp -> headers -> get ( 'Location' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $redirectParams  =  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        parse_str ( parse_url ( $redirect ,  PHP_URL_QUERY ),  $redirectParams ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( $expectedCodeChallenge ,  $redirectParams [ 'code_challenge' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 'S256' ,  $redirectParams [ 'code_challenge_method' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $transactions  =  $this -> mockHttpClient ([ $this -> getMockAuthorizationResponse ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'email'  =>  'benny@example.com' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'sub'    =>  'benny1010101' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ])]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> get ( '/oidc/callback?code=SplxlOBeZQQYbYS6WxSbIA&state='  .  $state ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $tokenRequest  =  $transactions -> latestRequest (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $bodyParams  =  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        parse_str ( $tokenRequest -> getBody (),  $bodyParams ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( $pkceCode ,  $bodyParams [ 'code_verifier' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-18 06:24:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    public  function  test_userinfo_endpoint_used_if_missing_claims_in_id_token () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ( 'oidc.display_name_claims' ,  'first_name|last_name' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> post ( '/oidc/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $state  =  session () -> get ( 'oidc_state' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $client  =  $this -> mockHttpClient ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $this -> getMockAuthorizationResponse ([ 'name'  =>  null ]), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            new  Response ( 200 ,  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'Content-Type'   =>  'application/json' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ],  json_encode ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'sub'  =>  OidcJwtHelper :: defaultPayload ()[ 'sub' ], 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'first_name'  =>  'Barry' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'last_name'  =>  'Userinfo' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ])) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> get ( '/oidc/callback?code=SplxlOBeZQQYbYS6WxSbIA&state='  .  $state ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 2 ,  $client -> requestCount ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoRequest  =  $client -> requestAt ( 1 ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 'GET' ,  $userinfoRequest -> getMethod ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 'https://oidc.local/userinfo' ,  ( string )  $userinfoRequest -> getUri ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 'Barry Userinfo' ,  user () -> name ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_userinfo_endpoint_fetch_with_different_sub_throws_error () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponseData  =  [ 'sub'  =>  'dcba4321' ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponse  =  new  Response ( 200 ,  [ 'Content-Type'   =>  'application/json' ],  json_encode ( $userinfoResponseData )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 'name'  =>  null ],  [ $userinfoResponse ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertSessionError ( 'Userinfo endpoint response validation failed with error: Subject value provided in the userinfo endpoint does not match the provided ID token value' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_userinfo_endpoint_fetch_returning_no_sub_throws_error () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponseData  =  [ 'name'  =>  'testing' ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponse  =  new  Response ( 200 ,  [ 'Content-Type'   =>  'application/json' ],  json_encode ( $userinfoResponseData )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 'name'  =>  null ],  [ $userinfoResponse ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertSessionError ( 'Userinfo endpoint response validation failed with error: No valid subject value found in userinfo data' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_userinfo_endpoint_fetch_can_parsed_nested_groups () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.user_to_groups'      =>  true , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.groups_claim'        =>  'my.nested.groups.attr' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.remove_from_groups'  =>  false , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $roleA  =  Role :: factory () -> create ([ 'display_name'  =>  'Ducks' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponseData  =  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'sub'  =>  OidcJwtHelper :: defaultPayload ()[ 'sub' ], 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'my'  =>  [ 'nested'  =>  [ 'groups'  =>  [ 'attr'  =>  [ 'Ducks' ,  'Donkeys' ]]]] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponse  =  new  Response ( 200 ,  [ 'Content-Type'   =>  'application/json' ],  json_encode ( $userinfoResponseData )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 'groups'  =>  null ],  [ $userinfoResponse ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $user  =  User :: where ( 'email' ,  OidcJwtHelper :: defaultPayload ()[ 'email' ]) -> first (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertTrue ( $user -> hasRole ( $roleA -> id )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 00:58:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    public  function  test_userinfo_endpoint_response_with_complex_json_content_type_handled () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponseData  =  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'sub'  =>  OidcJwtHelper :: defaultPayload ()[ 'sub' ], 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'name'  =>  'Barry' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponse  =  new  Response ( 200 ,  [ 'Content-Type'   =>  'Application/Json ; charset=utf-8' ],  json_encode ( $userinfoResponseData )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 'name'  =>  null ],  [ $userinfoResponse ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $user  =  User :: where ( 'email' ,  OidcJwtHelper :: defaultPayload ()[ 'email' ]) -> first (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 'Barry' ,  $user -> name ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-19 22:05:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    public  function  test_userinfo_endpoint_jwks_response_handled () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponseData  =  OidcJwtHelper :: idToken ([ 'name'  =>  'Barry Jwks' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponse  =  new  Response ( 200 ,  [ 'Content-Type'   =>  'application/jwt' ],  $userinfoResponseData ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 'name'  =>  null ],  [ $userinfoResponse ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $user  =  User :: where ( 'email' ,  OidcJwtHelper :: defaultPayload ()[ 'email' ]) -> first (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 'Barry Jwks' ,  $user -> name ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_userinfo_endpoint_jwks_response_returning_no_sub_throws () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponseData  =  OidcJwtHelper :: idToken ([ 'sub'  =>  null ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponse  =  new  Response ( 200 ,  [ 'Content-Type'   =>  'application/jwt' ],  $userinfoResponseData ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 'name'  =>  null ],  [ $userinfoResponse ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertSessionError ( 'Userinfo endpoint response validation failed with error: No valid subject value found in userinfo data' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_userinfo_endpoint_jwks_response_returning_non_matching_sub_throws () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponseData  =  OidcJwtHelper :: idToken ([ 'sub'  =>  'zzz123' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponse  =  new  Response ( 200 ,  [ 'Content-Type'   =>  'application/jwt' ],  $userinfoResponseData ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 'name'  =>  null ],  [ $userinfoResponse ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertSessionError ( 'Userinfo endpoint response validation failed with error: Subject value provided in the userinfo endpoint does not match the provided ID token value' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_userinfo_endpoint_jwks_response_with_invalid_signature_throws () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponseData  =  OidcJwtHelper :: idToken (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $exploded  =  explode ( '.' ,  $userinfoResponseData ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $exploded [ 2 ]  =  base64_encode ( base64_decode ( $exploded [ 2 ])  .  'ABC' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponse  =  new  Response ( 200 ,  [ 'Content-Type'   =>  'application/jwt' ],  implode ( '.' ,  $exploded )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 'name'  =>  null ],  [ $userinfoResponse ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertSessionError ( 'Userinfo endpoint response validation failed with error: Token signature could not be validated using the provided keys' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_userinfo_endpoint_jwks_response_with_invalid_signature_alg_throws () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponseData  =  OidcJwtHelper :: idToken ([],  [ 'alg'  =>  'ZZ512' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponse  =  new  Response ( 200 ,  [ 'Content-Type'   =>  'application/jwt' ],  $userinfoResponseData ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 'name'  =>  null ],  [ $userinfoResponse ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertSessionError ( 'Userinfo endpoint response validation failed with error: Only RS256 signature validation is supported. Token reports using ZZ512' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  function  test_userinfo_endpoint_response_with_invalid_content_type_throws () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $userinfoResponse  =  new  Response ( 200 ,  [ 'Content-Type'   =>  'application/beans' ],  json_encode ( OidcJwtHelper :: defaultPayload ())); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> runLogin ([ 'name'  =>  null ],  [ $userinfoResponse ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertSessionError ( 'Userinfo endpoint response validation failed with error: No valid subject value found in userinfo data' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-14 21:21:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    public  function  test_userinfo_endpoint_not_called_if_empty_groups_array_provided_in_id_token () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.user_to_groups'      =>  true , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.groups_claim'        =>  'groups' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.remove_from_groups'  =>  false , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> post ( '/oidc/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $state  =  session () -> get ( 'oidc_state' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $client  =  $this -> mockHttpClient ([ $this -> getMockAuthorizationResponse ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'groups'  =>  [], 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ])]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp  =  $this -> get ( '/oidc/callback?code=SplxlOBeZQQYbYS6WxSbIA&state='  .  $state ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $resp -> assertRedirect ( '/' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertEquals ( 1 ,  $client -> requestCount ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> assertTrue ( auth () -> check ()); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-18 06:24:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    protected  function  withAutodiscovery () :  void 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        config () -> set ([ 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'oidc.issuer'                  =>  OidcJwtHelper :: defaultIssuer (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'oidc.discover'                =>  true , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'oidc.authorization_endpoint'  =>  null , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'oidc.token_endpoint'          =>  null , 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-18 06:24:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'oidc.userinfo_endpoint'       =>  null , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'oidc.jwt_public_key'          =>  null , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-18 06:24:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    protected  function  runLogin ( $claimOverrides  =  [],  $additionalHttpResponses  =  []) :  TestResponse 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $this -> post ( '/oidc/login' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $state  =  session () -> get ( 'oidc_state' ); 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-18 06:24:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        $this -> mockHttpClient ([ $this -> getMockAuthorizationResponse ( $claimOverrides ),  ... $additionalHttpResponses ]); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-18 06:24:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        return  $this -> get ( '/oidc/callback?code=SplxlOBeZQQYbYS6WxSbIA&state='  .  $state ); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    protected  function  getAutoDiscoveryResponse ( $responseOverrides  =  []) :  Response 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  new  Response ( 200 ,  [ 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'Content-Type'   =>  'application/json' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'Cache-Control'  =>  'no-cache, no-store' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'Pragma'         =>  'no-cache' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ],  json_encode ( array_merge ([ 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'token_endpoint'          =>  OidcJwtHelper :: defaultIssuer ()  .  '/oidc/token' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'authorization_endpoint'  =>  OidcJwtHelper :: defaultIssuer ()  .  '/oidc/authorize' , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Oidc: Properly query the UserInfo Endpoint
BooksStack's OIDC Client requests the 'profile' and 'email' scope values
in order to have access to the 'name', 'email', and other claims.  It
looks for these claims in the ID Token that is returned along with the
Access Token.
However, the OIDC-core specification section 5.4 [1] only requires that
the Provider include those claims in the ID Token *if* an Access Token is
not also issued.  If an Access Token is issued, the Provider can leave out
those claims from the ID Token, and the Client is supposed to obtain them
by submitting the Access Token to the UserInfo Endpoint.
So I suppose it's just good luck that the OIDC Providers that BookStack
has been tested with just so happen to also stick those claims in the ID
Token even though they don't have to.  But others (in particular:
https://login.infomaniak.com) don't do so, and require fetching the
UserInfo Endpoint.)
A workaround is currently possible by having the user write a theme with a
ThemeEvents::OIDC_ID_TOKEN_PRE_VALIDATE hook that fetches the UserInfo
Endpoint.  This workaround isn't great, for a few reasons:
 1. Asking the user to implement core parts of the OIDC protocol is silly.
 2. The user either needs to re-fetch the .well-known/openid-configuration
    file to discover the endpoint (adding yet another round-trip to each
    login) or hard-code the endpoint, which is fragile.
 3. The hook doesn't receive the HTTP client configuration.
So, have BookStack's OidcService fetch the UserInfo Endpoint and inject
those claims into the ID Token, if a UserInfo Endpoint is defined.
Two points about this:
 - Injecting them into the ID Token's claims is the most obvious approach
   given the current code structure; though I'm not sure it is the best
   approach, perhaps it should instead fetch the user info in
   processAuthorizationResponse() and pass that as an argument to
   processAccessTokenCallback() which would then need a bit of
   restructuring.  But this made sense because it's also how the
   ThemeEvents::OIDC_ID_TOKEN_PRE_VALIDATE hook works.
 - OIDC *requires* that a UserInfo Endpoint exists, so why bother with
   that "if a UserInfo Endpoint is defined" bit?  Simply out of an
   abundance of caution that there's an existing BookStack user that is
   relying on it not fetching the UserInfo Endpoint in order to work with
   a non-compliant OIDC Provider.
[1]: https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims
											 
										 
										
											2023-12-16 01:58:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            'userinfo_endpoint'       =>  OidcJwtHelper :: defaultIssuer ()  .  '/oidc/userinfo' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'jwks_uri'                =>  OidcJwtHelper :: defaultIssuer ()  .  '/oidc/keys' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'issuer'                  =>  OidcJwtHelper :: defaultIssuer (), 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-07 00:41:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'end_session_endpoint'    =>  OidcJwtHelper :: defaultIssuer ()  .  '/oidc/logout' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ],  $responseOverrides ))); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    protected  function  getJwksResponse () :  Response 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  new  Response ( 200 ,  [ 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'Content-Type'   =>  'application/json' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'Cache-Control'  =>  'no-cache, no-store' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'Pragma'         =>  'no-cache' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ],  json_encode ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'keys'  =>  [ 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                OidcJwtHelper :: publicJwkKeyArray (), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ], 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ])); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    protected  function  getMockAuthorizationResponse ( $claimOverrides  =  []) :  Response 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  new  Response ( 200 ,  [ 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'Content-Type'   =>  'application/json' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'Cache-Control'  =>  'no-cache, no-store' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'Pragma'         =>  'no-cache' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ],  json_encode ([ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'access_token'  =>  'abc123' , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 23:01:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            'token_type'    =>  'Bearer' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'expires_in'    =>  3600 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            'id_token'      =>  OidcJwtHelper :: idToken ( $claimOverrides ), 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-13 23:51:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ])); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}