Token 발급 실패 문제

3-12-19 06:42:19541 [:bangbang:][AuthRequestRetrier.swift 40:25] → request retrier:
error:requestAdaptationFailed(error: KakaoSDKCommon.SdkError.ClientFailed(reason: KakaoSDKCommon.ClientFailureReason.TokenNotFound, errorMessage: Optional(“authentication tokens not exist.”)))
not api error → pass through

이 에러가 발생하는데 카카오가 안깔려있을대 웹로그인이 뜨는화면에서 발생하는화면입니다.

근데 같은 코드인데 iphone8 에서는 문제가 없는데 iphone 11에서는 문제가 발생합니다… 왜그럴까요?
둘다 ios는 16 이상이고 iphone11에서는 17씁니다.

sdk 버전은 2.19.0입니다.ㅠㅠㅠ

AuthRequestRetrier는 API 사용 시, 접근 토큰이 만료 되었거나 동의 항목에 동의하지 않아 권한이 불충분한 경우 내부적으로 다시 카카오 로그인 시도하기 위해 사용됩니다.

정확한 확인을 위해 사용하시는 앱 ID 부탁드립니다.

ID505902 입니다~
최초 설치 하고 로그인할때 발생하고 있습니다. 로그인창을 아예 띄우지 못해서 로그인을 할수가 없는 상태로 지속됩니다(카카오 앱이 설치되어있지 않아서)

카카오 로그인 구현하신 코드도 같이 부탁드립니다.

//
//  AppDelegate.swift
//

import UIKit
import KakaoSDKCommon
import KakaoSDKAuth
import FirebaseCore
import FirebaseFirestore
import FirebaseMessaging
import AppsFlyerLib
import SwiftyBootpay
import FirebaseDynamicLinks
import AppTrackingTransparency
import AdSupport
import ChannelIOFront
import Alamofire
import SwiftyJSON

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate  {
    
    var window: UIWindow?
    let gcmMessageIDKey = "gcm.message_id"
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        ChannelIO.initialize(application)
        
        KakaoSDK.initSDK(appKey: "----------------------")
        
        FirebaseApp.configure()
        Bootpay.sharedInstance.appLaunch(application_id: "--------------------)
        Messaging.messaging().delegate = self
        
        AppsFlyerLib.shared().appsFlyerDevKey = "-----------------------"
        AppsFlyerLib.shared().appleAppID = "------------------"
        AppsFlyerLib.shared().deepLinkDelegate = self
        AppsFlyerLib.shared().delegate = self
#if DEBUG 
        AppsFlyerLib.shared().isDebug = true
#endif
        if #available(iOS 10.0, *) {
            // For iOS 10 display notification (sent via APNS)
            UNUserNotificationCenter.current().delegate = self
            
            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
            UNUserNotificationCenter.current().requestAuthorization(
                options: authOptions,
                completionHandler: {_, _ in })
            application.registerForRemoteNotifications()
        } else {
            let settings: UIUserNotificationSettings =
            UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
            application.registerUserNotificationSettings(settings)
            UIApplication.shared.registerForRemoteNotifications()
        }
        
        application.registerForRemoteNotifications()
        
        //        window = UIWindow(frame: UIScreen.main.bounds)
        //        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        //        let view = storyboard.instantiateViewController(withIdentifier: "ViewController")
        //        let rootview = UINavigationController(rootViewController: view)
        //        window!.rootViewController = rootview
        //        window!.makeKeyAndVisible()
        
        
        if(UserDefaults.standard.integer(forKey: UserDefaultsKey.lastBranch) == 0){
            UserDefaults.standard.set(2, forKey: UserDefaultsKey.lastBranch)
        }
        
        Thread.sleep(forTimeInterval: 2.0)
        
        return true
    }
    
    func applicationWillResignActive(_ application: UIApplication) {
        Bootpay.sharedInstance.sessionActive(active: false)
    }
    
    func applicationDidBecomeActive(_ application: UIApplication) {
        AppsFlyerLib.shared().start()
        Bootpay.sharedInstance.sessionActive(active: true)
        
        let notificationName = Notification.Name("BecomeActive")
        NotificationCenter.default.post(name: notificationName, object: nil)
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        AppsFlyerLib.shared().continue(userActivity, restorationHandler: nil)
    }
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        //        print("APNs token retrieved: \(deviceToken)")
        
    }
    
    func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
        Messaging.messaging().apnsToken = deviceToken as Data
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
        
        if let messageID = userInfo[gcmMessageIDKey] {
            //            print("Message ID: \(messageID)")
        }
        
        //        print(userInfo)
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        AppsFlyerLib.shared().handlePushNotification(userInfo)
        if let messageID = userInfo[gcmMessageIDKey] {
            //            print("Message ID: \(messageID)")
        }
        
        // Print full message.
        //        print(userInfo)
        completionHandler(UIBackgroundFetchResult.newData)
    }
    
    func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
        AppsFlyerLib.shared().continue(userActivity, restorationHandler: nil)
        
        let handled = DynamicLinks.dynamicLinks().handleUniversalLink(userActivity.webpageURL!) { (dynamiclink, error) in
            if let dynamiclink = dynamiclink {
                if dynamiclink.url?.relativePath == "/invite" {
                    let notificationName = Notification.Name("RcvDeepLink")
                    NotificationCenter.default.post(name: notificationName, object: nil, userInfo: [
                        "shortUrl" : userActivity.webpageURL!.absoluteString,
                        "inviteUrl": dynamiclink.url!.absoluteString
                    ])
                }
            }
               
        }
        return handled
    }
    
    func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
        
        return true
    }
    
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        if (AuthApi.isKakaoTalkLoginUrl(url)) {
            return AuthController.handleOpenUrl(url: url)
        }
        
        return false
    }
    
    func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
        AppsFlyerLib.shared().handleOpen(url, sourceApplication: sourceApplication, withAnnotation: annotation)
        return true
    }
    
}



