Open guturiganesh opened 6 years ago
Logout support is still experimental and not included in our mainline releases. You can try out the feature from the dev-logout branch.
Thanks for the update @WilliamDenniss Which functions I should call for Logout after taking dev-logout branch? any code snippet please. Also Can we use this branch for production app?
Any update on this? How can we perform logout with AppAuth?
Hello, any chances to see this in master? @guturiganesh if you still need an answer: appDelegate.currentAuthorizationFlow = OIDAuthorizationService.present(request, externalUserAgent: agent, callback: { (response, error) in // handle response in case of success, remember to clear cookies
HTTPCookieStorage.shared.cookies?.forEach{ cookie in HTTPCookieStorage.shared.deleteCookie(cookie) } } where request is built using OIDEndSessionRequest(configuration: configuration, idTokenHint: idToken, postLogoutRedirectURL: redirectIRL, additionalParameters: [kLogOutID : kClientID]) and agent = OIDExternalUserAgentIOS(presenting: yourViewController)
idToken can be found on authState.
Thanks for the update @WilliamDenniss Which functions I should call for Logout after taking dev-logout branch? any code snippet please. Also Can we use this branch for production app?
have you successfully logout .
Thanks for the update @WilliamDenniss Which functions I should call for Logout after taking dev-logout branch? any code snippet please. Also Can we use this branch for production app?
have you successfully logout .
Yes it works.
Thanks for the update @WilliamDenniss Which functions I should call for Logout after taking dev-logout branch? any code snippet please. Also Can we use this branch for production app?
have you successfully logout .
Yes it works.
which function have you call?
Here's what I did:
Func logout (presenter: UIViewController) {
guard let authState = self.authState else {
return
}
guard let idToken = authState.lastTokenResponse?.idToken else {
return
}
let request = OIDEndSessionRequest(configuration: authState.lastAuthorizationResponse.request.configuration,
idTokenHint: idToken,
postLogoutRedirectURL: Constants.RedirectURI,
additionalParameters: nil)
guard let agent = OIDExternalUserAgentIOS(presenting: presenter) else {
return
}
self.currentAuthorizationFlow = OIDAuthorizationService.present(request, externalUserAgent: agent,
callback: { (response, error) in
if let response = response {
//delete cookies just in case
HTTPCookieStorage.shared.cookies?.forEach { cookie in
HTTPCookieStorage.shared.deleteCookie(cookie)
}
// successfully logout
}
if let err = error {
// print Error
}
})
}
}
Remember that you need to pass a viewcontroller (presenter) to handle the pop up (and of course your backend has to handle the logout request)
Here's what I did:
Func logout (presenter: UIViewController) { guard let authState = self.authState else { return } guard let idToken = authState.lastTokenResponse?.idToken else { return } let request = OIDEndSessionRequest(configuration: authState.lastAuthorizationResponse.request.configuration, idTokenHint: idToken, postLogoutRedirectURL: Constants.RedirectURI, additionalParameters: nil) guard let agent = OIDExternalUserAgentIOS(presenting: presenter) else { return } self.currentAuthorizationFlow = OIDAuthorizationService.present(request, externalUserAgent: agent, callback: { (response, error) in if let response = response { //delete cookies just in case HTTPCookieStorage.shared.cookies?.forEach { cookie in HTTPCookieStorage.shared.deleteCookie(cookie) } // successfully logout } if let err = error { // print Error } }) } }
Remember that you need to pass a viewcontroller (presenter) to handle the pop up (and of course your backend has to handle the logout request)
Thanks BlueCourso
But When i was delete the app and reinstall again then click on sign in the SDK give me pervious user (Google sign in). Please help me why pervious user come.
The log out operation is server side... you still have to delete your authstate from your app (if you save it somewhere). If your backend is doing its job, the access token is no longer valid once you log out.
The log out operation is server side... you still have to delete your authstate from your app (if you save it somewhere). If your backend is doing its job, the access token is no longer valid once you log out.
I have delete this but why same user return when delete this app.
The log out operation is server side... you still have to delete your authstate from your app (if you save it somewhere). If your backend is doing its job, the access token is no longer valid once you log out.
I have delete this but why same user return when delete this app.
May be some cookies issue in iOS.
The log out operation is server side... you still have to delete your authstate from your app (if you save it somewhere). If your backend is doing its job, the access token is no longer valid once you log out.
I have delete this but why same user return when delete this app.
May be some cookies issue in iOS.
OIDEndSessionRequest is not available in pod file.
are pulling the correct branch? (dev-logout)
are pulling the correct branch? (dev-logout)
I have add sdk via pod
I use carthage but using pod you should have something like this in your podfile pod 'appAuth', :git => 'https://github.com/openid/AppAuth-iOS.git', :branch => 'dev-logout'
I use carthage but using pod you should have something like this in your podfile pod 'appAuth', :git => 'https://github.com/openid/AppAuth-iOS.git', :branch => 'dev-logout'
I have pull dev-logout and add logout function but it show sign in pop message.
Logout support is still experimental and not included in our mainline releases. You can try out the feature from the dev-logout branch.
when release proper logout feature in sdk
I use carthage but using pod you should have something like this in your podfile pod 'appAuth', :git => 'https://github.com/openid/AppAuth-iOS.git', :branch => 'dev-logout'
I have pull dev-logout and add logout function but it show sign in pop message. Are you getting same sign in popup message when call logout function ?
Yeah I get the annoying log in pop up for log out too. I hope they fix it soon.
Hello. When you release this feature?
Hi all if you are looking to do this with Okta we actually have a newer sdk. It supports logout as well and is a wrapper around appauth. https://github.com/okta/okta-oidc-ios
Yeah I get the annoying log in pop up for log out too. I hope they fix it soon.
Even I am getting Sign In on logout alert popup, do anyone have solutions please. Any other alternative way to do this ? Please help. thanks in advance
Hey, Have anyone solved the logout problem?
@arshadsk5 @BlueCorso Were you able to fix the issue? I'am also getting the login popup on logout.
@arshadsk5 @BlueCorso Were you able to fix the issue? I'am also getting the login popup on logout.
I am sorry, we migrated to active directory so I can't tell whether they fixed it or not :(
@gastonborba here is my logout function and it works perfectly fine. Another thing I needed to do was make sure I add PostLogoutRedirectURI
in our Identity Server DB. If we don't do that, the server logs out, but user agent goes back to login page. After adding the post logout URI in DB, user agent automatically closes after logout completes.
func logout() {
OIDAuthorizationService.discoverConfiguration(forIssuer: AppSettings.issuer) { configuration, error in
guard let presentingViewController = self.presentingViewController else { return }
guard let configuration = configuration else {
fatalError("Error retrieving discovery document: \(error?.localizedDescription ?? "Unknown error")")
}
guard let idToken = self.authState?.lastTokenResponse?.idToken else { return }
let request = OIDEndSessionRequest(configuration: configuration,
idTokenHint: idToken,
postLogoutRedirectURL: AppSettings.redirectUrl,
additionalParameters: nil)
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
guard let userAgent = OIDExternalUserAgentIOS(presenting: presentingViewController) else { return }
appDelegate.currentAuthorizationFlow =
OIDAuthorizationService.present(request,
externalUserAgent: userAgent,
callback: { [weak self] (_, _) in
guard let self = self else { return }
self.setAuthState(nil)
})
}
}
Hey, Have anyone solved the logout problem?
@nagasivaram-tadepalli I have shared my answer above which works properly.
Here's what I did:
Func logout (presenter: UIViewController) { guard let authState = self.authState else { return } guard let idToken = authState.lastTokenResponse?.idToken else { return } let request = OIDEndSessionRequest(configuration: authState.lastAuthorizationResponse.request.configuration, idTokenHint: idToken, postLogoutRedirectURL: Constants.RedirectURI, additionalParameters: nil) guard let agent = OIDExternalUserAgentIOS(presenting: presenter) else { return } self.currentAuthorizationFlow = OIDAuthorizationService.present(request, externalUserAgent: agent, callback: { (response, error) in if let response = response { //delete cookies just in case HTTPCookieStorage.shared.cookies?.forEach { cookie in HTTPCookieStorage.shared.deleteCookie(cookie) } // successfully logout } if let err = error { // print Error } }) } }
Remember that you need to pass a viewcontroller (presenter) to handle the pop up (and of course your backend has to handle the logout request)
My problem is that the agent (SFSafariViewController) show up and disappear quickly and the agent not stay. Any idea? Thanks.
@sethi-ishmeet I greatly appreciate your code example. But there are two parts of your answer that I don't understand, and have not been able to figure out for myself.
Another thing I needed to do was make sure I add
PostLogoutRedirectURI
in our Identity Server DB. If we don't do that, the server logs out, but user agent goes back to login page. After adding the post logout URI in DB, user agent automatically closes after logout completes.
Can you explain exactly what URI you added to your DB for the PostLogoutRedirectURI
?
let request = OIDEndSessionRequest(configuration: configuration,
idTokenHint: idToken,
postLogoutRedirectURL: AppSettings.redirectUrl,
additionalParameters: nil)
What value did you use for AppSettings.redirectUrl
?
Thanks for the further info!
@dgoldman-pdx
Both the redirectURI and PostLogoutRedirectURI are same as following. It's been a couple years since I worked on this app so I vaguely remember any details. Let me know if I can help in any other way.
AppSettings.redirectURI
= URL(string: "<<bundle ID>>:/oauthredirect")!
@sethi-ishmeet thanks for the quick response!
Unfortunately, I'm still seeing the same thing as other posters, where the user agent reopens after logout, as if to attempt a new login. I'll post again here if I find a good solution/workaround. (Note: it appears that Okta has a workaround or two, but they're not trivial nor ideal.)
@dgoldman-pdx can you share your code? It might help investigate it.
@sethi-ishmeet my code is very similar to yours, above.
guard let redirectUrl = URL(string: "\(bundleId):/oauth-callback") else { return }
guard error == nil,
let tokenEndpoint = tokenEndpoint,
let authorizationEndpoint = authorizationEndpoint,
let logoutEndpoint = logoutEndpoint,
let idToken = authState.lastTokenResponse?.idToken,
let userAgent = OIDExternalUserAgentIOS(presenting: presentingViewController)
else { return }
DispatchQueue.main.async {
print("Logging out via OpenID")
let configuration = OIDServiceConfiguration(authorizationEndpoint: authorizationEndpoint, tokenEndpoint: tokenEndpoint, issuer: nil, registrationEndpoint: nil, endSessionEndpoint: logoutEndpoint)
let logoutRequest = OIDEndSessionRequest(configuration: configuration,
idTokenHint: idToken,
postLogoutRedirectURL: redirectUrl,
additionalParameters: nil)
// Note: need to retain a strong reference to the returned object until we're done with its SFAuthenticationSession
appDelegate.currentAuthorizationFlow = OIDAuthorizationService.present(logoutRequest, externalUserAgent: userAgent) {
authorizationState, error in
print("OpenID logout: \(error?.localizedDescription ?? "SUCCESSFUL")")
appDelegate.currentAuthorizationFlow?.cancel()
appDelegate.currentAuthorizationFlow = nil
}
}
The redirectUrl
is indeed one of the authorized redirect URIs set in our identity server (FusionAuth).
When this code executes, the user is logged out, but then AppAuth immediately displays the alert: {app} Wants to use {domain} to Sign In
.
If the user taps Cancel
, the alert is dismissed and the final print statement then displays:
OpenID logout: The operation couldn’t be completed. (org.openid.appauth.general error -3.)
If the user taps Continue
, the alert is dismissed, then an empty modal dialog appears for an instant and dismisses itself, and the print statement displays:
OpenID logout: SUCCESSFUL
~Update: if I set redirectUrl
to ""
, then (so far, at least) that seems to solve the problem of getting a log-in alert following logout. Which actually totally makes sense!~
Updated update: My mistake -- URL(string: "")
actually returns nil
, and OIDEndSessionRequest()
does not accept nil
for postLogoutRedirectURL
.
Summary for the next person to deal with all of this...
"Sign In" alert on logout:
prefersEphemeralWebBrowserSession
to avoid the alert: https://github.com/openid/AppAuth-iOS/issues/402The The id_token_hint is invalid.
error alert that sometimes appears on attempted logout:
id_token
has expired. To avoid the error alert, before making the OIDEndSessionRequest
, call authState.performAction(freshTokens:)
to refresh the id_token
.@sethi-ishmeet My solution is similar to your but the problem is that
OIDAuthorizationService.present(endSessionRequest, externalUserAgent: agent!) {response, error in
Can retrieve response or error from this function.
this is my solution
let authEndpoint = URL(string: Urls.Hydra.authEndpoint())!
let tokenEndpoint = URL(string: Urls.Hydra.tokenEndpoint())!
let redirectURL = URL(string: Urls.Hydra.redirectCallbackURL())!
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 = hydraAuthStateModel.idToken else {
return
}
let endSessionRequest = OIDEndSessionRequest(configuration: configuration,
idTokenHint: idToken,
postLogoutRedirectURL: redirectURL,
state: hydraAuthStateModel.state!,
additionalParameters: nil)
let agent = OIDExternalUserAgentIOS(presenting: viewController)
OIDAuthorizationService.present(endSessionRequest,
externalUserAgent: agent!) {response, error in
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)")
success?()
}
Can you please help me to fix this issue?
@tiwariammit What exactly is the issue you are facing? I am not able to comprehend what's wrong in your code.
@sethi-ishmeet thank you for your response.
I successfully able to logout, but the issue is that after closing signout dialogue can'ta able to tack the completion of below function.
OIDAuthorizationService.present(endSessionRequest, externalUserAgent: agent!) {response, error in
The flow won't go inside block. So, can't able to track whether user logout successfully or not.
I am using AppAuth library to support Okta and Identity Server4 authentication in my iOS application. I am able make user to login but couldn't able to make user to logout. I did not find much document on logout process. Can anyone please provide me some documents or code snippet on user logout.