// identityHandlers.go implements the identity API handler for user role discovery. // This handler allows authenticated users to discover their assigned roles and // the permissions granted by those roles from Permit.io. package queryapi import ( "net/http" "time" "queryorchestration/internal/cognitoauth" "queryorchestration/internal/usermanagement" "github.com/labstack/echo/v4" ) // GetIdentity returns the currently authenticated user's roles and permissions from Permit.io. // GET /identity // // This endpoint requires authentication but no authorization - any authenticated // user can retrieve their own roles and the permissions granted by those roles. // // Returns: // - 200: IdentityResponse with roles array including permissions // - 401: Unauthorized if user is not authenticated // - 502: Bad gateway if Permit.io call fails func (ctrl *Controllers) GetIdentity(ctx echo.Context) error { // Extract user subject ID from JWT token userSubject, ok := cognitoauth.GetUserSubject(ctx) if !ok { return ctx.JSON(http.StatusUnauthorized, ErrorMessage{ Message: "Could not identify user from token", }) } // Get role keys from Permit.io httpClient := &http.Client{Timeout: 10 * time.Second} permitConfig := ctrl.getPermitConfig() roleKeys, err := usermanagement.GetPermitUserRoles(httpClient, permitConfig, userSubject) if err != nil { ctrl.cfg.GetAuthLogger().Error("Failed to get user roles from Permit.io", "error", err, "user_subject", userSubject) return ctx.JSON(http.StatusBadGateway, ErrorMessage{ Message: "Failed to retrieve roles from authorization service", }) } // Build response with role details roles := make([]IdentityRole, 0, len(roleKeys)) for _, roleKey := range roleKeys { // Get role details including permissions roleDetails, err := usermanagement.GetRoleDetails(httpClient, permitConfig, roleKey) if err != nil { ctrl.cfg.GetAuthLogger().Warn("Failed to get role details from Permit.io", "error", err, "role_key", roleKey) // Include role with empty permissions if details fetch fails roles = append(roles, IdentityRole{ Key: roleKey, Name: roleKey, Permissions: []string{}, }) continue } permissions := roleDetails.Permissions if permissions == nil { permissions = []string{} } var description *string if roleDetails.Description != "" { description = &roleDetails.Description } roles = append(roles, IdentityRole{ Key: roleDetails.Key, Name: roleDetails.Name, Description: description, Permissions: permissions, }) } return ctx.JSON(http.StatusOK, IdentityResponse{ Roles: roles, }) }