ssr-keycloak
Version:
SSR compatible Keycloak authentication library for React applications
189 lines (188 loc) • 5.82 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSessionFromRequest = getSessionFromRequest;
exports.setSessionInResponse = setSessionInResponse;
exports.clearSessionInResponse = clearSessionInResponse;
exports.isSessionValid = isSessionValid;
exports.refreshSession = refreshSession;
exports.createNewSession = createNewSession;
exports.updateSession = updateSession;
exports.getUserRolesFromSession = getUserRolesFromSession;
exports.hasRoleInSession = hasRoleInSession;
exports.hasAnyRoleInSession = hasAnyRoleInSession;
exports.hasAllRolesInSession = hasAllRolesInSession;
const crypto_1 = __importDefault(require("crypto"));
const SESSION_COOKIE_NAME = 'ssr_keycloak_session';
const SESSION_SECRET = process.env.KEYCLOAK_SESSION_SECRET || 'default-secret-change-in-production';
/**
* Session'ı şifreler
*/
function encryptSession(session) {
const cipher = crypto_1.default.createCipher('aes-256-cbc', SESSION_SECRET);
let encrypted = cipher.update(JSON.stringify(session), 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
/**
* Session'ı şifresini çözer
*/
function decryptSession(encryptedSession) {
try {
const decipher = crypto_1.default.createDecipher('aes-256-cbc', SESSION_SECRET);
let decrypted = decipher.update(encryptedSession, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return JSON.parse(decrypted);
}
catch (error) {
console.error('Session decryption failed:', error);
return null;
}
}
/**
* Session cookie'sini oluşturur
*/
function createSessionCookie(session) {
const encryptedSession = encryptSession(session);
return {
name: SESSION_COOKIE_NAME,
value: encryptedSession,
expires: new Date(session.expiresAt),
maxAge: Math.floor((session.expiresAt - Date.now()) / 1000),
path: '/',
secure: process.env.NODE_ENV === 'production',
httpOnly: true,
sameSite: 'lax'
};
}
/**
* Request'ten session'ı okur
*/
function getSessionFromRequest(request) {
const sessionCookie = request.cookies[SESSION_COOKIE_NAME];
if (!sessionCookie) {
return null;
}
const session = decryptSession(sessionCookie);
if (!session) {
return null;
}
// Session'ın geçerli olup olmadığını kontrol et
if (Date.now() >= session.expiresAt) {
return null;
}
return session;
}
/**
* Session'ı response'a yazar
*/
function setSessionInResponse(session, response) {
const cookie = createSessionCookie(session);
response.setCookie(cookie);
}
/**
* Session'ı response'dan siler
*/
function clearSessionInResponse(response) {
response.deleteCookie(SESSION_COOKIE_NAME);
}
/**
* Session'ın geçerli olup olmadığını kontrol eder
*/
function isSessionValid(session) {
if (!session)
return false;
return Date.now() < session.expiresAt;
}
/**
* Session'ı yeniler (lastActivity günceller)
*/
function refreshSession(session) {
return {
...session,
lastActivity: Date.now()
};
}
/**
* Yeni session oluşturur
*/
function createNewSession(userId, tokens, user, realm, clientId, expiresIn = 3600) {
const now = Date.now();
return {
sessionId: userId, // Keycloak user ID'yi session ID olarak kullan
userId,
tokens: {
accessToken: tokens.access_token,
refreshToken: tokens.refresh_token,
idToken: tokens.id_token,
expiresAt: now + (tokens.expires_in * 1000),
refreshExpiresAt: now + (tokens.refresh_expires_in * 1000)
},
user: {
id: user.sub,
username: user.preferred_username || user.username || '',
email: user.email,
firstName: user.given_name,
lastName: user.family_name,
fullName: user.name,
roles: user.roles || [],
groups: user.groups || [],
emailVerified: user.email_verified || false,
enabled: user.enabled !== false,
realmAccess: {
roles: user.realm_access?.roles || []
},
resourceAccess: user.resource_access || {}
},
realm,
clientId,
lastActivity: now,
expiresAt: now + (expiresIn * 1000)
};
}
/**
* Session'ı günceller
*/
function updateSession(currentSession, updates) {
return {
...currentSession,
...updates,
lastActivity: Date.now()
};
}
/**
* Session'dan kullanıcı rollerini alır
*/
function getUserRolesFromSession(session, resource) {
if (!session)
return [];
if (resource) {
return session.user.resourceAccess[resource]?.roles || [];
}
return [...session.user.realmAccess.roles, ...session.user.roles];
}
/**
* Session'da belirli bir rol olup olmadığını kontrol eder
*/
function hasRoleInSession(session, role, resource) {
if (!session)
return false;
if (resource) {
return session.user.resourceAccess[resource]?.roles?.includes(role) || false;
}
return session.user.realmAccess.roles.includes(role) || session.user.roles.includes(role);
}
/**
* Session'da belirli rollerden herhangi biri olup olmadığını kontrol eder
*/
function hasAnyRoleInSession(session, roles, resource) {
return roles.some(role => hasRoleInSession(session, role, resource));
}
/**
* Session'da belirli rollerin hepsinin olup olmadığını kontrol eder
*/
function hasAllRolesInSession(session, roles, resource) {
return roles.every(role => hasRoleInSession(session, role, resource));
}
;