- 検証用に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設定」で登録した値。
以下の画面が表示される。