Unity+Android+OAuth認証の実装方法の紹介

# 1. 前置き
AndroidでOAuthを実装するにあたり、専用ライブラリを使うことが最も簡単な方法です。しかし、当たり前ですが、Android向けのライブラリなので、Unityでは使えません。本稿はUnityでAndroid向けのOAuthを実装する手順を紹介するものです。また、例として、GoogleのOAuthを取り上げます。

# 2. 流れの概要
AndroidでGoogleのOAuthを使用する流れは次の通りです。
1.	Custom Tabsを開く
2.	Googleの認証画面を表示する
3.	Google認証のリダイレクトを受け取る
4.	リダイレクトで得られたトークンを使い、ユーザー情報を取得する

下記のリソースを使えば、実装がより簡単になります。

## 2.1. リソースの紹介
### 2.1.1. IdentityModel.OidcClient
IdentityModel.OidcClientはC＃向けのOpenID Connect認定済みのOAuth SDKです。netstandard14、デスクトップ.N​​ET、UWP、.NET Core、Xamarin iOS、Androidをサポートしています。

UnityはJavaやKotlinではなくC＃を使用するため、AppAuth for AndroidなどのJavaベースのOAuth SDKをそのまま使用することができません。IdentityModel.OidcClientなら使用できます。

IdentityModel.OidcClientを使えば、Google Playサービスに依存せずにUnityのAndroid向けのゲームにGoogleアカウント認証を実装できます。

リンク：
https://github.com/IdentityModel/IdentityModel.OidcClient/tree/releases/2.9.x

### 2.1.2. Json.Net.Unity3D
Json.Net.Unity3DはUnityでJSONを使うためのSDKです。IdentityModel.OidcClientではJSONを使うため、Json.Net.Unity3Dが必要です。

リンク：
https://github.com/SaladLab/Json.Net.Unity3D/releases

### 2.1.3. unity-jar-resolver
unity-jar-resolverはCustom Tabのライブラリをダウンロードするためのライブラリです。

リンク：
https://github.com/googlesamples/unity-jar-resolver/tree/release/1.2.169

### 2.1.4. Unity3D.Authentication.Example
Unity3D.Authentication.ExampleはIdentityModel.OidcClientのサンプルです。このサンプルにAndroidUnityPluginが含まれています。OAuthの認証結果は、リダイレクトを通してカスタムタブからアクティビティに戻ります。 AndroidUnityPluginはリダイレクト結果を受け取り​​Unityに返します。

リンク：
https://github.com/peterhorsley/Unity3D.Authentication.Example

# 3. 実装方法
以下はGoogleのOAuthの実装例です。

## 3.1. 前準備
下記のリソースをダウンロードしておきます。

### IdentityModel.OidcClient：
https://github.com/IdentityModel/IdentityModel.OidcClient/tree/releases/2.9.x 

###	Json.Net.Unity3D：
https://github.com/SaladLab/Json.Net.Unity3D/releases 

###	unity-jar-resolver：
https://github.com/googlesamples/unity-jar-resolver/tree/release/1.2.169

###	Unity3D.Authentication.Example：
https://github.com/peterhorsley/Unity3D.Authentication.Example

## 3.2. Custom Tabsのライブラリのインポート
### 3.2.1. unity-jar-resolverのexternal-dependency-manager-1.2.169.unitypackageのインポート

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/3fe4af92-d783-f3e9-8b56-b54449c6afa3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/579dd2cf-0ddb-bd10-6f49-231dfcda41cb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/369fd719-ac5b-37bf-b55e-7c48f5a3d190.png)

### 3.2.2. ExternalDependencies.xmlの追加
Assets\ExternalDependencyManager\EditorにExternalDependencies.xmlを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/9c1c1eab-58b9-c790-f38d-0beca13e75bc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/10265895-4080-7c63-7587-e1f93fc77bc1.png)

ExternalDependencies.xmlに下記のソースコードを追加します。

```xml:ExternalDependencies.xml
<dependencies>
  <androidPackages>
    <repositories>
      <repository>https://repo.maven.apache.org/maven2</repository>
    </repositories>
    <androidPackage spec="androidx.browser:browser:1.4.0">
      <androidSdkPackageIds>
        <androidSdkPackageId>extra-google-m2repository</androidSdkPackageId>
      </androidSdkPackageIds>
      <repositories>
        <repository>https://maven.google.com</repository>
      </repositories>
    </androidPackage>
  </androidPackages>
</dependencies>
```

androidx.browser:browserの最新バージョンはここでご確認ください。
https://developer.android.com/jetpack/androidx/releases/browser

