質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
OAuth

OAuth(Open Authorization)は、APIを通して保護されたリソース(サードパーティのアプリケーション)へアクセスする為のオープンプロトコルです。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

2回答

642閲覧

ZaimAPIでOAuthSwiftによる認証・コールバックがうまくいかない

maztak

総合スコア61

OAuth

OAuth(Open Authorization)は、APIを通して保護されたリソース(サードパーティのアプリケーション)へアクセスする為のオープンプロトコルです。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2019/03/23 13:55

編集2019/03/24 01:33

前提・実現したいこと

ZaimAPIを使って音声で出費登録できるiOSアプリを作っています。

まずOAuth認証をしてアクセスキーを入手したく下記を参考にしているのですが、「ログインして許可する」を押して「認証が完了」と表示されるもののアプリに戻ってくれず、アクセスキーが入手できません。
http://qs.nndo.jp/oauth-swift-zaim
https://qiita.com/fromage-blanc/items/739622dee826806c12d5

発生している問題・エラーメッセージ

予定では認証完了後にAppDelegateのメソッドが呼ばれて、コールバック時のクロージャー内でアクセスキー(credential.oauthTokencredential.oauthTokenSecret)がprint出力されるはずなのですが、まずAppDelegateのメソッドが呼ばれません。

Xcodeのコンソールにも特にエラーメッセージはでていないです。

該当のソースコード

イメージ説明

※一度Zaim Developers Center側でアプリを削除して作り直そうとしたら、同じ名称だと重複と言われたので名称を変えています。
イメージ説明

swift

1// ViewController.swift 2import UIKit 3import OAuthSwift 4 5class ViewController: UIViewController { 6 7 var oauthswift: OAuthSwift? = nil 8 9 @IBAction func onTappedSyncButton(_ sender: UIButton) { 10 11 let oauthswift = OAuth1Swift( 12 consumerKey: "**********", 13 consumerSecret: "**********", 14 requestTokenUrl: "https://api.zaim.net/v2/auth/request", 15 authorizeUrl: "https://auth.zaim.net/users/auth", 16 accessTokenUrl: "https://api.zaim.net/v2/auth/access" 17 ) 18 19 self.oauthswift = oauthswift 20 oauthswift.authorizeURLHandler = getURLHandler() 21 22 let _ = oauthswift.authorize( 23 withCallbackURL: URL(string: "KoeDeZaim://oauth-callback")!, 24 success: { credential, response, parameters in 25 self.showTokenAlert(name: "Service", credential: credential) 26 }, 27 failure: { error in 28 print(error.description) 29 } 30 ) 31 } 32 33 func getURLHandler() -> OAuthSwiftURLHandlerType { 34 if #available(iOS 9.0, *) { 35 let handler = SafariURLHandler(viewController: self, oauthSwift: self.oauthswift!) 36 handler.presentCompletion = { 37 print("Safari presented") 38 } 39 handler.dismissCompletion = { 40 print("Safari dismissed") 41 } 42 return handler 43 } 44 return OAuthSwiftOpenURLExternally.sharedInstance 45 } 46 47 func showTokenAlert(name: String?, credential: OAuthSwiftCredential) { 48 var message = "oauth_token:(credential.oauthToken)" 49 if !credential.oauthTokenSecret.isEmpty { 50 message += "\n\noauth_token_secret:(credential.oauthTokenSecret)" 51 } 52 self.showAlertView(title: name ?? "Service", message: message) 53 54 } 55 56 func showAlertView(title: String, message: String) { 57 let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert) 58 alert.addAction(UIAlertAction(title: "Close", style: UIAlertAction.Style.default, handler: nil)) 59 self.present(alert, animated: true, completion: nil) 60 } 61 62}

swift

