keycloak-js Content Security Policyにはまった話

# はじめに

認証サーバーとして`keycloak`を使おうと思い、
`docker`でkeycloakを起動し、
アプリケーションを`Vite`で構築し、
「さあ認証だ！」というところで

<font color="red">Refused to frame 'http://localhost:8080/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'self'".</font>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/1a0d7051-d50e-5283-8859-cf2f15d2e874.png)

に悩まされた話です。

# 開発環境構築

## keycloak docker

1. docker-compose.ymlに以下を記入

    ```yaml:docker-compose.yml
    version: '2'
    services:
      postgresql:
        image: docker.io/bitnami/postgresql:11
        environment:
          - ALLOW_EMPTY_PASSWORD=yes
          - POSTGRESQL_USERNAME=bn_keycloak
          - POSTGRESQL_DATABASE=bitnami_keycloak
        volumes:
          - 'postgresql_data:/bitnami/postgresql'
    
      keycloak:
        image: docker.io/bitnami/keycloak:19
        depends_on:
          - postgresql
        ports:
          - "8080:8080"
    
    volumes:
      postgresql_data:
        driver: local
    ```

1. 起動

    ```bash
    $ docker-compose up
    ```

1. [http://localhost:8080](http://localhost:8080)に移動し、以下を登録(keycloakの詳しい説明は割愛)

* レルム
    * myrealm
* client_id
    * app-vue

## Vite + Vue3

* node v16.13.2

1. 以下を実行
    
    ```bash
    $ npm init vite@latest
      バージョンの確認: y
      アプリ名: (お好きに)
      フレームワーク: Vue ⇒ TypeScript
    
    $ cd (アプリ名)
    $ yarn
    ```

1. vite.config.tsの修正

    ```typescript
    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    
    // https://vitejs.dev/config/
    export default defineConfig({
      plugins: [vue()],
      server: {        // 追加
        host: true,    // 追加
        port: 18080    // 追加
      }                // 追加
    })
    ```

1. サーバー起動

    ```bash
    $ yarn dev
    ```

# keycloak-jsの導入・設定

1. `keycloak-js`のインストール

    ```bash
    $ yarn add keycloak-js
    ```

1. .envの設定
    
    ```env:.env
    VITE_KEYCLOAK_URL="http://localhost:8080"
    VITE_KEYCLOAK_REALM="Myrealm"
    VITE_KEYCLOAK_CLIENT_ID="app-vue"
    ```


1. 設定ファイルの作成

    ```typescript: src/keycloak.ts
    import Keycloak from "keycloak-js";
    
    const initOptions = {
      url: import.meta.env.VITE_KEYCLOAK_URL,
      realm: import.meta.env.VITE_KEYCLOAK_REALM,
      clientId: import.meta.env.VITE_KEYCLOAK_CLIENT_ID
    }
    
    const keycloakInstance = new Keycloak(initOptions);
    
    interface CallbackOneParam<T1 = void, T2 = void> {
      (param1: T1): T2;
    }
    
    const Login = (onAuthenticatedCallback: CallbackOneParam) => {
      keycloakInstance
        .init({ onLoad: "login-required" })
        .then(function (authenticated) {
          authenticated ? onAuthenticatedCallback() : alert("non authenticated");
        })
        .catch((e) => {
          console.dir(e);
          console.log(`keycloak init exception: ${e}`);
        });
    };
    
    const KeyCloakService = {
      CallLogin: Login,
    };
    
    export default KeyCloakService;
    ```

1. main.tsを修正し、ログインしないと表示されないように

```typescript
import { createApp } from 'vue'
import App from './App.vue'
import { loadFonts } from './plugins/webfontloader'
import KeyCloakService from './KeycloakService'

loadFonts()

const renderApp = () => {
  createApp(App)
    .mount('#app')
}

KeyCloakService.CallLogin(renderApp)
```

## ここでエラー発生。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/1a0d7051-d50e-5283-8859-cf2f15d2e874.png)

`vite.config.ts`を修正し、Content Security Policyの設定をしてみましたが、うまくいかず途方に暮れていたところ、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/b7fcdc2c-6db5-daa1-dcc7-fed20d05d577.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/1f2b1309-5142-23c6-cf5a-d245e4341343.png)

<font color="red">あれ？小文字じゃん。。。</font>

ということでkeycloakではレルム名で大文字小文字を間違えると上記エラーが発生するようです。

沼にはまらないように気を付けましょう～！