AppAuth-iOS icon indicating copy to clipboard operation
AppAuth-iOS copied to clipboard

Logout function not working on iOS > 14

Open luca8846 opened this issue 2 years ago • 11 comments

Hello, I'm experiencing an issue on iOS > 14. The logout function "OIDEndSessionRequest" isn't working correctly and I can't complete the logout procedure.

This is my code:

let config = OIDServiceConfiguration(authorizationEndpoint: URL(string: AUTHORIZATION_ENDPOINT)!, tokenEndpoint: URL(string: TOKEN_ENDPOINT)!, issuer: URL(string: ISSUER)!, registrationEndpoint: URL(string: REGISTRATION_ENDPOINT)!, endSessionEndpoint: URL(string: END_SESSION_ENDPOINT)!)

let logoutRequest = OIDEndSessionRequest(configuration: config, idTokenHint: (authState?.lastTokenResponse?.refreshToken)!, postLogoutRedirectURL: URL(string: "REDIRECT_URI")!, state: (authState?.lastAuthorizationResponse.state)!, additionalParameters: nil)

let storyboard = UIStoryboard(name: "Main", bundle: nil) let vc = storyboard.instantiateViewController(withIdentifier: "myView") as! MyViewController

let userAgent = OIDExternalUserAgentIOS(presenting: vc)

OIDAuthorizationService.present(logoutRequest, externalUserAgent: userAgent!, callback: { (authorizationState, error) in })

The error code received is: "Error Domain=org.openid.appauth.general Code=-3"

Can you help me please?

Thanks in advance

luca8846 avatar Sep 02 '21 12:09 luca8846

I am using a similar code, the difference being that I'm passing the idToken to the OIDEndSessionRequest instead of the refreshToken. The out come is still not the desired one - the server logs me out however the authentication sheet is not closed and I do not get any kind of callback.

Does anyone have any idea why this is so?

lehelmedves avatar Oct 19 '21 08:10 lehelmedves

As a workaround, you can use a "RP-Initiated Logout" instead. This is a get request to the end session endpoint and ID token as query param. This will also logout and end the session without showing the authentication sheet

Kerstin2020 avatar Nov 17 '21 09:11 Kerstin2020

Indeed, but my main problem with this is, that this way the cookie will not be erased and upon the next login this will be seen by the user.

lehelmedves avatar Nov 17 '21 09:11 lehelmedves

We are in a similar predicament as the OP. We call the the OIDEndSessionRequest the same way but here is what happens after that.

We are presented with an alert that's named Sign-in. We saw that others had this issue and that there's no way to correct that outside of AppAuth. So we are not too concerned about this and tap the Continue button.

We are then presented with a logout page where we are asked to tap the Sign out button. Tapping the button updates the page now displaying You are now signed out. Here's the problem: The page is never dismissed and the session callback is never called. Only by tapping the Cancel button at the top of the screen will we get the error: Error Domain=org.openid.appauth.general Code=-3 "(null)" UserInfo={NSUnderlyingError=0x600000438450 {Error Domain=com.apple.AuthenticationServices.WebAuthenticationSession Code=1 "(null)"}}

Any help would be greatly appreciated!

EggYoke avatar Nov 19 '21 17:11 EggYoke

@EggYoke this seems to be a redirect URI issue, it needs to be specified on the identity server and the same needs to be used when you perform the end session request.

lehelmedves avatar Nov 22 '21 06:11 lehelmedves

Hello All, I am facing an annoying issue while trying to logout from the AppAuth/OpenId session in iOS.

1 - On click of logout button the alert is appearing and dismissing immediately 2 - No error code appearing in console now (earlier i was getting same error as of @EggYoke but I corrected that after putting the registration URL as ${MybaseURL}/v1/clients) 3 - But my problem is when I am logging in again, the login UI is not presented to user (not even getting any callback response from presentEndSessionRequest method), rather the previous user's session is coming back (Seems not logging out earlier user)

Can anyone put some light, how to fix this.. (I researched a lot but no luck)

Here is my Logout Code

