VKCOM / vk-ios-sdk

iOS library for working with VK API, authorization through VK app, using VK functions
MIT License
298 stars 165 forks source link

Проблема при авторизации. #525

Open UnumInAgro opened 6 years ago

UnumInAgro commented 6 years ago

При попытке авторизации открывается приложение ВК. нажимаю "Разрешить", после чего происходит возврат в приложение, и вызов метода vkSdkShouldPresent. (Происходит открытие окна авторизации в сафари). Подскажите что не так делаю. Как после возврата из приложения ВК получить сразу токен?

class RegistrationScreen: UIViewController, VKSdkDelegate, VKSdkUIDelegate {

    let VK_APP_ID = "6267***"
    let scope = ["email", "photos", "wall", "offline"]
    let dialogsControl = DialogsControl()

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func EnterButton(_ sender: Any) {
        let sdkInstance = VKSdk.initialize(withAppId: self.VK_APP_ID)
        sdkInstance?.register(self)
        sdkInstance?.uiDelegate = self;
        VKSdk.wakeUpSession(scope, complete: {(state: VKAuthorizationState, error: Error?) -> Void in
            if state == .authorized {

            } else {
                VKSdk.authorize(self.scope)
            }
            return
        })
    }

    func vkSdkShouldPresent(_ controller: UIViewController!) {
       self.present(controller, animated: true, completion: nil)
    }

    func vkSdkAccessAuthorizationFinished(with result: VKAuthorizationResult!) {
        print("token: \(result.token)")
    }

    func vkSdkAccessAuthorizationFinishedWithResult(result:VKAuthorizationResult?) -> Void {
        print("token2: \(String(describing: result?.token))")
    }

    func vkSdkUserAuthorizationFailed() -> Void {
        self.dialogsControl.closeAppDialog(controller: self)
    }

    func vkSdkAccessTokenUpdated(newToken:VKAccessToken?, oldToken:VKAccessToken?) -> Void {

    }

    func vkSdkAuthorizationStateUpdated(with result:VKAuthorizationResult) -> Void {

    }

    func vkSdkShouldPresentViewController(controller:UIViewController?) -> Void {

    }

    func vkSdkNeedCaptchaEnter(_ captchaError:VKError?) -> Void {

    }
}

plist :

<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>$(DEVELOPMENT_LANGUAGE)</string>
    <key>CFBundleDisplayName</key>
    <string></string>
    <key>CFBundleExecutable</key>
    <string>$(EXECUTABLE_NAME)</string>
    <key>CFBundleIdentifier</key>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>$(PRODUCT_NAME)</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>1.0</string>
    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>vk6267***</string>
            </array>
        </dict>
    </array>
    <key>CFBundleVersion</key>
    <string>1</string>
    <key>LSApplicationCategoryType</key>
    <string></string>
    <key>LSApplicationQueriesSchemes</key>
    <array>
        <string>vk</string>
        <string>vk-share</string>
        <string>vkauthorize</string>
    </array>
    <key>LSRequiresIPhoneOS</key>
    <true/>
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>******</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <false/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
        </dict>
    </dict>
    <key>UILaunchStoryboardName</key>
    <string>LaunchScreen</string>
    <key>UIMainStoryboardFile</key>
    <string>Main</string>
    <key>UIRequiredDeviceCapabilities</key>
    <array>
        <string>armv7</string>
    </array>
    <key>UISupportedInterfaceOrientations</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
    </array>
    <key>UISupportedInterfaceOrientations~ipad</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationPortraitUpsideDown</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
</dict>
</plist>

В AppDelegate:

private func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
        VKSdk.processOpen(url as URL!, fromApplication: sourceApplication)

        return true
    }
AlexeyMeshkov commented 6 years ago

У меня возникает ровно та же проблема. К сожалению выглядит так, будто в VK забросили разработку мобильных SDK.

weet1 commented 6 years ago

@AlexeyMeshkov похоже на то. мне не отвечают уже два месяца...

PiPhone commented 5 years ago

И у меня такая же. Ни у кого так и не удалось найти решение?

PutkovDimi commented 5 years ago

