AppAuth-iOS
AppAuth-iOS copied to clipboard
AppAuth-Logout from Okta and Identity Server4 in iOS mobile application.
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.
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 :(
I tested the OIDEndSessionRequest and works well, the only problem is the popup message.
My solution follows this comment.
I use Keycloak as my IdP, so my OIDC logout endpoint is:
POST https://keycloak.example.com/auth/realms/REALM_NAME/protocol/openid-connect/logout
Content-Type: application/x-www-form-urlencoded
client_id=<my_client_id>&refresh_token=<refresh_token>
In the example Example-iOS_Swift-Carthage, my configuration is:
let kIssuer: String = "https://keycloak.company.com/auth/realms/REALM_NAME";
let kClientID: String? = "ios-app";
let kRedirectURI: String = "com.company.app://oauth/callback";
I added a logout button, the code snippet looks like this:
@IBAction func logout(_ sender: UIButton) {
// TODO: Handle errors and optionals
let issuer = URL(string: kIssuer)!
let refreshToken = self.authState!.refreshToken!
// clear the auth state
self.setAuthState(nil)
// discovers endpoints, we need the endSessionEndpoint
// in my case it is:
// https://keycloak.example.com/auth/realms/REALM_NAME/protocol/openid-connect/logout
// you can use the endpoint directly if you want
OIDAuthorizationService.discoverConfiguration(forIssuer: issuer) { configuration, error in
// TODO: Handle errors and optionals
let url = configuration!.endSessionEndpoint!
let data = "client_id=\(kClientID!)&refresh_token=\(refreshToken)".data(using: .utf8)!
// we create the request
let session = URLSession(configuration: URLSessionConfiguration.default)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField:"Content-Type");
request.httpBody = data
// we perform the logout in the server
let task = session.dataTask(with: request, completionHandler: {
(data, response, error) in
// TODO: Handle errors and optionals
// FIXME: This code is for debug only
print("task completionHandler")
print("data = \(String(describing: data))")
print("response = \(String(describing: response))")
print("error = \(String(describing: error))")
})
task.resume()
}
}
The login works fine:
If I only clear the auth state, I cannot change the user until accessToken expires:
If I perform the logout in the server, it seems to works:
If I did something wrong, please let me know
@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!