1// AppDelegate.swift 2import UIKit 3import OAuthSwift 4 5@UIApplicationMain 6class AppDelegate: UIResponder, UIApplicationDelegate { 7 8 func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool { 9 applicationHandle(url: url) 10 return true 11 } 12} 13 14extension AppDelegate { 15 16 func applicationHandle(url: URL) { 17 if (url.host == "oauth-callback") { 18 OAuthSwift.handle(url: url) 19 } else { 20 // Google provider is the only one wuth your.bundle.id url schema. 21 OAuthSwift.handle(url: url) 22 } 23 } 24}

ruby

1# platform :ios, '10.0' 2 3target 'KoeDeZaim' do 4 # Comment the next line if you're not using Swift and don't want to use dynamic frameworks 5 use_frameworks! 6 7 # Pods for KoeDeZaim 8 pod 'OAuthSwift' 9 10 target 'KoeDeZaimTests' do 11 inherit! :search_paths 12 # Pods for testing 13 end 14 15 target 'KoeDeZaimUITests' do 16 inherit! :search_paths 17 # Pods for testing 18 end 19 20end

試したこと

  • デリゲートメソッドを以下に変えても呼ばれませんでした。

swift

1// AppDelegate.swift 2 func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { 3 if (url.host == "oauth-callback") { 4 OAuthSwift.handle(url: url) 5 } 6 return true 7 }
  • 認証完了画面で左上の「完了」ボタンを押してアプリに戻っても特に変わりません。
  • getURLHandler()内で必ずOAuthSwiftOpenURLExternally.sharedInstanceを返すようにし、Safariで認証を行ってもうまくいきませんでした。
  • OAuthSwiftのDemoで以下すべてのパターンでうまくいきませんでした。

・external web browser
・internal web browser
・SFSafariViewController

補足情報(FW/ツールのバージョンなど)

  • Xcode10.1
  • Swift4.2
  • Depleyment Target: iOS 12.1
  • OAuthSwift: 1.2.2

完成イメージ
https://soh335.hatenablog.com/entry/2013/03/03/004306

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2019/03/26 02:11

Q1. 「AppDelegateのメソッドが呼ばれません」というの application(_:open:options:) のことですよね?呼ばれていないことをどうやって確認しましたか? Q2. Safariで KoeDeZaim:// を開くとアプリが起動しますか?
maztak

2019/03/26 04:36

ありがとうございます! Q1. そうです。BreakPointを`func`, `if`の行に設定しましたが一度もそこで止まることはありませんでした。 Q2. 「このページをKoeDeZaimで開きますか?」のメッセージの後、「開く」を押すと起動してくれました!そしてQ1の`if`でBreakしますがその後、中には入ってきてくれず`return true`しちゃいます。
fuzzball

2019/03/26 04:50

ということはURL Schemeは正しく設定されているということですね。 Zaim側が認識できていないか、認識できているのに呼び出されていないか。 参考記事の「アプリケーションの登録」で「サービスのURL」を登録していますが、ここは何を設定しましたか?
maztak

2019/03/26 04:52

OAuth1Swift.swiftのauthorize(callbackURL: success: failure)の中で止めてみると、SafariでZaimの認証画面に行く前にsuccessでは止まらずfailure側にきました。
fuzzball

2019/03/26 05:06

これは何の話ですか?
maztak

2019/03/26 06:03 編集

サービスのURLは私のドメインのhttps://right-apps.com/koedezaimとしています。参考記事だとcallbackURLと同じにしていましたが、ここは何でもいいという記述だったので上記に変えた次第です。 2番目はOAuthSwiftのライブラリの中でBreakpointを設定してみて、挙動から原因を探ってみたという話でした。OAuthSwiftの認証メソッドの結果が失敗しているようだ、という話でした。余計でしたでしょうか…。続けて記載したつもりが(ページリロードのタイミング差で)意味不明なお返事を返した形になってしまってました…。失礼いたしました…。
fuzzball

2019/03/26 06:15

>>OAuth1Swift.swiftのauthorize(callbackURL: success: failure)の中で〜 って、ViewController.swiftのことですかね。ライブラリ内部の話をしているのかと思いましたが‥。 failureになっているならエラーが表示されているんですよね? それを書いてもらえませんか。
maztak

