134 lines
3.6 KiB
Go
134 lines
3.6 KiB
Go
package cognitoauth
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
|
|
"queryorchestration/internal/serviceconfig/auth"
|
|
|
|
"strings"
|
|
|
|
"github.com/labstack/echo/v4"
|
|
"github.com/lestrrat-go/jwx/v2/jwt"
|
|
)
|
|
|
|
// RegisterRoutes registers all authentication-related routes to the Echo engine
|
|
func RegisterRoutes(e *echo.Echo, config auth.ConfigProvider) {
|
|
// check the auth feature flag
|
|
fmt.Println("Registering routes for Auth.")
|
|
disableAuth := os.Getenv("DISABLE_AUTH")
|
|
if strings.ToLower(disableAuth) == "true" {
|
|
fmt.Println("Auth is disabled. Skipping auth routes.")
|
|
return // Do nothing if auth is not enabled
|
|
}
|
|
|
|
// Register the login route - the middleware will handle this
|
|
e.GET(config.GetAuthLoginPath(), func(c echo.Context) error {
|
|
// This is handled by the middleware
|
|
return nil
|
|
})
|
|
|
|
// Register callback route - the middleware will handle this
|
|
e.GET(config.GetAuthCallbackPath(), func(c echo.Context) error {
|
|
// This handler will only be called for requests that don't have a code parameter
|
|
// (those are handled directly in the middleware)
|
|
|
|
// Get user info from context
|
|
userClaims, _ := c.Get("user_claims").(map[string]interface{})
|
|
userGroups, _ := c.Get("user_groups").([]string)
|
|
|
|
return c.JSON(http.StatusOK, map[string]interface{}{
|
|
"authenticated": true,
|
|
"username": userClaims["cognito:username"],
|
|
"email": userClaims["email"],
|
|
"groups": userGroups,
|
|
})
|
|
})
|
|
|
|
// Apply the JWT Auth middleware first
|
|
e.Use(JWTAuthMiddleware(config))
|
|
|
|
// Then apply the token validation middleware
|
|
e.Use(TokenValidationMiddleware(config))
|
|
}
|
|
|
|
// GetTokenFromRequest extracts the token from the request
|
|
func GetTokenFromRequest(c echo.Context) string {
|
|
// First try from Authorization header
|
|
authHeader := c.Request().Header.Get("Authorization")
|
|
if authHeader != "" && strings.HasPrefix(authHeader, "Bearer ") {
|
|
return authHeader[7:]
|
|
}
|
|
|
|
// Then try from cookie
|
|
tokenCookie, err := c.Cookie("auth_token")
|
|
if err == nil && tokenCookie.Value != "" {
|
|
return tokenCookie.Value
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// GetUserInfo gets user information from the context
|
|
func GetUserInfo(c echo.Context) (UserInfo, bool) {
|
|
// Try to get user info from context
|
|
userInfo, ok := c.Get("user_info").(UserInfo)
|
|
if ok {
|
|
return userInfo, true
|
|
}
|
|
|
|
// Try to get token and extract user info
|
|
token := GetTokenFromRequest(c)
|
|
if token == "" {
|
|
return UserInfo{}, false
|
|
}
|
|
|
|
// Parse token to extract claims
|
|
parsedToken, err := jwt.Parse([]byte(token), jwt.WithVerify(false))
|
|
if err != nil {
|
|
return UserInfo{}, false
|
|
}
|
|
|
|
claims, err := parsedToken.AsMap(context.Background())
|
|
if err != nil {
|
|
return UserInfo{}, false
|
|
}
|
|
|
|
// Extract user info
|
|
userInfo = ExtractUserInfo(claims)
|
|
return userInfo, true
|
|
}
|
|
|
|
// RequireGroups creates a middleware that checks if the user is in any of the specified groups
|
|
func RequireGroups(groups ...string) echo.MiddlewareFunc {
|
|
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
|
return func(c echo.Context) error {
|
|
userInfo, ok := GetUserInfo(c)
|
|
if !ok {
|
|
return c.JSON(http.StatusUnauthorized, map[string]string{
|
|
"error": "Authentication required",
|
|
})
|
|
}
|
|
|
|
// Check if user has any of the required groups
|
|
for _, requiredGroup := range groups {
|
|
for _, userGroup := range userInfo.Groups {
|
|
if userGroup == requiredGroup {
|
|
return next(c)
|
|
}
|
|
}
|
|
}
|
|
|
|
return c.JSON(http.StatusForbidden, map[string]interface{}{
|
|
"error": "Insufficient permissions",
|
|
"message": "User doesn't have the required group membership",
|
|
"username": userInfo.Username,
|
|
"groups": userInfo.Groups,
|
|
"required_groups": groups,
|
|
})
|
|
}
|
|
}
|
|
}
|