title: AppAuth in IOS App, issue when renewing authorization Code / Alert briefly shows then goes
body: <p>I'm using AppAuth pod to handle user login with Azure in my app. I followed this sample : <a href="https://github.com/openid/AppAuth-iOS/tree/master/Examples" rel="nofollow noreferrer">https://github.com/openid/AppAuth-iOS/tree/master/Examples</a> which works fine until my authentication code expires.  It works ok for the 1st connection and all the time while the authenticationCode is still valid. Once it expires, I briefly see the alert to "Sign in" and then it disappears and I get the error :"Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior ()". (It works fine again if I delete the app and re-install it.)</p>
  
  <p>I read that I should "Ensure that there is a strong reference to the SFAuthenticationSession instance when the session is in progress.". And I think that's the case : the viewController from where I do the login has its private var authState. (see code below)
  Did anyone solved this issue ?</p>
  
  <pre><code>import UIKit
  import AppAuth
  import AuthenticationServices
  
  var isLoginViewOn: Bool = false
  var isConnectionBtnPressed: Bool = false
  
  class ContainerController: UIViewController {
  
  
  // MARKS : Properties
  
  private var authState: OIDAuthState?
  var token: String?
  
  var menuController: MenuController!   
  var homeController: HomeController!
  var panView: UIView!
  var isExpanded = false
  
  var isLoginOut: Bool = false
  
  let loginView: UIImageView = {
      let v = UIImageView()
      v.image = UIImage(named: "")
      v.contentMode = .scaleAspectFit
      return v
  }()
  
  let connexionButton: UIButton = {
      let b = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
      return b
  }()
  
  let logoutBtn: UIButton = {
      let b = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
      b.setTitle("déconnexion", for: .normal)
      return b
  }()
  
  
  override func viewDidLoad() {
      super.viewDidLoad()
       chekToken()   
  }
  
  
  
  override func viewDidAppear(_ animated: Bool) {
      super.viewDidAppear(animated)
      if isLoginViewOn == true {
          if isConnectionBtnPressed == false {
              self.connexionButton.sendActions(for: .touchUpInside)
              isLoginViewOn = false
          } 
  
      }
  }
      override func viewWillLayoutSubviews() {
      super.viewWillLayoutSubviews()
      view.layoutIfNeeded()
      view.layoutSubviews()
  }
  
  /////////////////////////////////////////////////////////////////////////////
  ///                                 SET UP                               ////
  /////////////////////////////////////////////////////////////////////////////
  
  
  func setupLoginView() {
      print("setup loginView")
      isLoginViewOn = true
      view.addSubview(loginView)
      view.addSubview(connexionButton)
  
      loginView.translatesAutoresizingMaskIntoConstraints = false
      connexionButton.translatesAutoresizingMaskIntoConstraints = false
  
      [
          loginView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
          loginView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
          loginView.widthAnchor.constraint(equalToConstant: 250),
          loginView.heightAnchor.constraint(equalToConstant: 128),
  
  
          connexionButton.bottomAnchor.constraint(equalTo: loginView.topAnchor, constant: -50),
          connexionButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
          connexionButton.widthAnchor.constraint(equalToConstant: 200),
          connexionButton.heightAnchor.constraint(equalToConstant: 50),
  
          ].forEach{$0.isActive = true }
  
      connexionButton.addTarget(self, action: #selector(buttonAction(_:)), for: .touchUpInside)
  
      if isConnectionBtnPressed == false {
          self.connexionButton.sendActions(for: .touchUpInside)
      }
  }
  
  
  func setupHomeController() {
      homeController = HomeController()
      homeController.delegate = self 
      addControllerAsChild(forController: homeController)
      setupPanView(forController: homeController)
  }
  
  }
  </code></pre>
  
  <p>///                                 LOGIN                                ////</p>
  
  <pre><code>extension ContainerController {
  
  
  @objc func buttonAction(_ sender: UIButton){
      self.login()
      isConnectionBtnPressed = true
  }
  
  func checkToken() {
          guard let data = UserDefaults.standard.object(forKey: kAppAuthExampleAuthStateKey) as? Data else {
              setupLoginView()
              return
          }
  
          do {
              let authState = try NSKeyedUnarchiver.unarchivedObject(ofClass: OIDAuthState.self, from: data)
              self.setAuthState(authState)
              self.getUserInfo()
          } catch { print("catch loadState: \(error)") }
  }
  
  
  func login() {
      print("Got configuration: \(config)")
         if let clientId = kClientID {
             self.doAuthWithAutoCodeExchange(configuration: config, clientID: clientId, clientSecret: nil)
         }
  
     }
  
  
          func doAuthWithAutoCodeExchange(configuration: OIDServiceConfiguration, clientID: String, clientSecret: String?) {
              guard let redirectURI = URL(string: kRedirectURI) else {
                  print("Error creating URL for : \(kRedirectURI)")
                  return
              }
  
              guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
                  print("Error accessing AppDelegate")
                  return
              }
  
              // builds authentication request
  
              let request = OIDAuthorizationRequest(configuration: configuration,
                                                    clientId: clientID,
                                                    clientSecret: clientSecret,
                                                    scopes: [OIDScopeOpenID, OIDScopeProfile, "--kclientID--", "offline_access"],
                                                    redirectURL: redirectURI,
                                                    responseType: OIDResponseTypeCode,
                                                    additionalParameters: ["p": "b2c_1_my_app_sign_in_up"])
  
  
              // performs authentication request
              print("Initiating authorization request with scope: \(request.scope ?? "DEFAULT_SCOPE")")
  
              appDelegate.currentAuthorizationFlow = OIDAuthState.authState(byPresenting: request, presenting: self) { authState, error in
                  if let authState = authState {
                     self.setAuthState(authState)
                     print("Got authorization tokens. Access token")
                     self.getUserInfo()
  
                  } else {
                      self.setAuthState(nil)
                      print("Authorization error: \(error?.localizedDescription ?? "DEFAULT_ERROR")")
  
                  }
              }
          }
  
   func getUserInfo() {
       let currentAccessToken: String? = self.authState?.lastTokenResponse?.accessToken
         self.authState?.performAction() { (accessToken, idToken, error) in
             if error != nil  {
              CoreDataHelper().deleteIDToken("idToken")
              AuthenticationService().login()
                 print("Error fetching fresh tokens: \(error?.localizedDescription ?? "ERROR")")
                 return
             }
  
             guard let accessToken = accessToken else {
                 print("Error getting accessToken")
                 return
             }
  
             if currentAccessToken != accessToken {
              print("Access token was refreshed automatically ")
               self.token = currentAccessToken
             } else {
              print("Access token was fresh and not updated ")
               self.token = accessToken
             }
  
          self.loginView.removeFromSuperview() 
          self.setupHomeController()
         }
   }
  
  
  func saveState() {
      var data: Data? = nil
  
      if let authState = self.authState {
          do {
              data = try NSKeyedArchiver.archivedData(withRootObject: authState, requiringSecureCoding: false)
  
          } catch { print("catch saveState: \(error)") }
  
      }
      UserDefaults.standard.set(data, forKey: kAppAuthExampleAuthStateKey)
      UserDefaults.standard.synchronize()
  }
  
  func setAuthState(_ authState: OIDAuthState?) {
      if (self.authState == authState) {
          return;
      }
      self.authState = authState;
      self.authState?.stateChangeDelegate = self;
      self.saveState()
  }
  
  
  }
  extension ContainerController: ASWebAuthenticationPresentationContextProviding {
  func presentationAnchor(for session: ASWebAuthenticationSession) -&gt; ASPresentationAnchor {
      return view.window!
  }
  </code></pre>
  
  <p>}</p>
  
  <p>And in AppDelegate I put this on the top :</p>
  
  <pre><code>let kClientID: String? = "my client id";
  let kRedirectURI: String = "myapp.test.authent://oauth/redirect";
  let kAppAuthExampleAuthStateKey: String = "authState";
  
  let authorizationEndpoint = URL(string: "https://login.microsoftonline.com/myapp.onmicrosoft.com/oauth2/v2.0/authorize?p=b2c_1_myaapp_sign_in_up")!
  let tokenEndpoint = URL(string: "https://login.microsoftonline.com/myapp.onmicrosoft.com/oauth2/v2.0/token?p=b2c_1_myaapp_sign_in_up")!
  let config = OIDServiceConfiguration(authorizationEndpoint: authorizationEndpoint,
                                              tokenEndpoint: tokenEndpoint)
  </code></pre>
  
  <p>and in the AppDelegate class :</p>
  
  <pre><code>func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -&gt; Bool {
          // Sends the URL to the current authorization flow (if any) which will
          // process it if it relates to an authorization response.
          if let authorizationFlow = self.currentAuthorizationFlow, authorizationFlow.resumeExternalUserAgentFlow(with: url) {
              self.currentAuthorizationFlow = nil
              return true
          }
  
      return false
  }
  </code></pre>
  
  <p>Any suggestion is welcomed :) </p>