mirror of
https://18126008609:longquanjian123@gitee.com/feigong123/aurask.git
synced 2026-04-19 16:18:24 +00:00
Remove LY SSO sign-in flow
All checks were successful
aurask-release / build-and-deploy (push) Successful in 1m52s
All checks were successful
aurask-release / build-and-deploy (push) Successful in 1m52s
This commit is contained in:
parent
c44746a5a8
commit
4e2639ea43
@ -10,7 +10,7 @@ Aurask 当前处于 **可运行 MVP / 初版门户** 阶段,已覆盖:
|
||||
- Python 模块化后端
|
||||
- 标准库 HTTP Gateway
|
||||
- 租户、用户、API Key、Session
|
||||
- `LY SSO` / Google 登录入口
|
||||
- Google 登录入口
|
||||
- 首次登录自动创建独立 workspace
|
||||
- 配额 / TBU / 订单 / 支付闭环
|
||||
- 工作流模板编排
|
||||
@ -92,7 +92,6 @@ Browser
|
||||
未登录:
|
||||
|
||||
- 渲染 `/signin`
|
||||
- 提供 `Use LY SSO`
|
||||
- 提供 `Continue with Google`
|
||||
|
||||
已登录:
|
||||
@ -107,11 +106,7 @@ Browser
|
||||
|
||||
当前支持:
|
||||
|
||||
1. `LY SSO`
|
||||
- 以按钮形式进入
|
||||
- 当前实现为配置驱动的本地接入层
|
||||
- 通过 `AURASK_LY_SSO_USERNAME` / `AURASK_LY_SSO_PASSWORD` 控制
|
||||
2. Google
|
||||
1. Google
|
||||
- 通过 `AURASK_GOOGLE_CLIENT_ID` 开启
|
||||
- 首次注册后自动开通独立 tenant + user + workspace
|
||||
|
||||
@ -153,7 +148,7 @@ Browser
|
||||
- 公网域名
|
||||
- API 地址
|
||||
- Langflow / AnythingLLM 嵌入地址
|
||||
- `LY SSO` / Google 开关
|
||||
- Google 开关
|
||||
- DevCloud 镜像 / NodePort 默认值
|
||||
|
||||
### `knowledge_base.py`
|
||||
@ -180,7 +175,6 @@ Browser
|
||||
GET /health
|
||||
GET /plans
|
||||
GET /auth/config
|
||||
POST /auth/ly-sso/login
|
||||
POST /auth/google/login
|
||||
POST /demo/bootstrap
|
||||
POST /tenants
|
||||
@ -307,7 +301,6 @@ python -m unittest discover -s tests -v
|
||||
|
||||
- MVP 核心业务闭环
|
||||
- 桥接配置契约
|
||||
- `LY SSO` 登录
|
||||
- Google 首次登录建 workspace
|
||||
- Session 认证
|
||||
|
||||
|
||||
@ -10,8 +10,7 @@ Aurask 当前是一个按产品边界拆分的首版实现,根目录保持为
|
||||
当前版本已经补齐了用户门户登录闭环:
|
||||
|
||||
- `/signin` 风格化登录页
|
||||
- `LY SSO` 登录入口
|
||||
- Google 首次注册/登录后自动创建用户独立 workspace
|
||||
- Google 首次注册/登录后自动创建独立 workspace
|
||||
- 登录后双标签页工作台:
|
||||
- `Workflows` 内嵌 `Langflow`
|
||||
- `Knowledge Base` 内嵌 `AnythingLLM`
|
||||
@ -42,7 +41,6 @@ py -3 -m aurask demo --reset
|
||||
- `GET /health`
|
||||
- `GET /plans`
|
||||
- `GET /auth/config`
|
||||
- `POST /auth/ly-sso/login`
|
||||
- `POST /auth/google/login`
|
||||
- `POST /demo/bootstrap`
|
||||
- `POST /tenants`
|
||||
@ -77,9 +75,6 @@ AURASK_PUBLIC_BASE_URL=https://aurask.xyz
|
||||
AURASK_PUBLIC_API_BASE_URL=https://aurask.xyz/api
|
||||
AURASK_PUBLIC_LANGFLOW_URL=https://aurask.xyz/runtime/langflow/
|
||||
AURASK_PUBLIC_ANYTHINGLLM_URL=https://aurask.xyz/runtime/anythingllm/
|
||||
AURASK_LY_SSO_ENABLED=true
|
||||
AURASK_LY_SSO_USERNAME=ly-xujian1
|
||||
AURASK_LY_SSO_PASSWORD=<inject-secret>
|
||||
AURASK_GOOGLE_ENABLED=true
|
||||
AURASK_GOOGLE_CLIENT_ID=<google-client-id>
|
||||
AURASK_SESSION_TTL_DAYS=7
|
||||
@ -124,7 +119,7 @@ cmd /c "py -3 -m unittest discover -s tests -v"
|
||||
|
||||
- MVP 业务闭环
|
||||
- PostgreSQL / PGVector / Redis / AnythingLLM / Langflow 桥接契约
|
||||
- `LY SSO` / Google 登录与 session
|
||||
- Google 登录与 session
|
||||
|
||||
## 相关文档
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
- 租户、用户、API Key、Session:`api/aurask/auth.py`
|
||||
- 套餐、订单、支付、TBU:`api/aurask/plans.py`、`api/aurask/billing.py`、`api/aurask/quota.py`
|
||||
- 工作流编排:`api/aurask/orchestrator.py`
|
||||
- AnythingLLM workspace / 文档接入:`api/aurask/knowledge_base.py`
|
||||
- AnythingLLM workspace / 文档接入门面:`api/aurask/knowledge_base.py`
|
||||
- PostgreSQL / PGVector / Redis / AnythingLLM / Langflow 桥接:`api/aurask/bridges/`
|
||||
- 门户站点配置:`api/aurask/site_config.py`
|
||||
|
||||
@ -22,7 +22,7 @@ Aurask 现在支持两类 Bearer Token:
|
||||
- 由创建租户/用户或 demo bootstrap 返回
|
||||
2. Session Token
|
||||
- 适用于 `protal/` 登录态
|
||||
- 由 `LY SSO` 或 Google 登录接口签发
|
||||
- 由 Google 登录接口签发
|
||||
|
||||
## 公开接口
|
||||
|
||||
@ -30,7 +30,6 @@ Aurask 现在支持两类 Bearer Token:
|
||||
GET /health
|
||||
GET /plans
|
||||
GET /auth/config
|
||||
POST /auth/ly-sso/login
|
||||
POST /auth/google/login
|
||||
POST /demo/bootstrap
|
||||
POST /tenants
|
||||
@ -60,7 +59,7 @@ GET /admin/bridge-status
|
||||
|
||||
- 公网站点地址
|
||||
- API 地址
|
||||
- `LY SSO` / Google 开关
|
||||
- Google 开关
|
||||
- Langflow / AnythingLLM iframe 地址
|
||||
- DevCloud 对齐后的镜像与 NodePort 默认值
|
||||
|
||||
@ -73,11 +72,6 @@ AURASK_PUBLIC_BASE_URL=https://aurask.xyz
|
||||
AURASK_PUBLIC_API_BASE_URL=https://aurask.xyz/api
|
||||
AURASK_PUBLIC_LANGFLOW_URL=https://aurask.xyz/runtime/langflow/
|
||||
AURASK_PUBLIC_ANYTHINGLLM_URL=https://aurask.xyz/runtime/anythingllm/
|
||||
AURASK_LY_SSO_ENABLED=true
|
||||
AURASK_LY_SSO_LOGIN_URL=
|
||||
AURASK_LY_SSO_USERNAME=ly-xujian1
|
||||
AURASK_LY_SSO_PASSWORD=<ly-sso-password>
|
||||
AURASK_LY_SSO_EMAIL_DOMAIN=ly.szlanyou.local
|
||||
AURASK_GOOGLE_ENABLED=true
|
||||
AURASK_GOOGLE_CLIENT_ID=<google-client-id>
|
||||
AURASK_GOOGLE_TOKENINFO_URL=https://oauth2.googleapis.com/tokeninfo
|
||||
|
||||
@ -50,10 +50,6 @@ def make_handler(app: AuraskApp):
|
||||
if method == "GET" and path == "/auth/config":
|
||||
self._send(200, app.public_auth_config())
|
||||
return
|
||||
if method == "POST" and path == "/auth/ly-sso/login":
|
||||
body = self._read_json()
|
||||
self._send(200, app.login_with_ly_sso(username=body.get("username", ""), password=body.get("password", "")))
|
||||
return
|
||||
if method == "POST" and path == "/auth/google/login":
|
||||
body = self._read_json()
|
||||
self._send(200, app.login_with_google(id_token=body.get("id_token", "")))
|
||||
|
||||
@ -54,22 +54,6 @@ class AuraskApp:
|
||||
def public_auth_config(self) -> dict:
|
||||
return self.site_config.public_dict()
|
||||
|
||||
def login_with_ly_sso(self, *, username: str, password: str) -> dict:
|
||||
if not self.site_config.ly_sso_enabled:
|
||||
raise AuthError("LY SSO is not enabled")
|
||||
if not self.site_config.ly_sso_password:
|
||||
raise AuthError("LY SSO password secret is not configured")
|
||||
if username != self.site_config.ly_sso_username or password != self.site_config.ly_sso_password:
|
||||
raise AuthError("invalid LY SSO credentials")
|
||||
email = os.getenv("AURASK_LY_SSO_EMAIL", f"{username}@{self.site_config.ly_sso_email_domain}")
|
||||
return self._sign_in_external_identity(
|
||||
provider="ly_sso",
|
||||
subject=username,
|
||||
email=email,
|
||||
display_name=username,
|
||||
avatar_url="",
|
||||
)
|
||||
|
||||
def login_with_google(self, *, id_token: str) -> dict:
|
||||
claims = self._verify_google_id_token(id_token)
|
||||
email = claims.get("email", "").strip().lower()
|
||||
|
||||
@ -17,11 +17,6 @@ class SiteConfig:
|
||||
public_api_base_url: str
|
||||
langflow_embed_url: str
|
||||
anythingllm_embed_url: str
|
||||
ly_sso_enabled: bool
|
||||
ly_sso_login_url: str
|
||||
ly_sso_username: str
|
||||
ly_sso_password: str
|
||||
ly_sso_email_domain: str
|
||||
google_enabled: bool
|
||||
google_client_id: str
|
||||
google_tokeninfo_url: str
|
||||
@ -40,11 +35,6 @@ class SiteConfig:
|
||||
public_api_base_url=os.getenv("AURASK_PUBLIC_API_BASE_URL", f"{public_base_url}/api").rstrip("/"),
|
||||
langflow_embed_url=os.getenv("AURASK_PUBLIC_LANGFLOW_URL", f"{public_base_url}/runtime/langflow/"),
|
||||
anythingllm_embed_url=os.getenv("AURASK_PUBLIC_ANYTHINGLLM_URL", f"{public_base_url}/runtime/anythingllm/"),
|
||||
ly_sso_enabled=_enabled("AURASK_LY_SSO_ENABLED", True),
|
||||
ly_sso_login_url=os.getenv("AURASK_LY_SSO_LOGIN_URL", ""),
|
||||
ly_sso_username=os.getenv("AURASK_LY_SSO_USERNAME", "ly-xujian1"),
|
||||
ly_sso_password=os.getenv("AURASK_LY_SSO_PASSWORD", ""),
|
||||
ly_sso_email_domain=os.getenv("AURASK_LY_SSO_EMAIL_DOMAIN", "ly.szlanyou.local"),
|
||||
google_enabled=_enabled("AURASK_GOOGLE_ENABLED", bool(os.getenv("AURASK_GOOGLE_CLIENT_ID", ""))),
|
||||
google_client_id=os.getenv("AURASK_GOOGLE_CLIENT_ID", ""),
|
||||
google_tokeninfo_url=os.getenv("AURASK_GOOGLE_TOKENINFO_URL", "https://oauth2.googleapis.com/tokeninfo"),
|
||||
@ -61,11 +51,6 @@ class SiteConfig:
|
||||
"public_base_url": self.public_base_url,
|
||||
"public_api_base_url": self.public_api_base_url,
|
||||
"auth": {
|
||||
"ly_sso": {
|
||||
"enabled": self.ly_sso_enabled,
|
||||
"login_url": self.ly_sso_login_url,
|
||||
"username_hint": self.ly_sso_username,
|
||||
},
|
||||
"google": {
|
||||
"enabled": self.google_enabled,
|
||||
"client_id": self.google_client_id,
|
||||
|
||||
@ -7,15 +7,6 @@ GET http://127.0.0.1:8080/plans
|
||||
### Portal auth config
|
||||
GET http://127.0.0.1:8080/auth/config
|
||||
|
||||
### LY SSO login
|
||||
POST http://127.0.0.1:8080/auth/ly-sso/login
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"username": "ly-xujian1",
|
||||
"password": "replace-with-env-password"
|
||||
}
|
||||
|
||||
### Google login
|
||||
POST http://127.0.0.1:8080/auth/google/login
|
||||
Content-Type: application/json
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
本文档基于当前仓库与 DevCloud 现网结构,兼顾两部分目标:
|
||||
|
||||
- 保留已落地的 DevCloud `base + production overlay` 部署方式
|
||||
- 纳入本次新增的门户登录流、`LY SSO` / Google、Langflow / AnythingLLM 嵌入配置
|
||||
- 纳入本次新增的门户登录流、Google 登录、Langflow / AnythingLLM 嵌入配置
|
||||
|
||||
## 目录结构
|
||||
|
||||
@ -95,8 +95,6 @@ deploy/k3s/
|
||||
- `AURASK_DEVCLOUD_WEB_IMAGE=registry.mydevcloud.love/devcloud/aurask-web:latest`
|
||||
- `AURASK_DEVCLOUD_API_NODE_URL=http://45.113.2.55:30091`
|
||||
- `AURASK_DEVCLOUD_WEB_NODE_URL=http://45.113.2.55:30090`
|
||||
- `AURASK_LY_SSO_ENABLED=true`
|
||||
- `AURASK_LY_SSO_USERNAME=ly-xujian1`
|
||||
- `AURASK_GOOGLE_ENABLED=true`
|
||||
- `AURASK_SESSION_TTL_DAYS=7`
|
||||
|
||||
@ -107,7 +105,6 @@ deploy/k3s/
|
||||
- `AURASK_DATABASE_URL`
|
||||
- `AURASK_ANYTHINGLLM_API_KEY`
|
||||
- `AURASK_LANGFLOW_API_KEY`
|
||||
- `AURASK_LY_SSO_PASSWORD`
|
||||
- `AURASK_GOOGLE_CLIENT_ID`
|
||||
|
||||
说明:
|
||||
@ -122,7 +119,7 @@ deploy/k3s/
|
||||
职责:
|
||||
|
||||
- API Gateway
|
||||
- `LY SSO` / Google 登录
|
||||
- Google 登录
|
||||
- Session 签发与校验
|
||||
- 配额、订单、支付、工作流入口
|
||||
- 返回门户配置与嵌入 URL
|
||||
|
||||
@ -21,9 +21,6 @@ data:
|
||||
AURASK_REDIS_WORKFLOW_QUEUE: aurask:workflow-runs
|
||||
AURASK_ANYTHINGLLM_BASE_URL: http://anythingllm.aurask-runtime.svc.cluster.local:3001
|
||||
AURASK_LANGFLOW_BASE_URL: http://langflow-runtime.aurask-runtime.svc.cluster.local:7860
|
||||
AURASK_LY_SSO_ENABLED: "true"
|
||||
AURASK_LY_SSO_USERNAME: ly-xujian1
|
||||
AURASK_LY_SSO_EMAIL_DOMAIN: ly.szlanyou.local
|
||||
AURASK_GOOGLE_ENABLED: "true"
|
||||
AURASK_SESSION_TTL_DAYS: "7"
|
||||
AURASK_CORS_ALLOW_ORIGIN: https://aurask.xyz
|
||||
|
||||
@ -8,5 +8,4 @@ stringData:
|
||||
AURASK_DATABASE_URL: postgresql://aurask:<postgres-password>@postgres.aurask-data.svc.cluster.local:5432/aurask
|
||||
AURASK_ANYTHINGLLM_API_KEY: <anythingllm-api-key>
|
||||
AURASK_LANGFLOW_API_KEY: <langflow-api-key>
|
||||
AURASK_LY_SSO_PASSWORD: <ly-sso-password>
|
||||
AURASK_GOOGLE_CLIENT_ID: <google-oauth-client-id>
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
## 当前页面能力
|
||||
|
||||
- 未登录时渲染 `/signin` 风格登录页
|
||||
- 支持 `LY SSO` 登录按钮与本地凭据提交
|
||||
- 支持 Google 登录入口
|
||||
- 新用户首次登录自动创建独立 workspace
|
||||
- 登录后显示:
|
||||
@ -18,7 +17,6 @@
|
||||
门户依赖以下 API:
|
||||
|
||||
- `GET /auth/config`
|
||||
- `POST /auth/ly-sso/login`
|
||||
- `POST /auth/google/login`
|
||||
- `GET /auth/session`
|
||||
- `POST /auth/logout`
|
||||
|
||||
@ -8,7 +8,6 @@ const state = {
|
||||
sessionToken: window.localStorage.getItem(STORAGE_KEY) || "",
|
||||
profile: null,
|
||||
activeTab: window.localStorage.getItem(TAB_KEY) || "workflows",
|
||||
lyFormOpen: false,
|
||||
loading: true,
|
||||
error: "",
|
||||
};
|
||||
@ -127,31 +126,6 @@ async function bootstrap() {
|
||||
}
|
||||
}
|
||||
|
||||
async function submitLySso(event) {
|
||||
event.preventDefault();
|
||||
state.error = "";
|
||||
render();
|
||||
const form = new FormData(event.currentTarget);
|
||||
try {
|
||||
const payload = await request("/auth/ly-sso/login", {
|
||||
method: "POST",
|
||||
body: {
|
||||
username: String(form.get("username") || "").trim(),
|
||||
password: String(form.get("password") || ""),
|
||||
},
|
||||
});
|
||||
persistSession(payload.token);
|
||||
state.profile = payload;
|
||||
state.lyFormOpen = false;
|
||||
ensureDashboardRoute();
|
||||
} catch (error) {
|
||||
state.error = error.message || "LY SSO sign-in failed";
|
||||
} finally {
|
||||
render();
|
||||
mountGoogleButton();
|
||||
}
|
||||
}
|
||||
|
||||
async function signInWithGoogle(idToken) {
|
||||
state.error = "";
|
||||
render();
|
||||
@ -177,7 +151,6 @@ async function logout() {
|
||||
}
|
||||
persistSession("");
|
||||
state.profile = null;
|
||||
state.lyFormOpen = false;
|
||||
ensureSigninRoute();
|
||||
render();
|
||||
mountGoogleButton();
|
||||
@ -213,7 +186,6 @@ function renderStatusPills() {
|
||||
}
|
||||
|
||||
function renderSignin() {
|
||||
const lyConfig = state.config?.auth?.ly_sso || {};
|
||||
const googleConfig = state.config?.auth?.google || {};
|
||||
const googleEnabled = Boolean(googleConfig.enabled && googleConfig.client_id);
|
||||
app.innerHTML = `
|
||||
@ -231,37 +203,14 @@ function renderSignin() {
|
||||
<div class="signin-header">
|
||||
<p class="section-kicker">Welcome back</p>
|
||||
<h2>Sign in to Aurask</h2>
|
||||
<p>Use your organization account first, or enable Google one-tap registration for self-serve users.</p>
|
||||
<p>Continue with Google to access your workspace or create a new one on first sign-in.</p>
|
||||
</div>
|
||||
<div class="signin-actions">
|
||||
<button id="lyButton" class="auth-btn auth-btn-primary" type="button">Use LY SSO</button>
|
||||
<button id="googleFallbackButton" class="auth-btn auth-btn-secondary" type="button" ${googleEnabled ? "" : "disabled"}>
|
||||
Continue with Google
|
||||
</button>
|
||||
</div>
|
||||
<div id="googleButton" class="google-box ${googleEnabled ? "" : "is-hidden"}"></div>
|
||||
${googleEnabled ? '<div id="googleButton" class="google-box"></div>' : '<div class="signin-actions"><button class="auth-btn auth-btn-secondary" type="button" disabled>Continue with Google</button></div>'}
|
||||
${
|
||||
googleEnabled
|
||||
? '<p class="signin-tip">Google new-user login provisions a dedicated Aurask workspace on first sign-in.</p>'
|
||||
: '<p class="signin-tip">Set `AURASK_GOOGLE_CLIENT_ID` to enable Google one-tap registration.</p>'
|
||||
}
|
||||
${
|
||||
state.lyFormOpen
|
||||
? `
|
||||
<form id="lyForm" class="ly-form">
|
||||
<label>
|
||||
Username
|
||||
<input name="username" value="${escapeHtml(lyConfig.username_hint || "ly-xujian1")}" autocomplete="username" />
|
||||
</label>
|
||||
<label>
|
||||
Password
|
||||
<input name="password" type="password" autocomplete="current-password" placeholder="Enter LY SSO password" />
|
||||
</label>
|
||||
<button class="auth-btn auth-btn-primary" type="submit">Sign in with LY SSO</button>
|
||||
</form>
|
||||
`
|
||||
: ""
|
||||
}
|
||||
${state.error ? `<p class="message error">${escapeHtml(state.error)}</p>` : ""}
|
||||
<div class="signin-footer">
|
||||
<span>Need a first workspace?</span>
|
||||
@ -270,21 +219,6 @@ function renderSignin() {
|
||||
</section>
|
||||
</main>
|
||||
`;
|
||||
|
||||
document.querySelector("#lyButton")?.addEventListener("click", () => {
|
||||
if (lyConfig.login_url) {
|
||||
window.location.href = lyConfig.login_url;
|
||||
return;
|
||||
}
|
||||
state.lyFormOpen = !state.lyFormOpen;
|
||||
render();
|
||||
mountGoogleButton();
|
||||
});
|
||||
|
||||
document.querySelector("#lyForm")?.addEventListener("submit", submitLySso);
|
||||
document.querySelector("#googleFallbackButton")?.addEventListener("click", () => {
|
||||
document.querySelector("#googleButton")?.scrollIntoView({ behavior: "smooth", block: "center" });
|
||||
});
|
||||
}
|
||||
|
||||
function renderDashboard() {
|
||||
|
||||
@ -15,7 +15,6 @@ from aurask.app import create_app
|
||||
class AuthSessionTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.env_keys = [
|
||||
"AURASK_LY_SSO_PASSWORD",
|
||||
"AURASK_GOOGLE_ENABLED",
|
||||
"AURASK_GOOGLE_ALLOW_UNVERIFIED_ID_TOKEN",
|
||||
"AURASK_GOOGLE_CLIENT_ID",
|
||||
@ -29,18 +28,6 @@ class AuthSessionTests(unittest.TestCase):
|
||||
else:
|
||||
os.environ[key] = value
|
||||
|
||||
def test_ly_sso_login_creates_session_and_workspace(self) -> None:
|
||||
os.environ["AURASK_LY_SSO_PASSWORD"] = "local-secret"
|
||||
app = create_app(None, reset=True)
|
||||
|
||||
payload = app.login_with_ly_sso(username="ly-xujian1", password="local-secret")
|
||||
context = app.auth.authenticate(f"Bearer {payload['token']}")
|
||||
|
||||
self.assertEqual(context["token_type"], "session")
|
||||
self.assertEqual(payload["workspace"]["tenant_id"], payload["tenant"]["id"])
|
||||
self.assertEqual(payload["quota"]["plan_code"], "free_trial")
|
||||
self.assertEqual(len(app.list_workspaces(payload["tenant"]["id"])), 1)
|
||||
|
||||
def test_google_first_login_reuses_workspace_after_registration(self) -> None:
|
||||
os.environ["AURASK_GOOGLE_ENABLED"] = "true"
|
||||
os.environ["AURASK_GOOGLE_ALLOW_UNVERIFIED_ID_TOKEN"] = "true"
|
||||
@ -62,6 +49,7 @@ class AuthSessionTests(unittest.TestCase):
|
||||
self.assertFalse(second_login["is_new_user"])
|
||||
self.assertEqual(first_login["workspace"]["id"], second_login["workspace"]["id"])
|
||||
self.assertEqual(len(app.list_workspaces(first_login["tenant"]["id"])), 1)
|
||||
self.assertEqual(app.auth.authenticate(f"Bearer {first_login['token']}")["token_type"], "session")
|
||||
|
||||
def _fake_google_token(self, claims: dict) -> str:
|
||||
header = self._base64url({"alg": "none", "typ": "JWT"})
|
||||
|
||||
Loading…
Reference in New Issue
Block a user