はじめまして。
SwiftもTeratailも使い始めて日が浅く、分かる方からしたらくだらない質問かとは思いますが、お時間のあるどなたかがお答えくださることを願っております。よろしくお願いいたします。
前提・実現したいこと
Xcode12.3でiOS向けのSpotifyプレイリスト自動生成アプリを作っています。
ユーザーからプレイリスト作成権限を得るために、Safariと連携したOAuth2.0認証(PKCEは不使用)を実装しようとしています。その際に、OAuthSwiftの最新版(2.1.2)を使っています。
このOAuth認証が動きません。OAuth認証を正常に動作させたく質問しました。
発生している問題・エラーメッセージ
Safariと連携してのOAuth2.0認証(PKCEは不使用)がうまく動きません。
具体的には、後に掲載しているソースコードで実機ビルド(iPhone8, iOS14.3)をしたときに以下のように動作しています。
1.ボタン(clickButton)を押すと、Safari画面が表示され、そこではfacebook, apple, googleによるログインもしくはユーザー名とパスワードの直接入力によるログインのためのボタンが用意されている。
また、この時点でXcode側のデバッガーには下記のメッセージが出ている。
success3 <OAuthSwift.SafariURLHandler: 0x283fc8500> success1 success2 Safari presented
2.いずれのログイン方法も、ボタン(「Facebookで続ける」ボタン等)を押してもうまくいかない。
具体的には下記のようになる。
- appleで続けるボタン→iPhone上でappleIDと連携した指紋認証が行われ、Spotifyにログインはされるものの、Safariの画面が白くなり停止
- それ以外のボタン →何の反応も起きず、画面も上に掲載したままに留まる
なお、いずれの場合もXcodeのデバッガーに新規情報は入らない。
[追記]
ログインボタンを押した際の上記の反応は、実機上でのものでしたが、
エミュレーターでビルドしたところ、「Facebookで続ける」ボタンではユーザー名とパスワードを入れた後、下記の画面で終わってしまいました。
該当のソースコード
ソースコードは下記のとおりです。ネット上のOAuthSwiftの様々な実装例を参考にしており、類似点があることをご容赦下さい。
consumerKeyおよびconsumerSecretは一旦非表示とさせていただきますが、こちらは記入ミスがないことを既に確かめております。
Swift
1import UIKit 2import OAuthSwift 3 4struct Const { 5 static let consumerKey = "XX" 6 static let consumerSecret = "XX" 7} 8 9class ViewController: UIViewController { 10 11 var oauthswift: OAuthSwift? 12 13 override func viewDidLoad() { 14 super.viewDidLoad() 15 } 16 17 18 @IBAction func clickButton(_ sender: UIButton) { 19 doOAuthSpotify() 20 } 21 22 /// OAuth2ログイン処理 23 func doOAuthSpotify(){ 24 25 let oauthswift = OAuth2Swift( 26 consumerKey: Const.consumerKey, 27 consumerSecret: Const.consumerSecret, 28 authorizeUrl: "https://accounts.spotify.com/authorize", 29 accessTokenUrl: "https://accounts.spotify.com/api/token", 30 responseType: "code" 31 ) 32 self.oauthswift = oauthswift 33 oauthswift.authorizeURLHandler = getURLHandler() 34 35 print("success1") //for debug 36 let state = generateState(withLength: 20) 37 print("success2") //for debug 38 39 // コールバック処理 40 oauthswift.authorize(withCallbackURL: URL(string: "PlaylistMaker://")!, scope: "playlist-modify-private", state: state) 41 {result in 42 print("callback") //for debug 43 switch result { 44 case .success(let (credential, response, parameters)): 45 print(credential.oauthToken) 46 self.showAlert(credential: credential) 47 print("success") 48 case .failure(let error): 49 print(error.localizedDescription) 50 print("failure") 51 } 52 } 53 } 54 55 /// ログイン画面起動に必要な処理 56 /// 57 /// - Returns: OAuthSwiftURLHandlerType 58 func getURLHandler() -> OAuthSwiftURLHandlerType { 59 if #available(iOS 11.0, *) { 60 let handler = SafariURLHandler(viewController: self, oauthSwift: self.oauthswift!) 61 handler.presentCompletion = { 62 print("Safari presented") 63 } 64 handler.dismissCompletion = { 65 print("Safari dismissed") 66 } 67 print("success3") //for debug 68 print(handler) //for debug 69 return handler 70 } 71 print("OS has to be updated as later than iOS 10.0") 72 return OAuthSwiftOpenURLExternally.sharedInstance 73 } 74 75 /// アラート表示 76 /// 77 /// - Parameter credential: OAuthSwiftCredential 78 func showAlert(credential: OAuthSwiftCredential) { 79 var message = "oauth_token:(credential.oauthToken)" 80 if !credential.oauthTokenSecret.isEmpty { 81 message += "\n\noauth_token_secret:(credential.oauthTokenSecret)" 82 } 83 let alert = UIAlertController(title: "ログイン", 84 message: message, 85 preferredStyle: UIAlertController.Style.alert) 86 alert.addAction(UIAlertAction(title: "OK", 87 style: UIAlertAction.Style.default, handler: nil)) 88 self.present(alert, animated: true, completion: nil) 89 } 90} 91
試したこと
redirect URIの問題かと思い、Spotify側で設定しているものと違った文字列をあえてcallbackで設定した際はInvalid URIエラーが実機で確認できました。現在は正しいURIを使用しており、そこに問題はないようです。
素人考えではありますが、callback処理がなぜ始まらないのかという点に尽きるのかと考えております。しかしそれが様々に調べてみるもののわからず質問させていただきました。
あなたの回答
tips
プレビュー