### 3.2.3. Custom Tabsのライブラリのダウンロード
[Asset] > [External Dependency Manager] > [Android Resolver] > [Force Resolve]を実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/27c30c43-2ce4-748f-7af0-0d35ff25bde2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/58534618-b3a6-5785-93bd-f9cd29c0b58f.png)

ダウンロードが完了したら、Custom TabsのライブラリはAssets/Plugins/Andriodに保存されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/385c4e88-129e-40b4-def0-7b6afa29ee9b.png)

## 3.3. IdentityModel.OidcClientのインポート

### 3.3.1. IdentityModel.OidcClientのプロジェクトのビルド

### 3.3.2. net452フォルダの中の全ファイルをUnityのプロジェクトのAssets\IdentityModelにコピー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/adef1cd6-c558-defe-434c-41d6515d0102.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/ca7c58b3-7d4b-0c53-041c-07543d068021.png)

ただし、System.Runtime.InteropServices.RuntimeInformation.dllをコピーしません。

## 3.4. JsonNet.9.0.1のインポート

### 3.4.1. JsonNet.9.0.1.unitypackageのインポート

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/3fe4af92-d783-f3e9-8b56-b54449c6afa3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/8f154873-a711-0cc6-865e-36147a353d5c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/d2f7d64e-fdf0-6897-6da2-649158766348.png)

### 3.4.2. Newtonsoft.Json.dllの移動
Assets\UnityPackages\JsonNet\Newtonsoft.Json.dllをAssets\IdentityModelに移動させます。

### 3.4.3. link.xmlの作成
Assetsにlink.xmlを新規作成し、下記の内容を追加します。

```xml:link.xml
<linker>
    <assembly fullname="System">
        <type fullname="System.ComponentModel.TypeConverter" preserve="all"/>
        <type fullname="System.ComponentModel.ArrayConverter" preserve="all"/>
        <type fullname="System.ComponentModel.BaseNumberConverter" preserve="all"/>
        <type fullname="System.ComponentModel.BooleanConverter" preserve="all"/>
        <type fullname="System.ComponentModel.ByteConverter" preserve="all"/>
        <type fullname="System.ComponentModel.CharConverter" preserve="all"/>
        <type fullname="System.ComponentModel.CollectionConverter" preserve="all"/>
        <type fullname="System.ComponentModel.ComponentConverter" preserve="all"/>
        <type fullname="System.ComponentModel.CultureInfoConverter" preserve="all"/>
        <type fullname="System.ComponentModel.DateTimeConverter" preserve="all"/>
        <type fullname="System.ComponentModel.DecimalConverter" preserve="all"/>
        <type fullname="System.ComponentModel.DoubleConverter" preserve="all"/>
        <type fullname="System.ComponentModel.EnumConverter" preserve="all"/>
        <type fullname="System.ComponentModel.ExpandableObjectConverter" preserve="all"/>
        <type fullname="System.ComponentModel.Int16Converter" preserve="all"/>
        <type fullname="System.ComponentModel.Int32Converter" preserve="all"/>
        <type fullname="System.ComponentModel.Int64Converter" preserve="all"/>
        <type fullname="System.ComponentModel.NullableConverter" preserve="all"/>
        <type fullname="System.ComponentModel.SByteConverter" preserve="all"/>
        <type fullname="System.ComponentModel.SingleConverter" preserve="all"/>
        <type fullname="System.ComponentModel.StringConverter" preserve="all"/>
        <type fullname="System.ComponentModel.TimeSpanConverter" preserve="all"/>
        <type fullname="System.ComponentModel.UInt16Converter" preserve="all"/>
        <type fullname="System.ComponentModel.UInt32Converter" preserve="all"/>
        <type fullname="System.ComponentModel.UInt64Converter" preserve="all"/>
    </assembly>
</linker>
```

### 3.4.4. mcs.rspの作成
Assetsにmcs.rspを新規作成し、次の内容を追加します。

```
-r:System.Net.Http.dll
```

## 3.5. Googleの認証画面の表示
### 3.5.1. 次のソースコードをUnityプロジェクトに追加

https://github.com/Rei2020GitHub/MyPublicProject/blob/master/Unity%20OAuth%20Demo/Assets/AndroidChromeCustomTab.cs

https://github.com/Rei2020GitHub/MyPublicProject/blob/master/Unity%20OAuth%20Demo/Assets/AndroidChromeCustomTabBrowser.cs

https://github.com/Rei2020GitHub/MyPublicProject/blob/master/Unity%20OAuth%20Demo/Assets/CertificateHandler.cs

https://github.com/Rei2020GitHub/MyPublicProject/blob/master/Unity%20OAuth%20Demo/Assets/MobileBrowser.cs

https://github.com/Rei2020GitHub/MyPublicProject/blob/master/Unity%20OAuth%20Demo/Assets/OAuthLoginScript.cs