// [START ios_10_message_handling]
@available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
    
    // Receive displayed notifications for iOS 10 devices.
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        let userInfo = notification.request.content.userInfo
        
        if let messageID = userInfo[gcmMessageIDKey] {
            //            print("Message ID: \(messageID)")
        }
        
        //        print(userInfo)
        
        completionHandler([[.alert, .sound]])
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        let userInfo = response.notification.request.content.userInfo
        
        if let messageID = userInfo[gcmMessageIDKey] {
            //            print("Message ID: \(messageID)")
        }
        
        //        print(userInfo)
        
        completionHandler()
    }
    
    
}

extension AppDelegate : MessagingDelegate {
    // [START refresh_token]
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        //        print("Firebase registration token: \(String(describing: fcmToken))")
        
        if let token = fcmToken {
            let dataDict:[String: String] = ["token": token]
            NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
        }
        
    }
    // [END refresh_token]
}


extension AppDelegate: AppsFlyerLibDelegate {
    // Handle Organic/Non-organic installation
    func onConversionDataSuccess(_ data: [AnyHashable: Any]) {
        //        print("onConversionDataSuccess data:")
        for (key, value) in data {
            //            print(key, ":", value)
        }
        if let status = data["af_status"] as? String {
            if (status == "Non-organic") {
                if let sourceID = data["media_source"],
                   let campaign = data["campaign"] {
                    //                    print("This is a Non-Organic install. Media source: \(sourceID)  Campaign: \(campaign)")
                }
            } else {
                //                print("This is an organic install.")
            }
            if let is_first_launch = data["is_first_launch"] as? Bool,
               is_first_launch {
                //                print("First Launch")
            } else {
                //                print("Not First Launch")
            }
        }
    }
    func onConversionDataFail(_ error: Error) {
        //        print("\(error)")
    }
    // Handle Deeplink
    func onAppOpenAttribution(_ attributionData: [AnyHashable: Any]) {
        //Handle Deep Link Data
        //        print("onAppOpenAttribution data:")
        for (key, value) in attributionData {
            //            print(key, ":",value)
        }
    }
    func onAppOpenAttributionFailure(_ error: Error) {
        //        print("\(error)")
    }
}
extension UIApplication {
    /*function will return reference to tabbarcontroller */
    func tabbarController() -> UIViewController? {
        guard let vcs = self.keyWindow?.rootViewController?.children else { return nil }
        for vc in vcs {
            if  let _ = vc as? UITabBarController {
                return vc
            }
        }
        return nil
    }
}