2019/03/26 07:17 編集

すみません????‍♂️混乱して勘違いしてしまっておりました…。 ViewController.swiftのauthorize(callbackURL: success: failure)ではsuccessにもfailureにも降りてきてませんで、ライブラリ内部の話で合っております。 OAuth1Swift.swiftの中の以下3行でBreakPointを設定した際に①→③→①→②の順で止まりました。 ①self.postOAuthRequestToken ②self.observeCallback ③return self(ここで止まったのをfailureに来たと勘違いしてしまった) ``` open func authorize(withCallbackURL callbackURL: URL, success: @escaping TokenSuccessHandler, failure: FailureHandler?) -> OAuthSwiftRequestHandle? { self.postOAuthRequestToken(callbackURL: callbackURL, success: { [unowned self] credential, _, _ in self.observeCallback { [weak self] url in      // 省略 } // 2. Authorize // 省略 }, failure: failure) return self } ``` ViewController.swift側のprint(error.localizedDescription)は呼ばれないのですが、SafariでZaimの認証画面に遷移後、以下の内容がコンソールにでます。 ``` 2019-03-26 15:48:26.693416+0900 KoeDeZaim[20424:4021157] [BoringSSL] nw_protocol_boringssl_get_output_frames(1301) [C1.1:2][0x151b0ab70] get output frames failed, state 8196 2019-03-26 15:48:26.694251+0900 KoeDeZaim[20424:4021157] [BoringSSL] nw_protocol_boringssl_get_output_frames(1301) [C1.1:2][0x151b0ab70] get output frames failed, state 8196 2019-03-26 15:48:26.695169+0900 KoeDeZaim[20424:4021157] TIC Read Status [1:0x0]: 1:57 2019-03-26 15:48:26.695232+0900 KoeDeZaim[20424:4021157] TIC Read Status [1:0x0]: 1:57 2019-03-26 15:48:27.458230+0900 KoeDeZaim[20424:4021054] Could not load IOSurface for time string. Rendering locally instead. ``` stack overflowでは同じエラーで回答なしの人がいたり、Storyboardを使っていて「tableview.registerでなくreuseIdentifierを使え」とアドバイスされている方がいましたが今回とは無関係そうです…。ややこしくすみません????‍♂️
fuzzball

2019/03/26 07:26

実際に試さないと私には分かりそうにないので、この辺で撤収します。
maztak

2019/03/26 07:30

分かりました。お時間とご尽力ありがとうございました!
guest

回答2

0

ブラウザアプリを選択後、Zaim側のドキュメントに以下の文言があったので、サービスURLとcallbackURLを同じにすると認証画面にいき、無事コールバックURLが呼ばれトークンが取得できました!

If you select "Browser App", Zaim give you a permission to access only form the domain which you input the "Service URL".

投稿2019/03/31 14:59

編集2019/03/31 15:01
maztak

総合スコア61

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

自己解決

Zaimから回答いただき、クライアントアプリでなくブラウザアプリを選択しないとコールバックしないとのことでした。

しかしブラウザアプリに切り替えて試みると「お客様の端末の設定によりアクセスできません。端末の時間が 5 分以上ずれているとログインできないことがあります。」との画面が出て今度はログインができません。

callbackURLを変えてもこの画面にきたことがあったので、以下のようにいじってみましたがダメでした。
・/zaimを付与(OAuthSwiftがそうしてるので)→変わらず上記の画面
・コロン以下を無くしてみる→そもそもSafariが起動しなくなった

投稿2019/03/27 09:23

編集2019/03/28 03:09
maztak

総合スコア61

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maztak

2019/03/31 15:00 編集

ブラウザアプリを選択後、Zaim側のドキュメントに以下の文言があったので、サービスURLとcallbackURLを同じにすると認証画面にいき、無事コールバックURLが呼ばれトークンが取得できました! > If you select "Browser App", Zaim give you a permission to access only form the domain which you input the "Service URL".
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問