I have integrated ADAL library into my iOS application and it\'s working fine. But now I want to log out from ADAL. How can I do log out?
An update to Rich's excellent answer. First, the interface has changed with the latest ADAL release and you need to access the token cache this way:
#import <ADAL/ADKeychainTokenCache.h>
[...]
[[ADKeychainTokenCache defaultKeychainCache] removeAllForClientId:ADFS_CLIENT_ID error:&error];
And to clear the cookies, I recommend just deleting the ones that matter instead of clearing them all:
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [cookieJar cookies]) {
if ([cookie.name isEqualToString:@"MSISAuth"] ||
[cookie.name isEqualToString:@"MSISAuthenticated"] ||
[cookie.name isEqualToString:@"MSISLoopDetectionCookie"]) {
[cookieJar deleteCookie:cookie];
}
}
(I found that AD_PROMPT_ALWAYS didn't work on older ADFS installations and was forced to delete cookies.)
This swift 3 code worked for me (ADAL 2.5.1):
Destroy the keystore:
guard let clientId = getAuthConfig().clientId else {
// freak out
print("Auth.logout: I freaked out getting the client ID ")
return
}
ADKeychainTokenCache.defaultKeychain().removeAll(forClientId: clientId, error: nil)
And clear the cookies:
let cookieJar = HTTPCookieStorage.shared
guard let cookies = cookieJar.cookies else { return }
let cookiesArr = Array(cookies)
for cookie: HTTPCookie in cookiesArr {
print(cookie.name)
if (cookie.name == "SignInStateCookie" || cookie.name == "ESTSAUTHPERSISTENT" || cookie.name == "ESTSAUTHLIGHT" || cookie.name == "ESTSAUTH" || cookie.name == "ESTSSC") {
cookieJar.deleteCookie(cookie)
}
}
There are two places where sign-in state is stored when using an ADAL interactive flow. The first is the token cache that is entirely in the control of the app. Calling [authContext.tokenCacheStore removeAllWithError:&error] is a good way to clear all cached tokens and stop ADAL from being able to login without launching the browser at all.
However, sign-in state is also tracked by the server in browser cookies. The server will remember that a user was signed-in to the server until the cookie times out or is removed. When ADAL checks the cache and doesn't find a suitable token it will launch the webView. The server will find a cookie and then silently sign the user in. Browser cookies are largely hidden from ADAL. The ADAL library could potentially provide a sign-out function that clears all cookies, but this would have side effects if the app was depending on other cookies for some reason.
There are a couple of ways of working around this. If you simply want to log out and you don't mind clearing all webView cookies then after you clear the cache, clear out all browser cookies as described here:
How to delete all cookies of UIWebView?
That's the nuclear option. Another, more subtle option, is to clear the cache and then use the AD_PROMPT_ALWAYS value in a call to aquireToken that takes an ADPromptBehavior parameter. When you use AD_PROMPT_ALWAYS a flag is sent to AAD that causes it to ignore the cookies and surface a fresh prompt to the user. This leaves the cookies in place so technically the user is not actually signed out. To the user, it appears that they were signed out and have the ability to sign in again later. When they sign in again they can choose a different user if they prefer.
This is also the way you would handle sign-in with multiple users. In the case where you already have a user signed in, but want add another, do not clear the cache and pass AD_PROMPT_ALWAYS on the next call to acquireToken. The server will surface a fresh sign-in prompt and return a new token. That token will be stored in that ADAL cache. You get the a token for a particular user by calling acquireToken and passing a userId.