可以先在預設叫做master的realm下建立新的使用者

建議關掉Temporary的選項,這樣可以避免第一次登入就要求使用者更新密碼

如果想要進一步的去設定使用者資訊的話可以到account console去

要透過設定client才能去允許不同的連線方式

記得要設定Valid Redirect URIs不然之後會出錯,加上底下兩個
http://localhost:3000https://www.keycloak.org/*redhat提供的測試網頁讓你知道是不是有正確的設定好keycloak user帳號

如果測試的頁面會出現CORS error就要去client的Web Origins加上*
用http://localhost:8080/realms/{realm-name}/.well-known/openid-configuration來查

Keycloak官方有提供一些小範例專案可以去測試剛架的keycloak server
不論是Java或是Node.js版都會用到keycloak提供的SDK
const express = require('express');
const session = require('express-session');
const Keycloak = require('keycloak-connect');
const app = express();
const memoryStore = new session.MemoryStore();
const keycloak = new Keycloak({
store: memoryStore
});
app.get('/service/admin', keycloak.protect('realm:admin'), function (req, res) {
res.json({message: 'admin'});
});
app.listen(3000, function () {
console.log('Started at port 3000');
});
keycloak-connect吃的設定都要放在keycloak.json內
{
"realm": "quickstart",
"bearer-only": true,
"auth-server-url": "http://localhost:8180/auth",
"ssl-required": "external",
"resource": "service-nodejs"
}
用Postman來獲取之後call其他endpoint會需要的token

可以到JWT的官網去查看拿到的token意思

可以透過OAuth自動產生token,就不用先去POST token endpoint

Postman和Thunder Client使用OAuth時都得去client的validate redirect uri設定
https://www.thunderclient.com/oauth/callbackhttps://oauth.pstmn.io/v1/callback
由於剛剛設定的OAuth會自動記住token,所以call其他受保護的endpoint就不會報錯

由於實作上處理Keycloak給的資訊會有些複雜,我們可以透過plugin快速的完成登入驗證
安裝方式是npm i fastify-keycloak-adapter
// server.js
import fastify from 'fastify'
import keycloak, { KeycloakOptions } from 'fastify-keycloak-adapter'
const server = fastify()
const opts = {
appOrigin: 'http://localhost:3000', // fastify server ip and port
keycloakSubdomain: 'localhost:8080/realms/master',
clientId: 'myclient',
// clientSecret: 'client01secret'
}
server.register(keycloak, opts)
有一點要注意的是等等要用的fastify plugin官方範例是使用舊版URL
所以我們要重開一台fastify server並用較舊的版本
docker run -d -p 8080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin quay.io/keycloak/keycloak:15.0.0
舊版的url會長的類似
http://localhost:8080/auth/realms/{realm-name}/.well-known/openid-configuration
官方的舊版範例
// server.js
import fastify from 'fastify'
import keycloak, { KeycloakOptions } from 'fastify-keycloak-adapter'
const server = fastify()
const opts = {
appOrigin: 'http://localhost:3000',
keycloakSubdomain: 'localhost:8080/auth/realms/master',
clientId: 'myclient',
// clientSecret: 'client01secret'
}
server.register(keycloak, opts)
要將Access Type改成confidential才會有client secret的欄位

// return user info
server.get('/users/me', async (request, reply) => {
const user = request.session.user
return reply.status(200).send({ user })
})
logout已經被寫在plugin內,只要callhttp://localhost:3000/logout就好
這邊主要是讓react在initial render時就去call受到keycloak保護的endpoint
實際上當我們call受到保護但沒登入的endpoint時,就會被跳轉到keycloak的登入頁面了
其實Keycloak的SSO是支援跨subdomain去做登入的,但是為了避免遇到CORS的問題
會建議build好react專案後去給fastify serve
要先安裝套件npm i @fastify/static
還要透過npm run build去react專案下產生靜態的網頁
const path = require('path')
fastify.register(require('@fastify/static'), {
root: path.join(__dirname, 'public'),
prefix: '/public', // optional: default '/'
})
fastify.get('/public', function(req, rep){
rep.sendFile('index.html')
})
如果prefix有設定的話,AppOrigin和react的package.json中的homepage也得跟著異動
目前在console還是會看到error,可以去修改public/index.html

<link rel="manifest" href="%PUBLIC_URL%/manifest.json" crossorigin="use-credentials" />
manifest link最後面的地方加上crossorigin="use-credentials"
或是可以去裝Allow CORS的chrome插件來自動隱藏
如果前後端真的要用不同port或許可以考慮分開使用client
或是用nginx強制keycloak server的response會多出對的cors header
fetch前先套上proxy也是可能的解法之一
docker exec -it kc /opt/keycloak/bin/kc.sh export --realm master \
--file /tmp/master.json
指令中的--dir和--file必須要擇一,也可以使用GUI來輸出

docker exec -it kc bin/kc.sh import --file