REST APIによるログイン機能の実装方法
ログイン機能は3つの処理に分けられます。
1.ログイン画面を表示する処理
2.ログイン結果(認証コード)を受け取る処理
3.認証コードをIDトークンに交換する処理
ログイン画面を表示する処理
まず、Webログイン画面のリンクを生成します。
リンク:https://oauth-login.cloud.huawei.com/oauth2/v3/authorize
パラメータ:
パラメータ名 | 値 |
---|---|
client_id | AppGallery Connectのプロジェクト設定に表示されるApp IDです。 AGCUtils.getAppId()を使えば、agconnect-services.jsonの中の"app_id"の値を取得できます |
scope | "openid+profile" |
response_type | "code" |
access_type | 必須ではないが、"offline"を渡せばリフレッシュトークンも返ってきます |
redirect_uri | AppGallery ConnectのAccount Kitに設定したリダイレクトURIです |
こちらのページも合わせてご参照ください:
companion object {
private const val AUTH_LINK = "https://oauth-login.cloud.huawei.com/oauth2/v3/authorize"
private const val SCOPE = "openid+profile"
const val REDIRECT_URI = "http://www.hmsaccountkit.com"
}
override fun signIn(activity: Activity) {
activity.startActivity(generateSignInIntent(activity.applicationContext))
}
private fun generateSignInIntent(context: Context): Intent {
return Intent(context, WebViewActivity::class.java).apply {
putExtra("link", createAuthLink(context))
}
}
private fun mapToString(map: Map<String, String>): String {
var query = ""
var count = 0
map.forEach { (key, value) ->
if (count > 0) {
query += "&"
}
query += "$key=$value"
count++
}
return query
}
private fun createAuthLink(context: Context): String {
val map: Map<String, String> = hashMapOf(
"client_id" to AGCUtils.getAppId(context),
"scope" to SCOPE,
"response_type" to "code",
"access_type" to "offline",
"redirect_uri" to REDIRECT_URI
)
return AUTH_LINK + "?" + mapToString(map)
}
Webログイン画面のリンクをWebViewの中に表示します。
ログイン結果(認証コード)を受け取る処理
ログイン結果はリダイレクトURIのパラメータとして返ってきます。そのため、次のようにWebViewActivityクラスを作ります。
まず、レイアウトはWebViewのみで大丈夫です。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<WebView
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
次はWebViewActivityクラスです。
まず、webviewのJavaScriptを有効にします。
さらに、shouldOverrideUrlLoading()の中で、開くリンクがリダイレクトURIと一致しているかどうかをチェックし、一致していれば、それを開かずに、パラメータ(認証コード)と一緒にMainActivityに転送します。
class WebViewActivity : AppCompatActivity() {
private lateinit var binding: WebViewActivityBinding
@SuppressLint("SetJavaScriptEnabled")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.inflate<WebViewActivityBinding>(
layoutInflater,
R.layout.web_view_activity,
null,
false
)
setContentView(binding.root)
with(binding) {
webView.settings.javaScriptEnabled = true
webView.settings.domStorageEnabled = true
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
request?.url?.let { url ->
if (url.toString().contains(NonHmsHuaweiIdLogic.REDIRECT_URI)) {
val intent = Intent(applicationContext, MainActivity::class.java).apply {
data = url
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
startActivity(intent)
return true
}
view?.loadUrl(url.toString())
}
return false
}
}
intent?.getStringExtra("link")?.let { url ->
webView.loadUrl(url)
}
}
window.setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
}
}
認証コードはIntentのdataに格納されます。
intent.data?.getQueryParameter("code")
認証コードをIDトークンに交換する処理
認証コードはそのまま使えません。ユーザー情報が入っているIDトークンに交換する必要があります。
まずIntentから認証コードを取得します
override fun onStart() {
super.onStart()
huaweiIdLogic.update(applicationContext, intent)
}
override fun update(context: Context, intent: Intent) {
intent.data?.getQueryParameter("code")?.let { code ->
signInWithCode(context, code)
}
}
次はAPIを呼び出し、認証コードをIDトークンに交換します。
API:https://oauth-login.cloud.huawei.com/oauth2/v3/token
メソッド:POST
パラメータ:
パラメータ名 | 値 |
---|---|
grant_type | "authorization_code" |
client_id | AppGallery Connectのプロジェクト設定に表示されるApp IDです。 AGCUtils.getAppId()を使えば、agconnect-services.jsonの中の"app_id"の値を取得できます |
client_secret | AppGallery Connectのプロジェクト設定に表示されるApp Secretです。 |
code | 認証コード |
redirect_uri | AppGallery ConnectのAccount Kitに設定したリダイレクトURIです |
こちらのページも合わせてご参照ください:
companion object {
private const val GET_ID_TOKEN_URL = "https://oauth-login.cloud.huawei.com/oauth2/v3/token"
}
private fun signInWithCode(context: Context, code: String) {
val context: Context = context ?: return
getIdToken(
context,
code,
object : Response.Listener<String> {
override fun onResponse(response: String?) {
response?.let { response ->
val jsonObject = JSONObject(response)
if (jsonObject.has("id_token")) {
// 権限を取り消すときにアクセストークンが必要
val accessToken = jsonObject.getString("access_token")
// IDトークンにユーザー情報が入っている
val idToken = jsonObject.getString("id_token")
}
}
}
},
object : Response.ErrorListener {
override fun onErrorResponse(error: VolleyError?) {
error?.printStackTrace()
}
}
)
}
private fun getIdToken(
context: Context,
authorizationCode: String,
listener: Response.Listener<String>,
errorListener: Response.ErrorListener
) {
val queue = Volley.newRequestQueue(context)
val postRequest: StringRequest = object : StringRequest(
Method.POST,
GET_ID_TOKEN_URL,
listener,
errorListener
) {
override fun getBodyContentType(): String {
return "application/x-www-form-urlencoded"
}
override fun getParams(): Map<String, String> {
val params: MutableMap<String, String> = HashMap()
params["grant_type"] = "authorization_code"
params["client_id"] = AGCUtils.getAppId(context) ?: ""
params["client_secret"] = APP_SECRET
params["code"] = authorizationCode
params["redirect_uri"] = REDIRECT_URI
return params
}
}
queue.add(postRequest)
}
これでIDトークンが取得できます。
また、アクセストークンも同時に返ってきます。アクセストークンは権限取り消すときに必要です。
シリーズ
- Android端末におけるHUAWEI IDログイン機能の詳細実装手順1-ソリューションの概要
- Android端末におけるHUAWEI IDログイン機能の詳細実装手順2-実装準備
- Android端末におけるHUAWEI IDログイン機能の詳細実装手順3-HMS判定
- Android端末におけるHUAWEI IDログイン機能の詳細実装手順4-HMS端末でログイン
- Android端末におけるHUAWEI IDログイン機能の詳細実装手順5-HMS端末でログアウト
- Android端末におけるHUAWEI IDログイン機能の詳細実装手順6-HMS端末で権限取り消し
- Android端末におけるHUAWEI IDログイン機能の詳細実装手順7-GMS端末でログイン1
- Android端末におけるHUAWEI IDログイン機能の詳細実装手順8-GMS端末でログイン2
- Android端末におけるHUAWEI IDログイン機能の詳細実装手順9-GMS端末でログアウト
- Android端末におけるHUAWEI IDログイン機能の詳細実装手順10-GMS端末で権限取り消し
GitHub
参考
- HMS:https://developer.huawei.com/consumer/jp/
- HMS Account Kitの紹介:https://developer.huawei.com/consumer/jp/doc/overview/HMS
- HMS Account Kitのドキュメント:https://developer.huawei.com/consumer/jp/doc/development/HMSCore-Guides-V5/introduction-0000001050048870-V5
- Huawei Developers:https://forums.developer.huawei.com/forumPortal/en/home
- Facebook Huawei Developersグループ:https://www.facebook.com/Huaweidevs/