React APIクライアントへ Keycloak認証の機能追加

作成：2023年4月21日
[前回まで](https://qiita.com/RYO_/items/758dc99c7dd8f49c785e)で、Go の APIサーバーに GET/POST/PATCH/DELETE の機能を、 React の APIクライアントに GET の機能を実装しました。
また、前回、[React で Keycloak認証](https://qiita.com/RYO_/items/2fff63ae111d2957700c)を試してみました。
今回は、React のAPIクライアントに Keycloak認証を追加していきたいと思います。

# Reactアプリに GETボタンを追加
Keycloak認証を追加する前に、少し Reactアプリに手を加えます。
これまでは React を実行すると、実行後に GETリクエストしていましたが、今回 GETボタンを押すとリクエスト結果を表示するようにします。
コードを更新します（[GithubのApp.jsコードのリンク](https://github.com/ryoyuki6/api202304/blob/qiita20230402/react/src/App.js)）
```:App.js
  const fetchData = async () => {
    // const response = await axios.get("http://54.199.172.102:8080/health_data");
    const response = await axios.get("http://localhost:8080/health_data");
    setGetData(response.data);
  };

  return (
    <>
      <button onClick={fetchData}>GET</button>
```

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/baa9737c-f62f-8904-c94b-253fb09ba22d.png">

# Keycloak認証を追加する為にコード更新

reactのフォルダでインストールしておきます。
```:console
% yarn add keycloak-js @react-keycloak/web react-router-dom
```
次のファイルを更新します（[Githubのコード置き場：qiita20230416a](https://github.com/ryoyuki6/api202304/tree/qiita20230416a)）
・index.js
・App.js
・Keycloak.js
・Nav.js



# ローカルのDocker で「Keycloak認証付きReact APIクライアント」と「Go APIサーバー」を起動

## Keycloakサーバーのコンテナを起動
```:console
% docker run -d -p 8080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin --name keycloak jboss/keycloak
```
[設定は以前と同じ](https://qiita.com/RYO_/items/2fff63ae111d2957700c#keycloak-%E3%82%92-docker-%E3%81%A7%E7%AB%8B%E3%81%A6%E3%82%8B)とします。

## Go APIサーバーのコンテナを起動
ポート番号は、Keycloakサーバーと同じにならないように 8081 とします。
```:console
% pwd
/***/go-api
% docker build -t go-api20230416:1.0 .
% docker run -it --name go-api -p 8081:8081 go-api20230416:1.0
```

## React APIクライアントのコンテナを起動
```:console
% pwd
/***/react
% docker build -t react-api20230416:1.0 .
% docker run -it --name react-api -p 3000:3000 react-api20230416:1.0
```

## Dockerコンテナ確認
3つコンテナが立っています。
```:console
% docker ps
CONTAINER ID   IMAGE                        COMMAND                   CREATED          STATUS          PORTS                                                 NAMES
e53dffe32045   react-api20230416:1.0        "yarn start"              2 hours ago      Up 3 seconds    0.0.0.0:3000->3000/tcp, :::3000->3000/tcp             react-api
b7c24b6b8eb4   go-api20230416:1.0           "go run main.go"          2 hours ago      Up 13 seconds   0.0.0.0:8081->8081/tcp, :::8081->8081/tcp             go-api
5d817cac1909   jboss/keycloak               "/opt/jboss/tools/do…"   45 hours ago     Up 19 seconds   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 8443/tcp   keycloak
```

## ブラウザで確認
http://localhost:3000/ にブラウザでアクセスします。
「Loginボタン」を押します
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/e789dad8-cf31-9c9d-351f-52e4e0cd81a8.png">
ID と password を入力して「Sign in」を押します。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/2f5f1b2d-792f-9b40-3a38-a4eb35261bf6.png">
ログインできました。ログインして表示された「GET」ボタンを押してみます。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/fbabfa2d-8206-d735-916d-3a3dd0055cd8.png">
Go APIサーバーから GET したデータが画面に表示されました。
「Logout」ボタンを押してみます。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/b80b09f6-0d5e-842e-4e32-5f6f31cc9207.png">
ログアウトできました。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/ddc17995-2e21-88df-05ba-402ef880f6ec.png">


# AWS EC2上のDockerで起動

次は EC2上で Dockerを立ててみます。

## EC2 のIPアドレスをコードに反映させる
EC2 の管理コンソールでIPアドレスを確認して、main.go と Nav.js のコードを更新します。
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/cd7455d5-7448-9336-2d4a-15947a073dff.png">

```:main.go
config.AllowOrigins = []string{"http://54.95.36.175:3000"}
```

```:Nav.js
const response = await axios.get("http://54.95.36.175:8081/health_data");
```

```:Keycloak.js
const keycloak = new Keycloak({
  url: "http://52.196.53.235:8080/auth",
```

## imageファイルを作成
```:console
% pwd
/***/go-api
% docker build -t go-api20230416:2.0 .
```

```:console
% pwd
/***/react
% docker build -t react-api20230416:2.0 .
```

## imageファイルを .tar ファイルへ書き出し

```:console
ryo@Ryo-MacBook-Pro react % docker image ls
REPOSITORY                         TAG                    IMAGE ID       CREATED          SIZE
react-api20230416                  2.0                    6bb3b8f485a6   28 minutes ago   1.55GB
go-api20230416                     2.0                    046c2858bc27   29 minutes ago   501MB
% docker save -o react-api20230416.tar react-api20230416:2.0
% docker save -o go-api20230416.tar go-api20230416:2.0
```

## .tarファイルをEC2へコピー

```:console
% scp -i ~/.aws/docker20230223.pem ./react-api20230416.tar ubuntu@54.95.36.175:/home/ubuntu
% scp -i ~/.aws/docker20230223.pem ./go-api20230416.tar ubuntu@54.95.36.175:/home/ubuntu
```

## EC2上で .tarファイルを imageファイル化

EC2上で作業します。
```:EC2
% ssh ubuntu@54.95.36.175 -i ~/.aws/docker20230223.pem
$ docker load -i react-api20230416.tar
$ docker load -i go-api202330416.tar
$ docker image ls
REPOSITORY          TAG       IMAGE ID       CREATED         SIZE
react-api20230416   2.0       6bb3b8f485a6   4 hours ago     1.55GB
go-api20230416      2.0       046c2858bc27   4 hours ago     501MB
```

## Keycloakサーバーのコンテナを立てる

```:EC2
$ docker run -d -p 8080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin --name keycloak jboss/keycloak
```
レムル、user、clientを作成します。
ブラウザを起動して、EC2の http://13.231.64.168:8080/auth/ にアクセスします。
Administration Console > を押してみます。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/52ac3ce3-f116-d685-9daa-132a838b30e6.png">
すると HTTPS でアクセスして！と怒られました。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/a2362bf4-3ef9-8a4b-5021-e85243c414bf.png">
そこで、HTTP でもアクセスできるように設定を変えます。
```:EC2
$ docker exec -it keycloak bash

# Admin CLI コマンドで「SSL required」を「NONE」に変更
# Keycloakのデフォルト設定だと「SSL required」項目により、SSL通信が必須
# HTTP通信で使うために設定を変更
# 管理者ID（ここではadmin）で認証情報を設定する

$ /opt/jboss/keycloak/bin/kcadm.sh config credentials --server http://localhost:8080/auth --realm master --user admin --password admin

# レルム「master」のSSL requiredを「NONE」に変更
$ /opt/jboss/keycloak/bin/kcadm.sh update realms/master -s sslRequired=NONE

$ exit
```

ブラウザを起動して、EC2の http://13.231.64.168:8080/auth/ にアクセスします。
Administration Console > を押してみます。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/52ac3ce3-f116-d685-9daa-132a838b30e6.png">
管理者のIDとpasswordを入力できる画面にHTTPで行けました。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/d39304f8-ab3b-c0d1-2e58-0e56831dbedc.png">

以降は[以前と同じ手順](https://qiita.com/RYO_/items/2fff63ae111d2957700c#keycloak-%E3%82%92-docker-%E3%81%A7%E7%AB%8B%E3%81%A6%E3%82%8B)でレムル、user、clientを作成します。
だたし、途中で、user作成後に、userでログインする前に、レルム「test_realm」にHTTPでアクセスできるように設定します。
```:EC2
$ docker exec -it keycloak bash

# Admin CLI コマンドで「SSL required」を「NONE」に変更
# Keycloakのデフォルト設定だと「SSL required」項目により、SSL通信が必須
# HTTP通信で使うために設定を変更
# 管理者ID（ここではadmin）で認証情報を設定する

$ /opt/jboss/keycloak/bin/kcadm.sh config credentials --server http://localhost:8080/auth --realm test_realm --user admin --password admin

# レルム「master」のSSL requiredを「NONE」に変更
$ /opt/jboss/keycloak/bin/kcadm.sh update realms/test_realm -s sslRequired=NONE

$ exit
```
また、client作成では EC2 のIPアドレスを入力します。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/3b1dce9a-b903-4d0e-6d87-1c65df6f248f.png">

この設定を行わないと、HTTPSでアクセスしてと怒られます。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/874d17ae-88d0-0db0-fc6d-36d616059919.png">

Keycloak の設定を終えて次に進みます。


##Go APIサーバーのコンテナを立てる

```:EC2
$ docker run -dit --name go-api -p 8081:8081 go-api20230416:2.0
```

##React APIクライアントのコンテナ立てる

```:EC2
$ docker run -dit --name react-api -p 3000:3000 react-api20230416:2.0
$ docker ps
CONTAINER ID   IMAGE                   COMMAND                  CREATED          STATUS          PORTS                                                 NAMES
5652d679a7b8   react-api20230416:2.0   "yarn start"             7 seconds ago    Up 5 seconds    0.0.0.0:3000->3000/tcp, :::3000->3000/tcp             react-api
1a556a7f10b7   go-api20230416:2.0      "go run main.go"         40 seconds ago   Up 38 seconds   0.0.0.0:8081->8081/tcp, :::8081->8081/tcp             go-api
63f11eb12279   jboss/keycloak          "/opt/jboss/tools/do…"   2 minutes ago    Up 2 minutes    0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 8443/tcp   keycloak
```

##ブラウザでアクセスして確認

http://13.231.64.168:3000/ にアクセスして確認します。
Loginボタンを押します。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/72931ce7-b694-ed12-16f7-0d52237ddf8c.png">

# EC2立て直し

## EC2 の選択

EC2が固まってしまうので、もう少し大きいEC2を立ててみます。
・reactイメージが1.5GB、goイメージが0.5GBです。
・t2.micro（i386・メモリ1GB） で Reactコンテナ立ち上げ後に固まります
・t3.medium（x86_64・メモリ4GB）　で Reactコンテナが立ち上がるようになりました！
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/ef6fcb17-1f40-ef02-1392-918dbb8df026.png">


## EC2 へ Dockerインストール
```:MacBook console
% ssh ubuntu@35.77.214.212 -i ~/.aws/docker20230223.pem
```
```:EC2
# パッケージをアップデート
$ sudo apt-get update

# 必要なパッケージをインストール
$ sudo apt-get -y install apt-transport-https ca-certificates curl gnupg-agent software-properties-common

# Docker のオフィシャルGPGキーを追加
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# Dockerダウンロードサイトを　aptリポジトリに追加
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

# Docker Engine一式をインストール
$ sudo apt-get update
$ sudo apt-get install -y docker-ce docker-ce-cli containerd.io

# ubuntuユーザーでdockerを利用できるようにします
$ sudo gpasswd -a ubuntu docker

# 一旦ログオフします
$ exit
```

ログインして Dockerがインストールされていることを確認します。
```:MacBook console
% ssh ubuntu@35.77.214.212 -i ~/.aws/docker20230223.pem
```
```:EC2
$ docker --version
Docker version 23.0.4, build f480fb1
```

# 動作確認

上記方法で
・keycloakコンテナ立ち上げと設定
・go APIサーバーコンテナ立ち上げ
・react APIクライアントサーバー立ち上げ
を行って、
http://35.77.214.212:3000/
にアクセスしてEC2上で正常動作を確認できました。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/72931ce7-b694-ed12-16f7-0d52237ddf8c.png">
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/fdf95ed6-2817-30f7-431e-d8264917df01.png">
「GETボタン」を押します
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/b91fb364-b375-e3e2-266c-bd68abfb0c88.png">
GETリクエストの結果が表示されました。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/e17ea782-7e15-e24c-d11e-70f66f592fe8.png">
ログアウトします
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/cfffcbd6-9a3e-81c1-766d-9b72bf48421e.png">

　以上で、EC2 上の Dockerで、keycloakコンテナと Go APIサーバーのコンテナと React APIクライアントのコンテナを立てて、正常動作を確認できました（[Githubのコード置き場：qiitq20230421](https://github.com/ryoyuki6/api202304/tree/qiita20230421)）
　次は、React APIクライアントに createやupdateやdeleteの機能追加や、keycloak の認可機能を追加していきたいと思います。


# 参考

## GETボタン追加の参考
・[AxiosPOSTリクエストを理解する](https://morioh.com/p/0589058c0b87)
・[Reactを使ってaxiosを学ぶ](https://reffect.co.jp/react/react-axios#DELETE)

## Keycloak認証追加の参考
・[How to disable SSL for latest Keycloak?](https://groups.google.com/g/keycloak-user/c/H95eYsbhVHg?pli=1)
・[SSL required設定変更](https://qiita.com/rururu_kenken/items/a1afac2ef118f5616435#%E3%83%AC%E3%83%AB%E3%83%A0%E8%BF%BD%E5%8A%A0ssl-required%E8%A8%AD%E5%AE%9A%E5%A4%89%E6%9B%B4%E8%BF%BD%E5%8A%A0%E3%83%AC%E3%83%AB%E3%83%A0%E3%81%AE%E7%AE%A1%E7%90%86%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E8%BF%BD%E5%8A%A0)
・[KeycloakをALB+EC2構成で構築してみた](https://dev.classmethod.jp/articles/tried-building-keycloak-with-alb-and-ec2/)
HTTPS接続できるようにするため、ALBをSSL終端にしたいです。 証明書にはACMを利用します。 ACMを作成する場合、DNSにRoute53を利用した方が楽なので、Route53も利用します。
・[サンプルアプリケーションでKeycloakのSSO動作を確認してみよう](https://atmarkit.itmedia.co.jp/ait/articles/1710/04/news008.html)
デフォルト設定でKeycloakを起動した場合は、ローカルの「http://localhost:8080/auth」からのみアクセスすることができます。外部のリモートマシンからはアクセスできません。Keycloakを起動したサーバ以外のマシンからWebブラウザでリモートアクセスする場合は、「bin/standalone.sh」を実行する際、以下のように「-b」オプションを付けて起動する必要があります。
・["HTTPS required" while logging in to Keycloak as admin](https://stackoverflow.com/questions/30622599/https-required-while-logging-in-to-keycloak-as-admin)
・