この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
テントの中から失礼します、IoT 事業部のてんとタカハシです!
Android アプリ開発も Auth0 も Kotlin も初心者なのですが、これらを使ってユニバーサルログインをアプリに組み込む機会がありましたので、手順を残しておこうと思います。
基本的には Auth0 公式のクイックスタートを参考にすれば何となく実装できそうなのですが、初心者の私はそこそこ躓きました。同じような初心者の方にとって参考になれば嬉しいです。
環境
- macOS Catalina v10.15.7
- Android Studio 4.2.1
参考
主に Auth0 公式のクイックスタートを参考にしました。
Android プロジェクトを作成する
Empty Activity
を選択します。
プロジェクト名はsample-auth0-login
としています。Auth0 を使用する場合は、Android の API レベルを 21 以上に設定する必要があることに注意してください。
Android API version 21 or newer is required.
Auth0 Docs > Auth0 Libraries > Auth0.Android
Auth0 アプリケーションを作成する
アプリケーション名はsample-auth0-login
としています。アプリケーションタイプはNative
を選択します。
作成したアプリケーションの Settings タブを開くと、ドメイン名とクライアント ID が表示されます。この2つは後ほどログイン画面実装時に使用します。
下にスクロールして、Allowed Callback URLs と Allowed Logout URLs を設定します。
どちらもdemo://<Auth0 ドメイン名>/android/<Android プロジェクトのパッケージ名>/callback
で入力してください。本記事の例では、Android プロジェクトのパッケージ名がcom.example.sample_auth0_login
になります。
その後は、ページ下部にある Save Changes ボタンをクリックして設定を保存してください。
Auth0 SDK を使用するための準備を行う
Auth0 Android SDK を追加する
app 内の build.gradle に下記を追記します。その後、Gradle ファイルを同期してください。
app/build.gradle
...
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
// ★
implementation 'com.auth0.android:auth0:2.+'
}
ビルド変数を設定する
Auth0 Android SDK の内部で使用されるビルド変数を設定します。
app/build.gradle
...
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.sample_auth0_login"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// ★
manifestPlaceholders = [auth0Domain: "@string/com_auth0_domain", auth0Scheme: "@string/com_auth0_scheme"]
}
...
実際の値は strings.xml に記載します。Auth0 のクライアント ID、ドメイン名はそれぞれの環境に合わせて変更してください。本記事ではスキーマをdemo
にします。
app/src/main/res/values/strings.xml
<resources>
<string name="app_name">Auth0LoginSample</string>
<!-- ★ -->
<string name="com_auth0_client_id"><Auth0 のクライアント ID></string>
<string name="com_auth0_domain"><Auth0 のドメイン名></string>
<string name="com_auth0_scheme">demo</string>
</resources>
インターネットに接続するための権限を設定する
マニフェストファイルに権限を追記します。
app/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sample_auth0_login">
<!-- ★ -->
<uses-permission android:name="android.permission.INTERNET" />
<application
...
ログイン/ログアウト処理を持つモジュールを実装する
後述するログイン用の画面、ログアウト用の画面から Auth0 の処理を呼び出せるようにモジュールを実装しておきます。
Auth0(context)
としている箇所で、strings.xml に記載したcom_auth0_client_id
とcom_auth0_domain
の値が自動的に読み込まれます。
app/src/main/java/com/example/sample_auth0_login/AuthModule.kt
package com.example.sample_auth0_login
import android.content.Context
import com.auth0.android.Auth0
import com.auth0.android.provider.WebAuthProvider
internal object AuthModule {
fun loginAuthBuilder(context: Context): WebAuthProvider.Builder {
return WebAuthProvider.login(Auth0(context))
.withScheme(context.getString(R.string.com_auth0_scheme))
.withScope("openid profile email")
}
fun logoutAuthBuilder(context: Context): WebAuthProvider.LogoutBuilder {
return WebAuthProvider.logout(Auth0(context))
.withScheme(context.getString(R.string.com_auth0_scheme))
}
}
ログイン画面を実装する
MainActivity にログイン用のボタンを配置します。ログインボタンがクリックされると、ユニバーサルログイン画面が起動して、ログインが成功すれば、ContentActivity に画面遷移するようにしています。
app/src/main/java/com/example/sample_auth0_login/MainActivity.kt
package com.example.sample_auth0_login
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import com.auth0.android.authentication.AuthenticationException
import com.auth0.android.callback.Callback
import com.auth0.android.result.Credentials
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// ログインボタンをクリックするとユニバーサルログイン画面が起動する
val loginButton = findViewById<Button>(R.id.loginButton)
loginButton.setOnClickListener {
loginWithBrowser()
}
}
private fun loginWithBrowser() {
AuthModule.loginAuthBuilder(this)
.start(this, object : Callback<Credentials, AuthenticationException> {
override fun onSuccess(credentials: Credentials) {
// ログインに成功したら ContentActivity に遷移する
val intent = Intent(applicationContext, ContentActivity::class.java)
startActivity(intent)
}
override fun onFailure(exception: AuthenticationException) {}
})
}
}
ログアウト画面を実装する
ContentActivity にログアウト用のボタンを配置します。ログアウトボタンがクリックされると、ログアウト処理が走り、MainActivity に画面遷移するようにしています。
app/src/main/java/com/example/sample_auth0_login/ContentActivity.kt
package com.example.sample_auth0_login
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import com.auth0.android.authentication.AuthenticationException
import com.auth0.android.callback.Callback
class ContentActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_content)
// ログインボタンをクリックするとログアウト処理が走る
val logoutButton = findViewById<Button>(R.id.logoutButton)
logoutButton.setOnClickListener {
logout()
}
}
private fun logout() {
AuthModule.logoutAuthBuilder(this)
.start(this, object: Callback<Void?, AuthenticationException> {
override fun onSuccess(payload: Void?) {
// ログアウトに成功したら MainActivity に遷移する
val intent = Intent(applicationContext, MainActivity::class.java)
startActivity(intent)
}
override fun onFailure(error: AuthenticationException) {}
})
}
}
デモ
ログインボタンをクリックすると、
ユニバーサルログイン画面が起動します。
ログインが成功すると、ログアウトボタンが設置されている画面に遷移します。
ログアウトボタンをクリックすると、ログイン画面に戻ります。
おわりに
Android アプリに Auth0 のユニバーサルログインを組み込むことができました。公式のクイックスタートには、プロフィールの変更などの対応についても記載がありますので、そちらの理解も深めていきたいなと思います。
今回は以上になります。最後まで読んで頂きありがとうございました!