035. Keycloak.


Keycloak là một giải pháp quản lý danh tính và truy cập mã nguồn mở. Hướng dẫn này sẽ dẫn bạn qua các bước thiết lập Keycloak với Docker, tích hợp nó với phần frontend ReactJS.
1. Setting Up Keycloak with Docker
Đầu tiên là tạo container Keycloak:
docker run -d \
--name keycloak \
-p 8080:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:24.0.3 \
start-dev
- Truy cập Keycloak Dashboard tại http://localhost:8080
- Với tài khoản là
admin
/admin
- Nhớ là cái version của Keycloak phải khớp với version của keycloak-js
2.1. Tạo Admin
Ngay lần đầu tiên login, hãy tạo một user admin mới.
Users > Add user > Điền User name > Create
Thêm role admin cho user mới:
Role mapping > Assign role > Filter by realm roles > Chọn admin và nhấn Assign
2.2. Tạo Realm
Realm là có thể hiểu là một đơn vị, dùng để nhóm các user, setting của bạn cho một project.
Manage realms > Điền Realm name > Create
2.3 Tạo Client
Client là ứng dụng của bạn, có thể là một web app, mobile app, hoặc một API. Ở tab navigation, chọn Clients > Create client.
- Client Id:
project-name-dev
(hoặc tên khác tùy ý) - Valid redirect URIs:
http://localhost:5173/*
- Web origins:
http://localhost:5173
- Và
save
lại.
2.4. Tạo Test user
Tương tự bước tạo admin, và bỏ qua phần assign role.
Sau khi tạo xong, vào phần Credentials để tạo mật khẩu cho user.
3. ReactJS Frontend Integration
Install Keycloak JS adapter:
npm create vite@latest test-keycloak -- --template react
npm install keycloak-js
npm install @react-keycloak/web
// src/keycloak.jsx
import Keycloak from 'keycloak-js'
const keycloakConfig = {
url: 'http://localhost:8080',
realm: 'nolan',
clientId: 'react-dev',
};
const keycloakInst = new Keycloak(keycloakConfig);
export default keycloakInst
// src/App.jsx
import { useState, useEffect } from 'react'
import './App.css'
import { useKeycloak } from '@react-keycloak/web';
function App() {
const [infoMessage, setInfoMessage] = useState('');
const { keycloak, initialized } = useKeycloak();
useEffect(() => {
if (keycloak?.authenticated) {
keycloak.loadUserProfile()
.then(profile => {
const userInfo = `
User Info:
Name: ${profile.firstName} ${profile.lastName}
Email: ${profile.email}
Username: ${profile.username}
Token: ${keycloak.token}`;
setInfoMessage(userInfo);
});
}
}, [keycloak?.authenticated]);
if (!initialized) {
return <div>Loading authentication…</div>;
}
return (
<div className="app">
<h1>My Secured React App</h1>
<div className="container">
{!keycloak.authenticated && (
<div
onClick={() => { keycloak.login() }}
className="button success"
>
Login
</div>
)}
{keycloak.authenticated && (
<div
onClick={() => { keycloak.logout({ redirectUri: 'http://localhost:5173/' }) }}
className="button danger"
>
Logout
</div>
)}
<div className="info-card">
<p>
{infoMessage || (keycloak.authenticated ? 'Loading user info...' : 'Please log in')}
</p>
</div>
</div>
</div>
);
}
export default App;
// src.main.jsx
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
import keycloakInst from './keycloak';
import { ReactKeycloakProvider } from '@react-keycloak/web';
const initOptions = { onLoad: 'check-sso' };
createRoot(document.getElementById('root')).render(
<ReactKeycloakProvider authClient={keycloakInst} initOptions={initOptions}>
<App />
</ReactKeycloakProvider>,
)
.App {
max-width: 800px;
margin: 0 auto;
padding: 20px;
text-align: center;
}
.container {
margin-top: 20px;
}
.button {
padding: 10px 20px;
border-radius: 4px;
color: white;
cursor: pointer;
margin: 10px;
display: inline-block;
}
.success {
background-color: #22c55e;
}
.danger {
background-color: #ef4444;
}
.info-card {
background-color: #f5f5f5;
padding: 20px;
margin-top: 20px;
border-radius: 4px;
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
.info-card p {
white-space: pre-line;
margin: 0;
color: #333333;
line-height: 1.5;
word-break: break-word;
overflow-wrap: break-word;
}
Comments