Yahoo! ID連携

Androidアプリ

  • Hybridフロー
  • Implicitフロー

Hybridフロー

AndroidのHybridフローのサンプルコードの説明をします。



ライブラリーをインポートする

Yahoo! ID連携 Android SDKを任意の場所にダウンロードして解凍してください。以下のjarファイルにはYahoo! ID連携を利用するために必要なクラスが定義されています。インポートしてご利用ください。

  • jp.co.yahoo.yconnect


AndroidManifest.xmlの設定

はじめにAndroidManifest.xmlにパーミッションとintent-filterを設定します。

まずはアプリケーションでネットワークソケットのパーミッションを設定します。

AndroidManifest.xml
...
‹uses-permission android:name="android.permission.INTERNET"›‹/uses-permission›
... 

次にコールバックURLを処理するためのintent-filterを設定します。

Manifest.xml
...
‹activity
android:name="jp.co.yahoo.yconnect.sample.YConnectHybridActivity"
android:label="@string/app_name"
android:exported="true"
android:launchMode="singleTask" ›
    ‹intent-filter›
        ‹action android:name="android.intent.action.VIEW" /›
        ‹category android:name="android.intent.category.DEFAULT" /›
        ‹category android:name="android.intent.category.BROWSABLE" /›
        ‹data android:scheme="yj-xxxxx" /›
    ‹/intent-filter>
‹/activity>
...

今回はひとつのActivityでブラウザーの起動とコールバックURLの受け取りをするのでsingleTaskにしています。

android:launchMode="singleTask"

Activityを起動するためのschemeを指定します。
このschemeはClient ID登録時に発行されるカスタムURIスキーム「yj-xxxxx」を指定してください。
(カスタムURIスキームはアプリケーションの管理から変更可能です)

‹data android:scheme="yj-xxxxx" /›


Authorizationエンドポイントにリクエストして同意画面を表示する

YConnectHybridクラスにはHybridフローで必要なメソッドがすべて実装されています。
YConnectHybridクラスを使ってブラウザーを起動して同意画面を表示させます。

YConnectHybridクラス

メソッド 説明
public static YConnectHybrid getInstance() シングルトンパターンのインスタンスを取得する。
public void init(String clientId, String redirectUri, String state, String display, String[] prompt, String[] scope, String nonce, String bail, String maxAge) 各パラメーターを設定する。
public void requestAuthorization(Activity activity) ブラウザーを起動して同意画面を表示する。

OIDCDisplayクラス

定数フィールド値 説明
public static final String PAGEパソコン版のテンプレートを表示するための定数。
public static final String TOUCHスマートフォン版のテンプレートを表示するための定数。
public static final String AUTO User Agentから自動判定でテンプレートを出し分け表示するための定数。
public static final String INAPPネイティブアプリ版のテンプレートを表示するための定数。

OIDCPromptクラス

定数フィールド値 説明
public static final String DEFAULTユーザーの認証、認可のための定数。
public static final String LOGINユーザーの再認証のための定数。
public static final String SELECT_ACCOUNTユーザーの再認証(ID切り替え)のための定数。
public static final String NONE同意画面非表示のための定数。(ログイン状態でなかった場合、
過去に同意済みでなかった場合はエラーが返却されます)
public static final String CONSENT同意画面強制表示のための定数。

OIDCScopeクラス

定数フィールド値 説明
public static final String OPENIDユーザー識別子を取得するための定数。
public static final String PROFILE姓名・生年・性別を取得するための定数。
public static final String EMAILメールアドレスと確認済みフラグを取得するための定数。
public static final String ADDRESSユーザー登録住所情報を取得するための定数。
YConnectHybridActivity.java
..
// Client ID
public final static String clientId = "YOUR_APPLICATION_ID";
//1を指定した場合、同意キャンセル時にredirect_uri設定先へ遷移する
public final static String BAIL = "1";
//最大認証経過時間
public final static String MAX_AGE = "3600";
public final static String customUriScheme = "yj-example:/";
...
// YConnectインスタンス取得
YConnectHybrid yconnect = YConnectHybrid.getInstance();
...
// 各パラメーター初期化
// リクエストとコールバック間の検証用のランダムな文字列を指定してください
String state = "44GC44GC54Sh5oOF";
// リプレイアタック対策のランダムな文字列を指定してください
String nonce = "U0FNTCBpcyBEZWFkLg==";
String display = OIDCDisplay.TOUCH;
String[] prompt = { OIDCPrompt.DEFAULT };
String[] scope = { OIDCScope.OPENID, OIDCScope.PROFILE,
OIDCScope.EMAIL, OIDCScope.ADDRESS };
...
// 各パラメーターを設定
yconnect.init(clientId, customUriScheme, state, display, prompt, scope, nonce, BAIL, MAX_AGE);
// Authorizationエンドポイントにリクエスト
// (ブラウザーを起動して同意画面を表示)
yconnect.requestAuthorization(this);
... 

