Yahoo! ID連携 v2 iOS SDK
stable版は提供終了を予定していますので、最新版をご利用ください。
【Yahoo! ID連携】stable版iOS SDK、Android SDK提供終了についてのお知らせ
Hybridフロー
iOSのHybridフローのサンプルコードの説明をします。
-
サポートOS
- iOS 14以上
- SDK&サンプルコード
ライブラリーをプロジェクトに追加する
Yahoo! ID連携 iOS SDKを任意の場所にダウンロードして解凍してください。
解凍後、YConnectSDK.xcodeprojをアプリケーションのプロジェクトに追加してください。詳細な手順を下記に示します。
XCodeでアプリケーションのプロジェクトを開いてください。
XCodeのメニューから"File" > "Add Files To <プロジェクト名>"を選択してください。
解凍したYahoo! ID連携 iOS SDK内のYConnect.xcodeprojを選択し、"Add"してください。
プロジェクトの設定
はじめにYahoo! ID連携 iOS SDKを利用するためにプロジェクトの設定を行います。
まずはビルドターゲットの"Build Phase"を開き、"Link Binary With Libraries"の"+"ボタンを押してください。
ダイアログが表示されるので、WorkspaceからlibYConnect.aを選択し、"Add"してください。
続いてYahoo! ID連携 iOS SDK内のヘッダファイルをimportするために設定を行います。
ビルドターゲットの"Build Settings"を開き、設定項目中の"Header Search Paths"にYahoo! ID連携 iOS SDKのパスを追加します。
最後にコールバックURLを設定します。
ビルドターゲットの"Info"を開き、"URL Types"を展開してください。
"+"ボタンを押すと入力フォームが表示されるので、"identifier"に一意な値を、
"URL schemes"にはこのschemeはClient ID登録時に発行されるカスタムURIスキーム「yj-xxxxx」を指定してください。
"Identifier"に指定する値は"Bundle identifier"と同じ値が推奨されています。
また、カスタムURIスキームはアプリケーションの管理から変更可能です。
Privacy Manifestsに項目を追加する
Yahoo! ID連携 iOS SDKは静的ライブラリのため、アプリのPrivacyInfo.xcprivacyファイルの"Privacy Nutrition Label Types"に、以下の内容を追加する必要があります。
Collected Data Type | Linked to User | Used for Tracking | Collection Purposes |
---|---|---|---|
Email Address | YES | NO | App Functionality |
Phone Number | YES | NO | App Functionality |
User ID | YES | NO | App Functionality |
Swiftアプリケーションで使用する場合の設定
Yahoo! ID連携 iOS SDKはObjective-Cコードのため、Swiftアプリケーションで使用する場合にはプロジェクトにBridging Headerファイルを追加する必要があります。
Bridging Headerファイルがプロジェクトに追加されていない場合は、以下の手順で追加を行なってください。
- XCodeのメニューから"File" > "New" > "File"を選択してください。
- "Header File"を選択してください。
- ファイル名を"Bridging-Header.h"とし、"Create"してください。
続いてBridging Headerファイルを使用するための設定を行います。
ビルドターゲットの"Build Settings"を開き、"Swift Compiler"の"Objective-C Bridging Header"にBridging Headerファイルのパスを追加します。
Bridging HeaderファイルにはYahoo! ID連携 iOS SDKのヘッダファイルをimportするコードを追加してください。
Bridging-Header.h
#ifndef Bridging_Header_h
#define Bridging_Header_h
#import "YConnect.h"
#endif /* Bridging_Header.h */
設定の初期化をする
Info.plistにClient ID, コールバックURL, レスポンスタイプ, スコープ(複数ある場合はスペース区切り)を記載してください
plistに記載するキーと値の内訳は下記のとおりです。
Key Type 説明 入力例 YConnectClientId String Client IDを指定します。 dj00zaiZpPXNYeG5tRXJVVlLzPuW
NMvbnN1bWVyc2VjcmV0Jng9ZWU-YConnectRedirectUri String Client ID発行時に登録したコールバックURIを指定します。 yj-xxxxx:/
YConnectDisplay String ログイン画面、同意画面のテンプレートの種類を指定する場合に利用します。 touch
※任意のパラメーターです。YConnectResponseType String 「code id_token」「code token」「code id_token token」のいずれかを指定してください。 code%20id_token
※URLエンコードが必要です。YConnectScope String UserInfo APIから取得できる属性情報を指定できます。 openid address
YConnectBail Boolean YESにすると同意画面で「同意しない」ボタンをクリックした際にcodeパラメーターを付加せずにredirect_uriへリダイレクトさせます。指定しない場合はYahoo!トップへ遷移します。 YES
※任意のパラメーターです。YConnectMaxAge Number 最大認証経過時間を指定します。指定された秒数よりも認証日時が経過していた場合は再認証が必要です。 3600
※任意のパラメーターです。
Authorizationエンドポイントにリクエストして同意画面を表示する
YConnectManagerクラスにはHybridフローで必要なメソッドがすべて実装されています。
YConnectManagerクラスを使って、アプリ内ブラウザタブであるASWebAuthenticationSession、SFAuthenticationSessionもしくはSFSafariViewControllerに同意画面を表示させます。
なお、サンプルコードはStoryboardを使用しています。
YConnectManagerクラス
メソッド | 説明 |
---|---|
+ (instancetype)sharedInstance | シングルトンパターンのインスタンスを取得する。 |
- (NSURL *)generateAuthorizationUriWithState:(NSString *)state prompt:(NSString *)prompt nonce:(NSString *)nonce | 同意画面のURLを取得する。 |
- (void)requestAuthorizationWithState:(NSString *)state prompt:(NSString *)prompt nonce:(NSString *)nonce presentingViewController:(UIViewController *)presentingViewController API_AVAILABLE(ios(9.0)) | ASWebAuthenticationSession、SFAuthenticationSession、もしくはSFSafariViewControllerで同意画面を表示する。 ※iOS9〜iOS10をサポート対象に含める場合は必ずこちらを利用してください。 |
- (void)requestAuthorizationWithState:(NSString *)state prompt:(NSString *)prompt nonce:(NSString *)nonce handler:(YConnectAuthorizationEndpointResponseHandler)handler API_AVAILABLE(ios(11.0)) | ASWebAuthenticationSession、SFAuthenticationSessionで同意画面を表示する。 ログイン成功時は自動でコールバックURLのフラグメントに付加されたパラメーターを抽出する。 ※iOS9〜iOS10をサポート対象に含めず、iOS11以上をサポート対象とする場合はこちらの利用を推奨します。 |
OIDCPromptクラス
定数フィールド値 | 説明 |
---|---|
YConnectConfigPromptConsent | ユーザーの再認可のための定数です。 |
YConnectConfigPromptLogin | ユーザーの再認証のための定数です。 |
YConnectConfigPromptNone | 同意画面非表示のための定数です。(ログイン状態でなかった場合、過去に同意済みでなかった場合はエラーが返却されます) |
YConnectConfigPromptSelectAccount | ID切り替え画面を強制表示するための定数です。 |
MainViewController.swift
@IBAction func login(_ sender: UIButton) {
getStateAndNonce(callback: { (state, nonce, error) in
// エラーハンドリング
if let error = error {
...
return
}
let yconnect = YConnectManager.sharedInstance()
if #available(iOS 11.0, *) {
// iOS11以上をサポートする場合はハンドラありのメソッドを使用します
yconnect?.requestAuthorization(withState: state, prompt: nil, nonce: nonce, handler: { (error) in
// エラーハンドリング
if let error = error {
...
return
}
self.performSegue(withIdentifier: "ToResultPage", sender: nil)
})
} else if #available(iOS 9.0, *) {
// iOS9〜iOS10をサポートする場合はハンドラなしのメソッドを使用します
// レスポンスパラメータを取得するにはAppDelegate内にparseAuthorizationResponseの処理を記述する必要があります
yconnect?.requestAuthorization(withState: state, prompt: nil, nonce: nonce, presenting: self)
}
})
}
private func getStateAndNonce(callback: (String?, String?, Error?) -> Void) -> Void {
// state, nonceの取得(認証サーバー側にstateとnonceを発行するための任意のURLを用意してください)
let url = NSURL(string: "https://example.com/issue.php")
var state: String?
var nonce: String?
do {
let jsonData = try Data(contentsOf: url! as URL)
let json = try JSONSerialization.jsonObject(with: jsonData) as! Dictionary<String, Any>
state = json["state"] as? String
nonce = json["nonce"] as? String
// エラーハンドリング
guard let state = state, let nonce = nonce else {
...
return
}
callback(state, nonce, nil)
} catch {
// エラーハンドリング
...
return
}
}
認証サーバー側で発行するstateとnonceは独自の仕様でランダムな文字列を生成してデータベースなどに保存してください。
stateはAuthorizationエンドポイントからのコールバックURL受取時と認証サーバーへの認可コード連携時に、nonceはIDトークンを復号時の検証に必要です。
各パラメーター値の詳細についてはAuthorizationエンドポイントを参照してください。
サンプルでは各パラメーターを乗せたURLにリクエストしています。
コールバックURLを受け取り、認可コード、Access Token、ID Tokenを抽出する
iOS9〜iOS10をサポート対象に含める場合は、AppDelegateでコールバックURLを受け取るための実装が必要です。
同意後に返されるコールバックURLをAppDelegateで受け取り、"parseAuthorizationResponse"メソッドを用いてAccess Tokenなどを抽出します。
YConnectManagerクラス
メソッド | 説明 |
---|---|
- (void)parseAuthorizationResponse:(NSURL *)uri handler:(YConnectAuthorizationEndpointResponseHandler)handler | コールバックURLのフラグメントに付加 されたパラメーターを抽出する。 |
- (void)fetchAccessToken:(NSString *)code handler:(YConnectTokenEndpointResponseHandler)handler | 認可コードを用いてAccess Tokenを 取得する。 |
- (NSString *)accessTokenString | Access Tokenを取得する。 |
- (NSInteger)accessTokenExpiration | Access Tokenの有効期限を取得する。 |
- (NSString *)hybridIdTokenString | ID Tokenを取得する。 |
AppDelegate.swift
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
//コールバックURLに指定したURLだった場合、最初のViewControllerから結果を表示するResultViewControllerに遷移する
if url.scheme == "yj-xxxx" {
let yconnect = YConnectManager.sharedInstance()
yconnect?.parseAuthorizationResponse(url, handler: { (error) in
// エラーハンドリング
if let error = error {
...
return false
}
yconnect?.fetchAccessToken(yconnect?.authorizationCode, handler: { (retAccessToken, error) in
// エラーハンドリング
if let error = error {
...
return false
}
// Access Token、ID Tokenを取得
let accessToken = yconnect?.accessTokenString()
let idToken = yconnect?.hybridIdTokenString()
})
let viewController = self.window?.rootViewController?.children[0]
viewController?.dismiss(animated: true, completion: nil)
viewController?.performSegue(withIdentifier: "ToResultPage", sender: viewController)
})
return true
}
return false
}
iOS9〜iOS10をサポート対象に含めず、iOS11以上のみをサポート対象とする場合はAppDelegateに追加の実装は必要ありません。
ハンドラありの"requestAuthorization"メソッド内で"parseAuthorizationResponse"メソッドが実行されるため、正常終了時は任意のタイミングでAccess Tokenなどの取得が可能です。
MainViewController.swift
if #available(iOS 11.0, *) {
// iOS11以上をサポートする場合はハンドラありのメソッドを使用します
yconnect?.requestAuthorization(withState: state, prompt: nil, nonce: nonce, handler: { (error) in
// エラーハンドリング
if let error = error {
...
return
}
// Access Token、ID Tokenを取得
let accessToken = yconnect?.accessTokenString()
let idToken = yconnect?.hybridIdTokenString()
})
}
取得した認可コードを認証サーバに連携する
認証サーバー側に認可コードとstateを渡し、認証サーバはTokenエンドポイントにリクエストしてAccess Token/Refresh Token/ID Tokenを発行します。
LoggedInResultViewController.swift
// コールバックURLから各パラメータを抽出
let yconnect = YConnectManager.sharedInstance()
// 認証サーバー側にcodeとstateを渡すURLを作成してください
guard let authorizationCode = yconnect?.authorizationCode, let state = yconnect?.state else {
// エラーハンドリング
...
return
}
let url = NSURL(string: "http://example.com/auth.php?code=\(authorizationCode)&state=\(state)")
/*
* WebViewを起動して認証サーバに送信してください
*/
取得したID Tokenを検証した上でユーザー識別子を取得する
オプションでレスポンスタイプにID Tokenを指定した場合、ID Tokenの暗号化された文字列が返されます。
この文字列をクライアント側で検証し、ユーザー識別子やID Tokenの発行元などの情報を取得します。
LoggedInResultViewController.swift
{
...
// コールバックURLから各パラメータを抽出
let yconnect = YConnectManager.sharedInstance()
/** IDトークンの検証が必要です
*
* 検証手順については下記リンク先の「ID Tokenの検証手順」をご参照ください
* https://developer.yahoo.co.jp/yconnect/v2/id_token.html
*
* 検証に必要な公開鍵は以下から取得が可能です
**/
self.getDataFrom(url: YConnectConfigV2PublicKeysEndpoint, callback: { (publicKey, error) in
// エラーハンドリング
if let error = error {
...
return
}
// エラーハンドリング
guard let publicKey = publicKey else {
...
return
}
let data = publicKey.data(using: String.Encoding.utf8)
do {
let json = try JSONSerialization.jsonObject(with: data!) as! Dictionary<String, Any>
} catch {
// エラーハンドリング
...
return
}
// 検証済みのIDトークンを利用する
let idTokenObject: YConnectIdTokenObject = (yconnect?.idTokenObject!)!
})
}
private func getDataFrom(url: String, callback: @escaping (String?, Error?) -> Void)
{
let request = NSURLRequest(url: URL(string: url)!)
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration)
let task = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) in
if let httpResponse = response as? HTTPURLResponse {
// エラーハンドリング
if httpResponse.statusCode != 200 {
callback(nil, error)
return
}
// エラーハンドリング
guard let data = data else {
callback(nil, error)
return
}
let responseData: String? = String(data: data, encoding: String.Encoding.utf8)
callback(responseData, nil)
}
})
task.resume()
}
各パラメーターはID Tokenオブジェクトのプロパティーに保持されているので、必要に応じて取り出して利用してください。
UserInfo APIにリクエストしてユーザー識別子を取得する
Access Tokenを用いてユーザー識別子などを取得します。
YConnectManagerクラス
メソッド | 説明 |
---|---|
- (void)fetchUserInfo:(NSString *)accessTokenString handler:(YConnectUserInfoEndpointResponseHandler)handler | UserInfo APIにリクエストする。 |
LoggedInResultViewController.swift
// UserInfo情報を取得
private func fetchUserInfo()
{
let yconnect = YConnectManager.sharedInstance()
let accessToken = yconnect?.accessTokenString()
// Access Tokenが空
guard (accessToken != nil) else {
...
return
}
yconnect?.fetchUserInfo(accessToken, handler: { (userInfoObject, error) in
// エラーハンドリング
if let error = error {
...
return
}
// UserInfo情報からユーザー識別子を取得
let userid = yconnect?.userInfoObject.sub
})
}
Access Tokenを更新する
Refresh Tokenをつかって有効期限切れのAccess Tokenを更新します。
YConnectManagerクラス
メソッド | 説明 |
---|---|
- (void)refreshAccessToken:(NSString *)refreshToken handler:(YConnectTokenEndpointResponseHandler)handler | Access Tokenを更新する |
LoggedInResultViewController.swift
yconnect?.refreshAccessToken(yconnect?.refreshTokenString(), handler: { (accessToken, error) in
if /* エラーレスポンスが"Invalid_Token"であるかチェック */ {
// 再度認証を行う必要があります
}
// 更新に成功したAccess Tokenを利用できます
...
})
Access Tokenなどの保存について
Access Token、ID Token、UserInfo情報の保存は、悪意のある外部アプリケーションから盗みとられないように注意が必要です。 取得したトークンやユーザー情報を保存する場合には、適宜暗号化や難読化し外部から読み取られないようにしてください。
ログインボタンの指定と追加
Yahoo! ID連携 iOS SDK内の"YConnectAssets.xcassets"に含まれているログインボタンは、デフォルト画像としてアプリケーション内で使用できます。
"YConnectAssets.xcassets"には以下の4種類のログインボタンがデフォルト画像として用意されています。
さらにログインボタンをアレンジする場合は、Yahoo! JAPAN IDログインボタン デザインガイドラインに沿って利用してください。
画像名 | YConnectLoginButtonImageクラスのメソッド名 | 表示されるログインボタン |
---|---|---|
yconnect_button_square | + (UIImage *)squareImage | |
yconnect_button_square_inverse | + (UIImage *)squareInverseImage | |
yconnect_button_circle | + (UIImage *)circleImage | |
yconnect_button_circle_inverse | + (UIImage *)circleInverseImage |
デフォルトのログインボタンを使用するには、"YConnectAssets.xcassets"をプロジェクトに追加する必要があります。
まず、ビルドターゲットの"Build Phases"を開き、"Copy Bundle Resources"の"+"ボタンを押してください。
ダイアログが表示されるので、"Add Other..."から"YConnectAssets.xcassets"を"Open"してください。
以下ように"Copy Bundle Resources"に"YConnectAssets.acassets"が追加されていることを確認できたら完了です。
Storyboard上での指定方法
Storyboard上でログインボタンとして使用したい"Button"を選択し、"Attributes Inspector"の"Image"から任意の画像名を指定してください。
コード上での指定方法
ログインボタンとして使用したい"UIButton"インスタンスに対し、
以下のように"YConnectLoginButtonImage"クラスのメソッドを使用して任意の画像を指定してください。
MainViewController.swift
@IBOutlet weak var loginButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// 表示させたいログインボタンを指定してください
loginButton.setImage(YConnectLoginButtonImage.squareImage(), for: UIControl.State.normal)
}
Yahoo! ID連携 v2
- Yahoo! ID連携とは
- ガイドラインを確認する
- Yahoo! JAPAN IDを取得する
- Client IDを登録する
- 各種フロー
-
ネイティブアプリを開発
- iOSアプリ
- Androidアプリ
- 属性取得API(UserInfoAPI)
- ID Token
- JavaScript SDK
- PHP SDK
- Java SDK
- デザインガイドライン
- APIアクセス実装方法
- Yahoo! ID連携用語集
- FAQ