@weet1 @UnumInAgro @AlexeyMeshkov @PiPhone @chipp Здравствуйте, коллеги. Решил ли кто-нибудь эту проблему ?

NikKovIos commented 4 years ago

@UnumInAgro исправь плз заголовок на более информативный. Тем временем в версии 1.5.1 это всё ещё не исправлено. Соответственно, если делать смену пользователя и вызывать forceLogout, то пользователю нужно будет снова авторизовываться в Safari, что не удобно.

Попробовал сделать

func vkSdkShouldPresent(_ controller: UIViewController!) {
    self.token = VKSdk.accessToken().accessToken
}

Но там ещё нет токена, получается краш((

Mol0ko commented 4 years ago

Такая проблема может возникнуть если по какой-то причине после авторизации через приложение неверно отрабатывает этот метод sdk:

Снимок экрана 2020-03-17 в 18 07 21

Попробуйте поставить точки останова как на скрине выше и подебажить авторизацию. В нормальном варианте (после предоставления доступа в открывшемся приложении vk) отладчик должен остановиться внутри if.

В моем случае я неправильно реализовал метод апделегата и вышеупомянутый метод из sdk совсем не вызывался, вследствие чего не менялся статус авторизации и sdk открывал браузер.

Сейчас мой апделегат вот так обрабатывает урлы и у меня все работает, браузер после приложения не открывается:

    func application(_: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
        let sourceApplication = options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String
        let vkSdkResult = VKSdk.processOpen(url, fromApplication: sourceApplication)
        return vkSdkResult
    }
NikKovIos commented 4 years ago

@Mol0ko У меня сейчас есть и facebook и vk. Как думаешь, это правильно?

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {

        // Facebook
        if FBSDKCoreKit.ApplicationDelegate.shared.application(app, open: url, options: options) {
            return true
        }

        // Vkontakte
        if let callingAppName = options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String {
            if VKSdk.processOpen(url, fromApplication: callingAppName) {
                return true
            }
        }
        return false
    }
Mol0ko commented 4 years ago

@NikKovIos да, я аналогичный код использую для fb+vk

NikKovIos commented 4 years ago

У меня баг есть (

ckalolass commented 4 years ago

@Mol0ko У меня сейчас есть и facebook и vk. Как думаешь, это правильно?

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {

        // Facebook
        if FBSDKCoreKit.ApplicationDelegate.shared.application(app, open: url, options: options) {
            return true
        }

        // Vkontakte
        if let callingAppName = options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String {
            if VKSdk.processOpen(url, fromApplication: callingAppName) {
                return true
            }
        }
        return false
    }

@NikKovIos Не разыменовывай callingAppName, processOpen принимает опциональные значения. Все должно заработать если у тебя таргет ось > 9.0

NikKovIos commented 4 years ago

Ребят, нашёл причину. В ios 13 sourceApplication всегда nil по вопросам приватности. Просто убираем все if и делаем две строки. Одна с Facebook, другая с Vk. И в конце return true. СДК сами разруливают на что реагировать. (в коде выше тк sourceApplication == nil, в случае с фейсбуком всегда будет false, пока не обновите до 7.0.0, а вк не будет вызваться так как if let не будет получать sourceApplication). Я юзаю объединенную версию фейсбук сдк (FBSDKCore/Swift) и SwiftyVK.

yevreinov commented 4 years ago

Мне не помогли никакие решения.

Симптомы были такие: если приложения vk нет на девайсе, открывался webview вариант логина через метод: vkSdkShouldPresent После того, как пользователь жал кнопку "Разрешить" - ничего не происходило, страница перегружалась, обратно в мое приложение не возвращалось.

Если vk установлено, то оно открывалось, пользователь давал разрешение там, мое приложение снова открывалось, но токена не было и сразу открывался webview, где происходило то же самое, что и описано выше.

2 дня потратил на то, чтобы найти проблему.

В ios 13, если используете SceneDelegate (а именно так теперь по умолчанию), вызывается метод openURLContexts, а не open url в AppDelegate.

Решение: в SceneDelegate добавить:

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        if let url = URLContexts.first?.url {
            // Handle URL
            VKSdk.processOpen(url, fromApplication: nil)
        }
    }