https://github.com/Rei2020GitHub/MyPublicProject/blob/master/Unity%20OAuth%20Demo/Assets/UnityAuthClient.cs

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/79648c41-f231-e8e0-f87b-6b39dbde8887.png)

### 3.5.2. GoogleのOAuthの設定の追加
OAuthLoginScript.csを開き、GoogleのOAuthの設定を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/0f199b80-4666-2f6c-15d4-faae96b4396c.png)

Client IdはGoogle Cloud Platform > [APIとサービス] > [認証情報] > [OAuth 2.0 クライアント ID] > [クライアント ID]です。また、Client Idを作るときに、アプリケーションの種類をAndroidに設定しなければなりません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/1c8ea6bb-53c7-d5a0-5139-da6a027e4d7f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/75a1d2dd-7522-ddf5-a3ce-32854c445dea.png)

ScopeはGoogle Cloud Platform > [APIとサービス] > [OAuth 同意画面]に設定したスコープです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/789c46c3-a674-b80a-3ab0-317d13d707e8.png)

Package nameはProject Settingsに設定したパッケージ名で、Pathはなんでも大丈夫です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/908534ae-9e5f-ef71-e42a-64c9c50b147b.png)

### 3.5.3. Googleの認証画面の表示
GoogleIdLogin()を実行すれば、Googleの認証画面はCustom Tabsの中で開かれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/a5fddf1f-beb1-db65-e08f-e55302793527.png)

## 3.6. AndroidUnityPluginのインポート
Googleの認証結果はリダイレクトを通じて返ってくるので、Unityプロジェクトにリダイレクト結果を受け取るプラグインを追加しなければなりません。

### 3.6.1. AndroidUnityPluginをUnityプロジェクトにコピー
Unity3D.Authentication.Example-master\AndroidUnityPluginを自分のUnityプロジェクトにコピーします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/ccc35e9c-ecb1-3ded-0c82-84e21d9c5670.png)

### 3.6.2. Unity Editorのclasses.jarをAndroidUnityPluginにコピー
C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes\classes.jarをAndroidUnityPlugin/app/libsにコピーします。

### 3.6.3. AuthRedirectActivity.javaの編集
AndroidUnityPluginのAuthRedirectActivity.javaを開きます。
UnityPlayer.UnitySendMessageの最初のパラメータを、OAuthLoginScriptのターゲットに書き換えます。たとえば、OAuthLoginScriptのターゲットがCanvasであれば、UnityPlayer.UnitySendMessageの最初のパラメータをCanvasに書き換えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/61929705-11ee-534f-499c-f6c8eebb9a53.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/7137c1b0-2038-9517-eeff-054492e9d996.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/07308b5c-3dcc-8700-311f-e7da408194ca.png)

### 3.6.4. app:exportJarの実行
gradleのapp:exportJarを実行します。実行したら、Assets\Plugins\AndroidにAndroidUnityPlugin.jarが生成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/e4c61c02-15a8-6f13-d55f-43c92ff94289.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/1e4aa06a-bd64-adb9-1a1f-1e22f1022266.png)

### 3.6.5. AndroidManifest.xmlの編集
Project SettingsのPlayerにあるCustom Main Manifestをチェックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/4140233e-1fb4-346b-5dc4-6bb05b07020c.png)

Assets\Plugins\AndroidにあるAndroidManifest.xmlを開き、次のソースコードを追加します。

```xml:AndroidManifest.xml
   <uses-permission android:name="android.permission.INTERNET" />
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

        <activity android:name="org.identitymodel.unityclient.AuthRedirectActivity" android:label="@string/app_name">
        <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="{Your package name}" />
        </intent-filter>
```

{Your package name}は自分んおアプリのパッケージ名です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704548/58d5fb27-198e-a6bf-93b6-0dcf1bffddd9.png)

## 3.7. 各Tokenについて
OAuthLoginScriptの中で次のメソッドを実行すれば、アクセストークン、リフレッシュトークン、IDトークンが取得できます。

_authClient.GetAccessToken()
_authClient.GetRefreshToken()
_authClient.GetIdToken()

## 3.8. ユーザー情報について
OAuthLoginScriptの中で
_authClient.GetPayload({field})
を実行すれば、IDトークンの中のユーザー情報が取得できます。

fieldは次のものになります。

|データ|field|
|:---:|:---:|
|Open Id|sub|
|姓名|name|
|姓|family_name|
|名|given_name|
|画像URL|picture|
|メールアドレス|email|
|有効なメールアドレスかどうか|email_verified|

# GitHub
https://github.com/Rei2020GitHub/MyPublicProject/tree/master/Unity%20OAuth%20Demo