authentication requests from authorization microservice

This commit is contained in:
2025-12-09 15:43:48 +08:00
parent 7c87114b30
commit adb0f59b23
2 changed files with 93 additions and 7 deletions
+91 -5
View File
@@ -29,6 +29,7 @@ import (
var googleOauthConfig oauth2.Config
var oauthStateString = generateRandomState()
var DashboardBaseURL string
var AuthorizationURL string
// init initializes the Google OAuth2 configuration by loading environment variables
// from a .env file. If the .env file cannot be loaded, it logs a fatal error.
@@ -37,7 +38,7 @@ var DashboardBaseURL string
func init() {
cwd, _ := os.Getwd()
log.Printf("[google_auth.init] Current working directory: %s", cwd)
err := godotenv.Load()
if err != nil {
log.Printf("[google_auth.init] Failed to load .env: %v, trying .env explicitly", err)
@@ -46,11 +47,11 @@ func init() {
log.Printf("[google_auth.init] Failed to load .env explicitly: %v", err)
}
}
clientID := os.Getenv("GOOGLE_CLIENT_ID")
clientSecret := os.Getenv("GOOGLE_CLIENT_SECRET")
backendURL := os.Getenv("BACKEND_URL")
log.Printf("[google_auth.init] GOOGLE_CLIENT_ID: '%s' (length: %d)", clientID, len(clientID))
log.Printf("[google_auth.init] GOOGLE_CLIENT_SECRET: '%s' (length: %d)", clientSecret, len(clientSecret))
log.Printf("[google_auth.init] BACKEND_URL: '%s'", backendURL)
@@ -75,6 +76,7 @@ func init() {
}
DashboardBaseURL = os.Getenv("DASHBOARD_URL")
AuthorizationURL = os.Getenv("AUTHORIZATION_URL")
}
@@ -87,6 +89,61 @@ func generateRandomState() string {
return fmt.Sprintf("%x", b)
}
// checkUserAuthorization calls the authorization microservice to verify user permissions
func checkUserAuthorization(userID, accessToken string) (bool, string, error) {
if AuthorizationURL == "" {
helper.LogWarn("AUTHORIZATION_URL not configured, skipping authorization check")
return true, "", nil // Allow access if authorization service is not configured
}
// Prepare request to authorization microservice
authCheckURL := fmt.Sprintf("%s", AuthorizationURL)
reqBody := map[string]string{
"user_id": userID,
}
jsonData, err := json.Marshal(reqBody)
if err != nil {
helper.LogError(err, "Failed to marshal authorization request")
return false, "", err
}
req, err := http.NewRequest("POST", authCheckURL, strings.NewReader(string(jsonData)))
if err != nil {
helper.LogError(err, "Failed to create authorization request")
return false, "", err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+accessToken)
client := &http.Client{Timeout: 5 * time.Second}
resp, err := client.Do(req)
if err != nil {
helper.LogError(err, "Failed to call authorization microservice")
return false, "", err
}
defer resp.Body.Close()
// Parse response
var authResp struct {
Allowed bool `json:"allowed"`
RedirectRoute string `json:"redirect_route,omitempty"`
Message string `json:"message,omitempty"`
}
if err := json.NewDecoder(resp.Body).Decode(&authResp); err != nil {
helper.LogError(err, "Failed to decode authorization response")
return false, "", err
}
helper.LogInfo(fmt.Sprintf("Authorization check for user %s: allowed=%v, redirect=%s, message=%s",
userID, authResp.Allowed, authResp.RedirectRoute, authResp.Message))
return authResp.Allowed, authResp.RedirectRoute, nil
}
func GoogleLogin(w http.ResponseWriter, r *http.Request) {
helper.LogInfo(fmt.Sprintf("Generated oauth_state: %s", oauthStateString))
@@ -242,9 +299,38 @@ func GoogleCallback(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, fmt.Sprintf(errorFormat, DashboardBaseURL, url.QueryEscape("Failed to log login event")), http.StatusSeeOther)
return
}
// Check user authorization via authorization microservice
allowed, redirectRoute, err := checkUserAuthorization(userID, accessToken)
if err != nil {
helper.LogError(err, "Authorization check failed")
// Continue with default flow if authorization service is unavailable
helper.LogWarn("Proceeding without authorization check due to error")
}
if !allowed {
helper.LogWarn(fmt.Sprintf("User %s denied access by authorization service", userID))
http.Redirect(w, r, fmt.Sprintf(errorFormat, DashboardBaseURL, url.QueryEscape("Access denied: Insufficient permissions")), http.StatusSeeOther)
return
}
helper.LogInfo("Copy this access token: " + accessToken)
DashboardURL := fmt.Sprintf("%s/callback?token=%s&user_id=%s&first_name=%s&last_name=%s&email_address=%s&profile_picture=%s", DashboardBaseURL, accessToken, userID, firstName, lastName, emailAddress, profilePicture)
http.Redirect(w, r, DashboardURL, http.StatusSeeOther)
// Determine redirect URL based on authorization response
var redirectURL string
if redirectRoute != "" {
// Authorization service provided a specific route
redirectURL = fmt.Sprintf("%s%s?token=%s&user_id=%s&first_name=%s&last_name=%s&email_address=%s&profile_picture=%s",
DashboardBaseURL, redirectRoute, accessToken, userID, firstName, lastName, emailAddress, profilePicture)
helper.LogInfo(fmt.Sprintf("Redirecting user to authorized route: %s", redirectRoute))
} else {
// Default to dashboard callback
redirectURL = fmt.Sprintf("%s/callback?token=%s&user_id=%s&first_name=%s&last_name=%s&email_address=%s&profile_picture=%s",
DashboardBaseURL, accessToken, userID, firstName, lastName, emailAddress, profilePicture)
helper.LogInfo("Redirecting user to default dashboard")
}
http.Redirect(w, r, redirectURL, http.StatusSeeOther)
}
func validateState(w http.ResponseWriter, r *http.Request) bool {