NSString *kClientID = @"**********";
	NSURL *kRedirectURI = [NSURL URLWithString:@"*******"]; //Login Redirect URI
	NSURL *authorizationEndpoint = [NSURL URLWithString:@"*************/v1/authorize"];
	NSURL *tokenEndpoint = [NSURL URLWithString:@"***************/v1/token"];
	
	NSURL *urlIssuer = [NSURL URLWithString:@"****************"];
	NSURL *urlRegistration = [NSURL URLWithString:@"*****************/v1/clients"];
	NSURL *urlSessionEndPoint = [NSURL URLWithString:@"*******************/v1/logout"]; //Logout Redirect URI

	configuration = [[OIDServiceConfiguration alloc] initWithAuthorizationEndpoint:authorizationEndpoint tokenEndpoint:tokenEndpoint issuer:urlIssuer registrationEndpoint:urlRegistration endSessionEndpoint:urlSessionEndPoint];
	
	
	NSURL *logoutURL = [NSURL URLWithString:@"***********"];
	NSDictionary *additionalParam = nil;
	
	OIDEndSessionRequest *endSessionRequest = [[OIDEndSessionRequest alloc] initWithConfiguration:configuration idTokenHint:self.authState.lastTokenResponse.refreshToken postLogoutRedirectURL:logoutURL additionalParameters:additionalParam];
	
	OIDExternalUserAgentIOS *iOSExternalAgent = [[OIDExternalUserAgentIOS alloc] initWithPresentingViewController:self];
	
	[OIDAuthorizationService presentEndSessionRequest:endSessionRequest externalUserAgent:iOSExternalAgent callback:^(OIDEndSessionResponse * _Nullable endSessionResponse, NSError * _Nullable error) {
		
		if (endSessionResponse) {
			 
			for (NSHTTPCookie *cookie in [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies) {
				[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
			}
		} else {
			MPLogs(@"Error: %@", error.description);

		}
	}];

janmenjayarout avatar Nov 28 '21 08:11 janmenjayarout

@EggYoke was there any work around to fix the logout issue?

Itsprobme avatar Dec 23 '21 10:12 Itsprobme

@WilliamDenniss is there any workaround for this?

Itsprobme avatar Dec 23 '21 10:12 Itsprobme

We have a solution for our issue. We figured out that the OIDEndSessionRequest's idTokenHint parameter needs the idToken and not a refreshToken.

EggYoke avatar Jan 04 '22 14:01 EggYoke

@EggYoke how did you get the idToken?

Itsprobme avatar Jan 04 '22 15:01 Itsprobme

Hi @EggYoke, did that help to resolve the problem "alert that's named Sign-in" ?

vuta1927 avatar Jan 11 '22 10:01 vuta1927

@EggYoke How did you manage to close the browser window when you sign out? Becuase i have same issue and i double checked that i passed idToken in IdTokenHint, but it the browser window still remains open.

softsan avatar Dec 08 '22 21:12 softsan

@softsan Did you solve this issue?

tiwari1amrit avatar Apr 18 '23 04:04 tiwari1amrit

Any updates on this?

Zachthac avatar Jul 31 '23 23:07 Zachthac

@Zachthac I found a solution, please have a look.

    private var externalUserAlertSession: OIDExternalUserAgentSession!

    public func logout(onSuccess: (() -> Void)? = nil) {

        guard let userDetailData = UserDefaults.hydraUserDetail else {
            return
        }

        let inksAuthLoginModel = InksAuthLoginModel.fromDictionary(userDetailData)

        let logoutEndpointString = Urls.Hydra.logout() + "/?redirect_uri=" + Urls.Hydra.redirectCallbackURL()

        let logoutEndpoint = URL(string: logoutEndpointString)!

        let configuration = OIDServiceConfiguration(
            authorizationEndpoint: authEndpoint,
            tokenEndpoint: tokenEndpoint,
            issuer: nil,
            registrationEndpoint: nil,
            endSessionEndpoint: logoutEndpoint)

        guard let idToken = inksAuthLoginModel.idToken else {
            return
        }

        let endSessionRequest = OIDEndSessionRequest(
            configuration: configuration,
            idTokenHint: idToken,
            postLogoutRedirectURL: redirectURL,
            state: inksAuthLoginModel.state ?? "",
            additionalParameters: nil)

        let agent = OIDExternalUserAgentIOS(presenting: viewController)

        self.externalUserAlertSession = OIDAuthorizationService.present(
            endSessionRequest,
            externalUserAgent: agent!) {[weak self] response, error in
                guard let `self` = self else { return }

                if let error = error {
                    print("Authorization error: \(error.localizedDescription)")
                    return
                }

                guard let response = response else {
                    print("Authorization response is nil.")
                    return
                }

                print("Authorization response: \(response)")

                HTTPCookieStorage.shared.cookies?.forEach { cookie in
                    HTTPCookieStorage.shared.deleteCookie(cookie)
                }

                UserDefaults.standard.flushAllSaveData()

                onSuccess?()
            }
    }

tiwari1amrit avatar Aug 01 '23 01:08 tiwari1amrit

I'm closing this to de-clutter our issue backlog since this doesn't appear to be a bug.

mdmathias avatar Aug 17 '23 21:08 mdmathias