extension AppDelegate: DeepLinkDelegate {
    func didResolveDeepLink(_ result: DeepLinkResult) {
        var fruitNameStr: String?
        switch result.status {
        case .notFound:
            NSLog("[AFSDK] Deep link not found")
            return
        case .failure:
            print("Error %@", result.error!)
            return
        case .found:
            NSLog("[AFSDK] Deep link found")
        }
        
        guard let deepLinkObj:DeepLink = result.deepLink else {
            NSLog("[AFSDK] Could not extract deep link object")
            return
        }
        
        if deepLinkObj.clickEvent.keys.contains("deep_link_sub2") {
            let ReferrerId:String = deepLinkObj.clickEvent["deep_link_sub2"] as! String
            NSLog("[AFSDK] AppsFlyer: Referrer ID: \(ReferrerId)")
        } else {
            NSLog("[AFSDK] Could not extract referrerId")
        }
        
        let deepLinkStr:String = deepLinkObj.toString()
        NSLog("[AFSDK] DeepLink data is: \(deepLinkStr)")
            
        if( deepLinkObj.isDeferred == true) {
            NSLog("[AFSDK] This is a deferred deep link")
        }
        else {
            NSLog("[AFSDK] This is a direct deep link")
        }
        
        fruitNameStr = deepLinkObj.deeplinkValue
    }
}


================= 로그인 버튼 코드 =================

  if (UserApi.isKakaoTalkLoginAvailable()) {
            UserApi.shared.loginWithKakaoTalk {(oauthToken, error) in
                if let error = error {
                    print(error)
                    self.view.makeToast("카카오톡이 설치 되어있지 않거나 사용자가 로그인을 취소하였습니다.")
                }
                else {
                    self.kakaoUserInfo()
                }
            }
        } else {
            UserApi.shared.loginWithKakaoAccount {(oauthToken, error) in
                if let error = error {
                    print(error)
                    self.view.makeToast("사용자가 로그인을 취소하였습니다.")
                }
                else {
                    self.kakaoUserInfo()
                }
            }
        }

appdelegate와 로그인버튼 누를때 코드 입니다.

안녕하세요.

[:bangbang:][AuthRequestRetrier.swift 40:25] → request retrier:
error:requestAdaptationFailed(error: KakaoSDKCommon.SdkError.ClientFailed(reason: KakaoSDKCommon.ClientFailureReason.TokenNotFound, errorMessage: Optional(“authentication tokens not exist.”)))
not api error → pass through

위 에러의 경우, SDK 내부적으로 토큰 여부 체크 및 토큰 리프레시 진행합니다. 앱 최초 설치 시에는 토큰 정보가 없어 아래의 에러가 발생할 수 있습니다.

웹 로그인 시도 시 로그인 창이 안뜬다 말씀주셨는데 내부에서 테스트할 때는 재현이 되지 않아 추가적으로 질문드려요.

  • iOS 17을 사용하는 다른 기기에서 발생이 될까요?
  • 발생하는 디바이스의 디폴트 브라우저는 어떻게 될까요?
  • 2.19.0 미만의 SDK를 사용했을 때는 문제가 없었을까요?

ios 17을 사용하는 다른 기기는 없어서 테스트 하지 못했습니다.
사파리가 기본브라우저이고 다른 브라우저 설치된건없습니다
2.18 버전에서도 발생합니다.


이렇게 아무화면도 뜨지 않습니다.

기종은 iphone 11pro입니다.
동일코드가 iphone8에서는 문제가 없구요.ㅠㅠ
타겟버전은 13이지만 scenedelegate 사용하지 않습니다.

iphone8에서도 별도 브라우저 설치된거없이 사파리만있습니다.
개발용 폰들이라 카카오앱이 설치되어있지 않습니다 두대 모두

확인부탁드리겠습니다!

서버 로그를 확인해 봤을 때, 브라우저에서 로그인 페이지에 아예 접근하지 못한 것으로 보입니다.
디바이스 상에 방화벽 설정이 되어 있을까요?
해당 페이지를 사파리 브라우저에서 접근이 불가능한지 확인 부탁드립니다.

사파리에서 안열리네요; 어디서 차단된건지 찾아봐야겠네요;; 포맷한 폰이라 그런걸 따로 한적이 없었는데…
다른폰에서는 열리는거 확인했습니다

사파리에서 안열리는 문제는 방문기록을 지우고나니 해결이 되었는데 앱에서 로그인창이 안열리는건 해결이 안됩니다 ㅠㅠ
방화벽이라는 옵션은 별도로 찾을수가 없는데 다른 원인은 없을까요?

문제가 발생하는 디바이스의 웹페이지를 사파리 웹페이지에서 디버깅 해보시겠어요? (참고)
해당 로그인 웹페이지가 로드 되었을 때 네트워크 요청이 정상적으로 발생되는지 확인 부탁드립니다.