実際の開発の際にはstate、nonceは固定の文字列ではなく、認証サーバーを用意して認証サーバーから独自の仕様で生成したランダムな文字列のstateとnonceを受け取ってデータベースなどに保存してください。stateはAuthorizationエンドポイントからのコールバックURL受け取り時と認証サーバーへの認可コード連携時に、nonceはID Token復号時の検証に必要です。

各パラメーター値の詳細についてはAuthorizationエンドポイントを参照してください。



コールバックURLを受け取り、認可コード、Access Token、ID Tokenを抽出する

同意後に返されるコールバックURLをActivityで受け取り、Access Tokenなどを抽出します。

YConnectHybridクラス

メソッド 説明
public void parseAuthorizationResponse(Uri uri, String callBackUrl, String state)コールバックURLのフラグメントに付加されたパラメーターを抽出する。
public String getAuthorizationCode()認可コードを取得する。
public String getAccessToken()Access Tokenを取得する。
public long getAccessTokenExpiration()Access Tokenの有効期限を取得する。
public String getIdToken()ID Tokenを取得する。
YConnectHybridActivity.java
...
Intent intent = getIntent();
 
if(Intent.ACTION_VIEW.equals(intent.getAction())) {
    ...
    // コールバックURLから各パラメーターを抽出
    Uri uri = intent.getData();
    yconnect.parseAuthorizationResponse(uri, customUriScheme, state);
    // 認可コード、Access Token、ID Tokenを取得
    String code = yconnect.getAuthorizationCode();
    String accessTokenString = yconnect.getAccessToken();
    String idTokenString = yconnect.getIdToken();
    ...
}
... 


取得した認可コードを認証サーバに連携する

認証サーバー側に認可コードとstateを渡し、認証サーバはTokenエンドポイントにリクエストしてAccess Token/Refresh Token/ID Tokenを発行します。

YConnectHybridAsyncTask.java
...
//認証サーバー側にcodeとstateを渡すURLを作成してください
String urlSt = "https://example.com/auth.php?code=" + code + "&state=" + state;
URL url = new URL(urlSt);
/*
 * webviewを起動して認証サーバに送信してください
 */
... 


ID Tokenを検証してユーザー識別子を取得する

オプションでレスポンスタイプにID Tokenを指定した場合、ID Tokenの暗号化された文字列が返されます。
この文字列を復号、検証し、ユーザー識別子やID Tokenの発行元などの情報を取得します。

YConnectHybridクラス

メソッド 説明
public boolean verifyIdToken(String idTokenString, String clientId, String nonce, String authorizationCode, String accessToken, String maxAge)ID Token、Access Token、認可コードが異常でないか検証する。
public IdTokenObject getIdTokenObject()復号されたID Tokenをオブジェクトとして取得する。

非同期通信をするためメインスレッドとは別スレッドで実装する必要があります。
今回は簡易的なスレッドとしてAsyncTaskを継承したサブクラスでリクエストします。

YConnectExplicitAsyncTask.java
...
// ID Tokenの検証
yconnect.verifyIdToken(idTokenString, clientId, nonce, code, accessTokenString, maxAge);
// 復号されたID Token情報を取得
final IdTokenObject idtokenObject = yconnect.getIdTokenObject();
// ID Token情報からユーザー識別子を取得
String sub = idtokenObject.getSub();
...

復号されたID Tokenはオブジェクト(JavaBeans形式)として返されます。各パラメーターはID Tokenオブジェクトのプロパティーに保持されているので、必要に応じてgetterで取り出して利用してください。



UserInfo APIにリクエストしてユーザー識別子を取得する

Access Tokenを用いてユーザー識別子などを取得します。

YConnectHybridクラス

メソッド 説明
public void requestUserInfo(String accessTokenString)UserInfo APIにリクエストする。
public UserInfoObject getUserInfoObject()UserInfoオブジェクトを取得する。

非同期通信をするためメインスレッドとは別スレッドで実装する必要があります。
今回は簡易的なスレッドとしてAsyncTaskを継承したサブクラスでリクエストします。

YConnectHybridAsyncTask.java
...
// UserInfo APIにリクエスト
yconnect.requestUserInfo(storedAccessToken);
// UserInfo情報を取得
final UserInfoObject userInfoObject = yconnect.getUserInfoObject();
// UserInfo情報からユーザー識別子を取得
String sub = userInfoObject.getSub();
...

userInfoObjectはオブジェクト(JavaBeans形式)として返されます。各パラメーターはUserInfoオブジェクトのプロパティーに保持されているので、必要に応じてgetterで取り出して利用してください。



Access Tokenなどの保存について

Access Token、ID Token、UserInfo情報の保存は、悪意のある外部アプリケーションから盗みとられないように注意が必要です。
取得したトークンやユーザー情報を保存する場合には、適宜暗号化や難読化し外部から読み取られないようにしてください。



Yahoo!知恵袋で調べる