2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AppAuth for Androidを用いてGoogleログインを実装する

Last updated at Posted at 2022-02-01

前置き

Android端末において、Googleログインの実装方法として、よく使われているのはGoogle Play開発者サービスを利用するやり方です。しかし、Google Play開発者サービスが無効になった場合、Googleログインができなくなります。また、国や地域、メーカーによって、そもそもAndroid端末にGoogle Play開発者サービスが入っていないことがあります。

AppAuth for Androidを利用するメリット

  1. GoogleのOAuthでは、webviewをサポートしなくなりました。AppAuth for AndroidはChrome Custom Tabをサポートしているので、GoogleのOAuthを利用できます。(https://developers-jp.googleblog.com/2016/09/modernizing-oauth-interactions-in-native-apps.html)
  2. Google Play開発者サービスがいりません。
  3. 独自実装より楽です。

AppAuth for Androidの導入方法

AppAuth for Androidの使い方で基本的な使い方を解説しました。ここではGoogleログインに特化した導入方法を説明します。

Google Cloud Platformの登録

  1. Google Cloud Platformでプロジェクトを作成します。
  2. [APIとサービス]→[OAuth同意画面]に入り、OAuth 同意画面の設定をします。スコープもここで設定します。
  3. [APIとサービス]→[認証情報]に入り、[認証情報を作成]→[OAuthクライアントID]をクリックし、[アプリケーションの種類]で“Android”を選び、その他の必要な情報を設定します。
  4. 設定が終わったら、クライアントIDが表示されます。このクライアントIDはソースコードで使われます。

ライブラリの導入

appモジュールのbuild.gradleに

  1. AppAuth for Androidnet.openid:appauth
  2. JWT Decoding library for Androidcom.auth0.android:jwtdecode
    を追加します。
build.gradle
// AppAuth SDK:最新バージョンはhttps://search.maven.org/artifact/net.openid/appauth
implementation 'net.openid:appauth:0.11.1'
// For decode ID Token:最新バージョンはhttps://mvnrepository.com/artifact/com.auth0.android/jwtdecode
implementation 'com.auth0.android:jwtdecode:2.0.0'

AndroidManifest.xmlの編集

AndroidManifest.xmlに次のようにリダイレクト用のactivityを追加します。

AndroidManifest.xml
...
<activity
        android:name="net.openid.appauth.RedirectUriReceiverActivity"
        tools:node="replace">
    <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="{アプリのパッケージ名}"/>
    </intent-filter>
</activity>
...

AuthStateとAuthorizationServiceConfigurationを用意

空のAuthStateとAuthorizationServiceConfigurationを生成します。

private val appAuthState: AuthState = AuthState.jsonDeserialize("{}")
private val config = AuthorizationServiceConfiguration(
    Uri.parse("https://accounts.google.com/o/oauth2/v2/auth"),
    Uri.parse("https://www.googleapis.com/oauth2/v4/token")
)

サインイン

サインイン画面を表示

  1. AuthorizationRequestを生成します。
  2. スコープを設定します。
  3. AuthorizationServiceのgetAuthorizationRequestIntentで、サインインのIntentを作ります。
  4. startActivityForResultでサインインのIntentを起動します。
fun signIn() {
    val authorizationRequest = AuthorizationRequest
        .Builder(
            config,
            {クライアントID},
            ResponseTypeValues.CODE,
            Uri.parse({アプリのパッケジ名}:/{適当なパス})
        )
        .setScope({Google Cloud Platformで設定したスコプ。例:openid email profile})
        .build()
    val intent = AuthorizationService(context).getAuthorizationRequestIntent(authorizationRequest)
    startActivityForResult(intent, requestCode)
}

サインインの認証結果を取得

  1. onActivityResultでサインインの認証結果を受け取ります。
  2. AuthStateを更新します。

認証成功の条件
AuthorizationResponseが空ではなく、かつAuthorizationExceptionが空である

認証失敗の条件
AuthorizationResponseが空、またはAuthorizationExceptionが空ではない

fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    val authorizationResponse = AuthorizationResponse.fromIntent(data)
    val exception = AuthorizationException.fromIntent(data)
    appAuthState.update(authorizationResponse, exception)

    if (exception != null || authorizationResponse == null) {
        // 認証失敗
    } else {
        // 認証成功
    }
}

各トークンを取得

  1. AuthorizationResponseを使ってトークンを要求します。
  2. (1)のレスポンスを使ってAuthStateを更新します。
  3. AuthStateのaccessTokenにアクセストークンが入っています。
  4. AuthStateのrefreshTokenにリフレッシュトークンが入っています。
  5. AuthStateのidTokenにIDトークンが入っています。
AuthorizationService(context)
    .performTokenRequest(authorizationResponse.createTokenExchangeRequest()) { tokenResponse, authorizationException ->
        appAuthState.update(tokenResponse, authorizationException)
        tokenResponse?.let {
            // アクセストークン=appAuthState.accessToken
            // リフレッシュトークン=appAuthState.refreshToken
            // IDトークン=appAuthState.idToken
        }
    }

IDトークンをユーザー情報に変換

JWTでIDトークンを解凍したら、次のユーザー情報が取得できます。

val jwt = JWT(idToken)
// Open ID
val openId = jwt.subject
// 姓名
val name = jwt.claims["name"]?.asString()
// 姓
val familyName = jwt.claims["family_name"]?.asString()
// 名
val givenName = jwt.claims["given_name"]?.asString()
// プロフィール画像のURL
val pictureUrl = jwt.claims["picture"]?.asString()
// メールアドレス
val email = jwt.claims["email"]?.asString()
// メールアドレスは認証済みかどうか
val emailVerified = jwt.claims["email_verified"]?.asBoolean()

GitHub

AppAuthDemo(Huawei Google)

参考

AppAuth for Android
AppAuth for Androidを用いてソーシャルログインを実装する

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?