更新 .env 示例文件以修正 OIDC 重定向 URL,添加可选的管理员用户名注释。增强 OIDC 登录流程,生成随机状态并在 Cookie 中存储,验证状态以提高安全性。此更改提升了 OIDC 认证的安全性和灵活性。

This commit is contained in:
BetterAndBetterII
2025-08-18 19:33:48 +08:00
committed by Yuzhong Zhang
parent bff23e9117
commit aa8e9ed4d0
2 changed files with 49 additions and 3 deletions
+3 -2
View File
@@ -1,12 +1,13 @@
OIDC_ISSUER_URL=http://localhost:5556 OIDC_ISSUER_URL=http://localhost:5556
OIDC_CLIENT_ID=excalidraw OIDC_CLIENT_ID=excalidraw
OIDC_CLIENT_SECRET=excalidraw-secret OIDC_CLIENT_SECRET=excalidraw-secret
OIDC_REDIRECT_URL=http://localhost:3002/auth/oidc/callback OIDC_REDIRECT_URL=http://localhost:3000/auth/oidc/callback
ADMIN_USERNAME=admin ADMIN_USERNAME=admin
ADMIN_PASSWORD_HASH='$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W' ADMIN_PASSWORD_HASH='$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W'
ADMIN_EMAIL=admin@example.com ADMIN_EMAIL=admin@example.com
ADMIN_USER_ID=admin1234 ADMIN_USERNAME=admin # Optional
ADMIN_USER_ID=admin1234 # Optional
JWT_SECRET=your_super_secret_jwt_string JWT_SECRET=your_super_secret_jwt_string
+46 -1
View File
@@ -2,6 +2,8 @@ package auth
import ( import (
"context" "context"
"crypto/rand"
"encoding/hex"
"excalidraw-complete/core" "excalidraw-complete/core"
"fmt" "fmt"
"net/http" "net/http"
@@ -68,7 +70,27 @@ func HandleOIDCLogin(w http.ResponseWriter, r *http.Request) {
return return
} }
url := oidcOauthConfig.AuthCodeURL("random", oauth2.AccessTypeOffline) // Generate random state
stateBytes := make([]byte, 16)
_, err := rand.Read(stateBytes)
if err != nil {
http.Error(w, "Failed to generate state for OIDC login", http.StatusInternalServerError)
return
}
state := hex.EncodeToString(stateBytes)
// Set state in a cookie
http.SetCookie(w, &http.Cookie{
Name: "oidc_state",
Value: state,
Path: "/",
Expires: time.Now().Add(10 * time.Minute), // 10 minutes expiry
HttpOnly: true,
Secure: r.Header.Get("X-Forwarded-Proto") == "https",
SameSite: http.SameSiteLaxMode,
})
url := oidcOauthConfig.AuthCodeURL(state, oauth2.AccessTypeOffline)
http.Redirect(w, r, url, http.StatusTemporaryRedirect) http.Redirect(w, r, url, http.StatusTemporaryRedirect)
} }
@@ -78,6 +100,29 @@ func HandleOIDCCallback(w http.ResponseWriter, r *http.Request) {
return return
} }
// Verify state cookie
stateCookie, err := r.Cookie("oidc_state")
if err != nil {
http.Error(w, "State cookie not found", http.StatusBadRequest)
return
}
if r.URL.Query().Get("state") != stateCookie.Value {
http.Error(w, "Invalid state", http.StatusBadRequest)
return
}
// Clear state cookie
http.SetCookie(w, &http.Cookie{
Name: "oidc_state",
Value: "",
Path: "/",
Expires: time.Unix(0, 0),
HttpOnly: true,
Secure: r.Header.Get("X-Forwarded-Proto") == "https",
SameSite: http.SameSiteLaxMode,
})
code := r.FormValue("code") code := r.FormValue("code")
if code == "" { if code == "" {
logrus.Error("no code in callback") logrus.Error("no code in callback")