WEBサイト制作・アプリ開発・システム開発・ブランディングデザイン制作に関するご相談はお気軽にご連絡ください。
構想段階からじっくりとヒアリングし、お客様の課題にあわせたアプローチ手法でお客様の“欲しかった”をカタチにしてご提案いたします。
Blog スタッフブログ
iOS
PHP
Swift
システム開発
[Swift]AuthenticationServicesでoAuth認証を実装してみた
こんにちは、株式会社MIXシステム開発担当のBloomです。
早速本題のAuthenticationServicesでoAuth認証を実装する手順について、
お仕事の中で得た知見を共有させていただきたいと思います。
AuthenticationServicesとは
AuthenticationServicesフレームワークは主に認証情報を入力しログインをする際の操作をサポートしてくれます。
Sign in with Appleの実装に主に使われています(当社比)が、Web上で行うoAuth認証にアプリからアクセスする際、コールバックでトークンを受け取りたい場合に利用することができます。
今回は例として実際にLINEログインを実装して動作を見てみましょう。
※LINEログインはiOS版SDKも公開されているため、実際は他のアプリネイティブSDKを提供していないoAuth認証サービスで利用してください。
Web側コールバックAPI実装
LINE Developersへの登録は割愛させていただきます。今回は審査不要なprofileスコープのみのリクエストとします。
<?php
if (isset($_REQUEST['code'])) {
$code = $_REQUEST['code'];
$result = getToken($code);
$res_array = json_decode($result);
// アプリ側で設定するコールバックスキームをプロトコルに指定
$uri = "sandbox://auth?token=".$res_array->access_token;
echo <<< EOM
<!DOCTYPE html>
<html>
<head><meta charset="utf-8">
<script type="text/javascript">
window.onload = function(){
// 直接アプリ側で設定するコールバックスキームへリダイレクト
location.href= "{$uri}";
}
</script>
</head>
<body>
// 直接コールバックさせなくてもリンク押下で遷移もできます。
<a href="{$uri}">ログイン</a>
</body></html>
EOM;
}
// curlでアクセストークンを取得
function getToken($code) {
$header_array = array(
"Content-Type: application/x-www-form-urlencoded"
);
$data_array =
array("grant_type" => "authorization_code",
"code" => $code,
"redirect_uri" => "[LINE Developersコンソールで指定したリダイレクトURI]",
"client_id" => "[LINE Developersコンソールで確認できるチャネルID]",
"client_secret" => "[LINE Developersコンソールで確認できるチャネルシークレット]"
);
$data = http_build_query($data_array , "" , "&");
$curl = curl_init();
curl_setopt($curl , CURLOPT_HTTPHEADER , $header_array);
curl_setopt($curl , CURLOPT_URL , "https://api.line.me/oauth2/v2.1/token");
curl_setopt($curl , CURLOPT_RETURNTRANSFER , 1);
curl_setopt($curl , CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_1_1);
curl_setopt($curl , CURLOPT_CUSTOMREQUEST , 'POST');
curl_setopt($curl , CURLOPT_POSTFIELDS , $data);
$result = curl_exec($curl);
if(curl_errno($curl)){
$error = curl_error($curl);
var_dump($error);
}
curl_close($curl);
return $result;
}
?>
iOS側実装
import AuthenticationServices
class ViewController: UIViewController {
@IBOutlet weak var tokenLabel: UILabel!
// 今回はログインボタンの押下に反応してログインさせます
@IBAction func login(_ sender: Any) {
let endpoint = "https://access.line.me/oauth2/v2.1/authorize?"
let response_type = "code"
let client_id = "[LINE Developersコンソールで確認できるチャネルID]"
let redirect_uri = "[LINE Developersコンソールで設定したリダイレクトURI]".addingPercentEncoding(withAllowedCharacters: .alphanumerics)!
let state = "[CSRF対策のランダム文字]"
let scope = "profile"
let urlString = "\(endpoint)response_type=\(response_type)&client_id=\(client_id)&redirect_uri=\(redirect_uri)&state=\(state)&scope=\(scope)"
let url = URL(string: urlString)!
let session = ASWebAuthenticationSession(url: url,
callbackURLScheme: "sandbox") { callbackURL, error in
if error != nil {
print(error.debugDescription)
}
if callbackURL != nil {
let queryItems = URLComponents(string: callbackURL!.absoluteString)?.queryItems
let token = queryItems?.filter( {$0.name == "token"} ).first?.value ?? ""
print(token)
if !token.isEmpty {
self.tokenLabel.text = "アクセストークンを取得できました"
}
}
}
// prefersEphemeralWebBrowserSessionで前回入力を引き継ぐかどうか指定可能です。
session.prefersEphemeralWebBrowserSession = false
session.presentationContextProvider = self
// ブラウザ起動
session.start()
}
}
extension ViewController: ASWebAuthenticationPresentationContextProviding {
func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
return self.view.window!
}
}
実行結果
これで簡単にoAuth認証のアクセストークンの取得ができました。良かったですね。