EramCloud SSO
راهنمای اتصال پنلها و وبسایتها
این صفحه برای ادمین و برنامهنویس پروژههای دیگر است. طبق همین سند، ورود با نام کاربری و رمز را از پنل خودتان بردارید و به Identity Provider مرکزی روی sso.eramcloud.com وصل شوید. کاربر یکبار در پورتال لاگین میکند؛ بعد با کلیک روی لوگو، بدون رمز دوباره وارد داشبورد شما میشود.
۱) معرفی
پروتکل: OpenID Connect روی OAuth 2.0 با Authorization Code. اپ شما هرگز username/password کاربر را نمیگیرد. فقط یک code میگیرد، آن را در سمت سرور با client_secret عوض میکند، و از روی توکن session محلی میسازد.
- رمز عبور فقط در پورتال SSO وارد میشود.
client_secretفقط در Backend پنل شما بماند؛ در مرورگر و فرانت نگذارید.- اگر کاربر در پورتال به سرویس شما دسترسی نداشته باشد، حتی با دانستن URL هم وارد نمیشود.
۲) ثبت سرویس در پورتال
مدیر SSO باید سرویس شما را در مدیریت سرویسها ثبت کند و این مقادیر را به شما بدهد:
| نام و لوگو | همان چیزی که در Homepage دیده میشود |
| Client ID | شناسه OIDC سرویس شما |
| Client Secret | فقط یکبار نمایش داده میشود؛ در سرور خودتان ذخیره کنید |
| Redirect URI | مثلاً https://panel.eramcloud.com/sso/callback — باید دقیقاً همین باشد |
| حالت ورود | از پورتال (idp) تا کلیک روی لوگو مستقیم به callback شما برسد |
اولین Redirect URI برای کلیک روی لوگو استفاده میشود. بعد از ثبت، مدیر SSO باید در صفحه کاربر، تیک دسترسی همین سرویس را بزند.
۳) آدرسهای SSO
Discovery:
https://sso.eramcloud.com/.well-known/openid-configuration| نقش | آدرس |
|---|---|
| Authorize | https://sso.eramcloud.com/oauth/authorize |
| Token | https://sso.eramcloud.com/oauth/token |
| UserInfo | https://sso.eramcloud.com/oauth/userinfo |
| JWKS | https://sso.eramcloud.com/oauth/jwks |
| Logout | https://sso.eramcloud.com/logout |
| کلیک لوگو | https://sso.eramcloud.com/launch/<slug> |
۴) دو روش ورود
الف) از Homepage پورتال (پیشنهادی)
کاربر روی لوگوی سرویس شما کلیک میکند. پورتال یک code میسازد و به اولین Redirect URI شما میفرستد:
$REDIRECT_URI?code=...&state=eram-sso-launchهمین کافی است که callback را پیاده کنید. فرم لاگین پنل شما نباید وسط کار بیاید.
ب) کاربر مستقیم وارد پنل شما شود
اگر session محلی ندارد، او را به Authorize بفرستید. اگر قبلاً در پورتال لاگین باشد، فرم رمز SSO هم نشان داده نمیشود:
GET https://sso.eramcloud.com/oauth/authorize
?client_id=YOUR_CLIENT_ID
&redirect_uri=https%3A%2F%2FYOUR-APP%2Fsso%2Fcallback
&response_type=code
&scope=openid%20profile%20email
&state=RANDOM_CSRF_TOKENstate را خودتان بسازید و بعد از برگشت چک کنید. مقدار redirect_uri باید با مقدار ثبتشده در پورتال حرفبهحرف یکی باشد.
۵) پیادهسازی Callback
در مسیر callback (سمت سرور):
- اگر
error=access_deniedبود، صفحه «دسترسی ندارید» نشان دهید. codeرا بخوانید. اعتبار آن حدود ۲ دقیقه است و یکبارمصرف است.- با درخواست زیر توکن بگیرید. این درخواست فقط از Backend زده شود.
POST https://sso.eramcloud.com/oauth/token
Content-Type: application/json
{
"grant_type": "authorization_code",
"code": "CODE_FROM_QUERY",
"redirect_uri": "https://YOUR-APP/sso/callback",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET"
}پاسخ موفق:
{
"access_token": "...",
"id_token": "...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "openid profile email"
}نمونه Node.js:
app.get("/sso/callback", async (req, res) => {
if (req.query.error) {
return res.status(403).send("دسترسی به این سرویس ندارید.");
}
const tokenRes = await fetch("https://sso.eramcloud.com/oauth/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
grant_type: "authorization_code",
code: req.query.code,
redirect_uri: process.env.SSO_REDIRECT_URI,
client_id: process.env.SSO_CLIENT_ID,
client_secret: process.env.SSO_CLIENT_SECRET,
}),
});
if (!tokenRes.ok) return res.status(401).send("ورود SSO ناموفق بود.");
const tokens = await tokenRes.json();
const userRes = await fetch("https://sso.eramcloud.com/oauth/userinfo", {
headers: { Authorization: "Bearer " + tokens.access_token },
});
const profile = await userRes.json();
// session محلی بسازید؛ دیگر username/password نخواهید
req.session.user = {
id: profile.sub,
username: profile.preferred_username,
email: profile.email,
name: profile.name,
role: profile.role,
};
res.redirect("/dashboard");
});نمونه PHP:
<?php
$code = $_GET["code"] ?? "";
if (!$code) { http_response_code(403); exit("دسترسی ندارید"); }
$ch = curl_init("https://sso.eramcloud.com/oauth/token");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode([
"grant_type" => "authorization_code",
"code" => $code,
"redirect_uri" => getenv("SSO_REDIRECT_URI"),
"client_id" => getenv("SSO_CLIENT_ID"),
"client_secret" => getenv("SSO_CLIENT_SECRET"),
]),
]);
$tokens = json_decode(curl_exec($ch), true);
$ch = curl_init("https://sso.eramcloud.com/oauth/userinfo");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer ".$tokens["access_token"]],
]);
$profile = json_decode(curl_exec($ch), true);
$_SESSION["sso_user"] = $profile;
header("Location: /admin");میتوانید بهجای UserInfo، id_token را با کلیدهای https://sso.eramcloud.com/oauth/jwks و الگوریتم RS256 و kid=eram-sso-1 هم verify کنید. Issuer باید دقیقاً https://sso.eramcloud.com و Audience همان Client ID شما باشد.
۶) اطلاعات کاربر
این فیلدها در access token، id_token و UserInfo میآید:
| Claim | معنی |
|---|---|
| sub | شناسه پایدار کاربر در SSO؛ برای مپ کردن اکانت داخلی از این استفاده کنید |
| preferred_username | نام کاربری پورتال |
| ایمیل | |
| name | نام نمایشی |
| role | نقش داخل سرویس شما؛ همان مقداری که ادمین SSO هنگام دادن دسترسی نوشته |
| app | slug سرویس |
کاربر داخلی را با sub بسازید یا بهروز کنید. پسورد جدا در دیتابیس پنل لازم نیست. سطح دسترسی داخل داشبورد را از role بخوانید.
۷) چکلیست پنل اختصاصی و ادمین وبسایت
- مسیر
/sso/callback(یا معادل) فقط سمت سرور پیاده شود. - اگر کاربر مستقیم به داشبورد آمد و session نداشت، به Authorize ریدایرکت شود؛ فرم رمز محلی نشان داده نشود.
- فرم لاگین قدیمی را غیرفعال کنید یا فقط برای اضطرار نگه دارید.
- متغیرهای محیطی:
SSO_CLIENT_ID،SSO_CLIENT_SECRET،SSO_REDIRECT_URI،SSO_ISSUER=https://sso.eramcloud.com - برای بخش ادمین سایت، کل
/adminرا پشت همین SSO بگذارید. - خروج از پنل، session محلی را پاک کند. خروج سراسری از پورتال: https://sso.eramcloud.com/logout
۸) خطاهای رایج
| نشانه | علت معمول |
|---|---|
| invalid_redirect_uri | آدرس callback با مقدار ثبتشده یکی نیست (حتی اسلش آخر یا http/https) |
| invalid_client | Client ID/Secret اشتباه است یا سرویس در پورتال غیرفعال شده |
| access_denied | برای این کاربر تیک دسترسی این سرویس زده نشده |
| invalid_grant | code منقضی، تکراری، یا redirect_uri در توکن با authorize فرق دارد |
| لوگو فرم لاگین پنل را باز میکند | حالت ورود باید idp باشد و callback همان اولین Redirect URI |
لینک قابل ارسال برای تیمهای دیگر: https://sso.eramcloud.com/docs