- 検証用にVue.jsアプリとDocker起動しているKeycloakを接続してみたため、手順をメモしておく。
構成
keycloak_test - docker-compose.yml
- fe - app-vue
Keycloakコンテナ作成
docker-compose.ymlの準備
-
docker-compose.yml
- Keycloak起動用
version: "3" volumes: mysql_data: driver: local services: mysql: image: mysql:5.7 volumes: - mysql_data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: keycloak MYSQL_USER: keycloak MYSQL_PASSWORD: password keycloak: image: quay.io/keycloak/keycloak:latest container_name: "keycloak" environment: DB_VENDOR: MYSQL DB_ADDR: mysql DB_DATABASE: keycloak DB_USER: keycloak DB_PASSWORD: password KEYCLOAK_USER: admin KEYCLOAK_PASSWORD: P@ssw0rd ports: - 8080:8080 depends_on: - mysql
コンテナ起動
docker-compose up
Keycloak設定
-
http://localhost8080
からAdmin Consoleにアクセスする。認証情報は、docker-compose.ymlを参照のこと。 - こちらの手順(「Create a realm」から...)に従い、Keycloak設定を行う。
Vue.js フロント部分作成
プロジェクト作成
cd fe
vue init webpack-simple app-vue
※すべてデフォルトを選択する。
依存ライブラリインストール
npm i keycloak-js --save
npm i vuejs-logger --save
コード修正
-
こちらを参考にmain.js,App.vueを修正する。
-
main.js
-
initOptions
に対して、以下の修正を行っている。-
realm
:自環境に合わせて修正 -
CheckLoginiframe
:追加
-
import Vue from 'vue' import App from './App.vue' import VueLogger from 'vuejs-logger'; import * as Keycloak from 'keycloak-js'; Vue.use(VueLogger); let initOptions = { url: 'http://127.0.0.1:8080/auth', realm: 'myrealm', clientId: 'app-vue', onLoad: 'login-required',CheckLoginiframe:false } let keycloak = Keycloak(initOptions); keycloak.init({ onLoad: initOptions.onLoad, checkLoginIframe:initOptions.CheckLoginiframe }).then((auth) => { if (!auth) { window.location.reload(); } else { Vue.$log.info("Authenticated"); new Vue({ el: '#app', render: h => h(App, { props: { keycloak: keycloak } }) }) } //Token Refresh setInterval(() => { keycloak.updateToken(70).then((refreshed) => { if (refreshed) { Vue.$log.info('Token refreshed' + refreshed); } else { Vue.$log.warn('Token not refreshed, valid for ' + Math.round(keycloak.tokenParsed.exp + keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds'); } }).catch(() => { Vue.$log.error('Failed to refresh token'); }); }, 6000) }).catch(() => { Vue.$log.error("Authenticated Failed"); });
-
-
App.vue
<template> <div id="app"> <img src="./assets/logo.png" /> <h1>{{ msg }}</h1> <h2>User: {{ keycloak.idTokenParsed.preferred_username }}</h2> <div> <button class="btn" @click="keycloak.logout()">Logout</button> </div> <div id="wrapper"> <div class="jwt-token"> <h3 style="color: black">JWT Token</h3> {{ keycloak.idToken }} </div> <div class="jwt-token"> <h3 style="color: black">Info</h3> <ul> <li>clientId: {{ keycloak.clientId }}</li> <li>Auth Server Url: {{ keycloak.authServerUrl }}</li> </ul> </div> </div> <h2>Essential Links</h2> <ul> <li><a href="https://keycloak.org" target="_blank">Keycloak</a></li> <li> <a href="https://github.com/keycloak/keycloak-quickstarts" target="_blank" >Code Repo</a > </li> <li> <a href="https://twitter.com/keycloak" target="_blank">Twitter</a> </li> </ul> </div> </template> <script> export default { name: "app", props: ["keycloak"], data() { return { msg: "Welcome to Your Secured Vue.js App with Keycloak", }; }, }; </script> <style> #app { font-family: "Avenir", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: block; margin: 0 10px; color: #333; font-size: 20px; } a { color: #42b983; } #wrapper { display: flex; margin-top: 100px; } .jwt-token { width: 50%; display: block; padding: 20px; margin: 10 0 10px; font-size: 13px; line-height: 1.42857143; color: #333; word-break: break-all; word-wrap: break-word; background-color: #f5f5f5; border: 1px solid #ccc; border-radius: 4px; color: #d63aff; font-weight: bolder; } .btn { color: #fff; background-color: #0088ce; border-color: #00659c; padding: 6px 10px; font-size: 14px; line-height: 1.3333333; border-radius: 1px; } </style>
動作確認
-
起動
npm run dev -- --port 3000
-
(Keycloakエンドポイントにリダイレクトされるので、)ユーザー認証情報を入力する※上記「Keycloak設定」で登録した値。
-
以下の画面が表示される。