$30 off During Our Annual Pro Sale. View Details »

Content editing in Symfony

Content editing in Symfony

Content editing is the process of letting users create rich content directly from your project. It goes from allowing users to write simple text comments to letting users write rich documents collaboratively in real-time. Due to the inherent risks of displaying user content on your platform, it is a difficult problem to tackle in a secure, scalable and feature-rich way.

Let's discuss how the HtmlSanitizer component, Symfony UX and Mercure can be used together to build amazing editing experiences for your users.

Titouan Galopin

November 18, 2022
Tweet

More Decks by Titouan Galopin

Other Decks in Technology

Transcript

  1. Content editing in Symfony

  2. Hello! I am Titouan Galopin Symfony UX initiative lead Selency

    // Citipo 2
  3. Agenda 1. Know your content 2. Security concerns 3. Choosing

    an editor 4. The state of the art: block-based editors 5. Live editing with Symfony UX and Mercure 3
  4. 1 Know your content 4

  5. Content editing isn’t a technical challenge, it’s an architecture one

    5
  6. • Article comments • Restaurant reviews • Social post •

    Document writing • CMS • … Many use cases 6
  7. ⬡ Stylable content vs Plain text? Should your users be

    able to insert bold/italic? Links? Images? … Questions to ask yourself 7
  8. Questions to ask yourself 8 ⬡ Stylable content vs Plain

    text? ⬡ Feature-rich content vs Markdown? Markdown is great but it’s difficult to use for non-technical users, and will it be enough?
  9. Questions to ask yourself 9 ⬡ Stylable content vs Plain

    text? ⬡ Feature-rich content vs Markdown? ⬡ Programmatic content manipulation? Will you need to manipulate the content programmatically (move elements, migrate to a new editor, upgrade your current editor, …)? (Most likely yes)
  10. Questions to ask yourself 10 ⬡ Stylable content vs Plain

    text? ⬡ Feature-rich content vs Markdown? ⬡ Programmatic content manipulation? ⬡ Translation? Automatic/manual content translation?
  11. Questions to ask yourself 11 ⬡ Stylable content vs Plain

    text? ⬡ Feature-rich content vs Markdown? ⬡ Programmatic content manipulation? ⬡ Translation? ⬡ Different display on mobile vs desktop? Should some blocks have a different structure on mobile?
  12. Questions to ask yourself 12 ⬡ Stylable content vs Plain

    text? ⬡ Feature-rich content vs Markdown? ⬡ Programmatic content manipulation? ⬡ Translation? ⬡ Different display on mobile vs desktop? ⬡ Display in non-Web contexts (mobile/desktop app, …)?
  13. Answers to these questions are both technical and human Content

    editors are one of the most complex UX challenge 13
  14. 2 Security concerns 14

  15. A content editor is a big security risk You must

    implement dedicated security 15
  16. Biggest risk: Cross-site scripting Inject JavaScript code into Web pages

    viewed by other users to extract information (session cookie, password, emails, …) from your users. 16
  17. But also … CSS display attack Inject CSS into pages

    to render them unusable or log the keystrokes of visitors. 17
  18. But also … Click-hijacking attack Inject HTML/CSS into pages to

    change the target of a legitimate link somewhere in the page (for instance the login button) to a phishing page. 18
  19. But also … DDoS attacks Libraries to sanitize user content

    are complex and CPU-intensive (HTML parsing and manipulation). It’s a great place to DDoS a platform. 19
  20. 20 Implementing security

  21. Simplest option Twig escape filter (or htmlentities) if you don’t

    need to accept HTML (plain text/markdown/…). You should use this when you can. 21
  22. HTML sanitizing When you need to accept HTML (rich-content), you

    need to distinguish safe from unsafe HTML. This is what’s called HTML Sanitizing. 22
  23. Symfony HtmlSanitizer The HTML Sanitizer component aims at sanitizing untrusted

    HTML code (e.g. created by a WYSIWYG editor in the browser) into HTML that can be trusted. 23
  24. HtmlSanitizer is useful to: • Prevent security issues (XSS, CSRF,

    data extraction, …) • Prevent display problems (ensure content consistency) • Output valid, standard HTML from potentially invalid WYSIWYG editor one 24
  25. Usage 25

  26. 26

  27. 27 As a service

  28. 28 In a form

  29. 29 As a Twig filter

  30. Configuration 30

  31. 31 Create a custom sanitizer

  32. 32 Configure allowed …

  33. 33 Configure allowed … and forbidden elements

  34. 34 Configure allowed links to prevent phishing and privacy issues

  35. 35 Configure allowed media to prevent phishing and privacy issues

  36. Tip: you should apply sanitizing before storing and before display

    36
  37. Before storing To store safe HTML in the database 37

  38. Before displaying Because: 1. Content can be manipulated from outside

    your application (manually, script missing the sanitizer, …) 2. Because some databases have unpredictable behaviors Ex: MySQL transforms UTF-8 character ⟨ to ASCII < when storing in a non-UTF8 field 38
  39. 3 Choosing an editor 39

  40. The editor you choose should match your technical and UX

    needs 40
  41. 41 Plain-text

  42. Simplest option (textarea) • Easy-to-use for everyone • Can be

    enough, especially with modern emoji support • Very limited styling 42
  43. Implementation • Editor: standard textarea • Display: Twig + escape

    filter 43
  44. 44 Markup language

  45. Great for technical users • Great UX for tech users

    (ex: Markdown + CodeMirror) • Flexible without too much JavaScript complexity • Not usable by non-tech users • Requires HTML sanitization for security 45
  46. 46 Implementation Editor: • TextareaType + HtmlSanitizer

  47. 47 Implementation Editor: • TextareaType + HtmlSanitizer • Symfony UX

    + CodeMirror
  48. 48 Implementation Editor: • TextareaType + HtmlSanitizer • Symfony UX

    + CodeMirror
  49. 49 Implementation Display: • Twig + league/ commonmark + HtmlSanitizer

  50. 50 WYSIWYG

  51. UX-friendly for everyone • Easy-to-use by anyone • Requires a

    complex JavaScript library • Requires HTML sanitization for security • Difficult to manipulate the generated content 51
  52. 52 Implementation Editor: • TextareaType + HtmlSanitizer

  53. 53 Implementation Editor: • TextareaType + HtmlSanitizer • Symfony UX

    + CKEditor
  54. 54 Implementation Editor: • TextareaType + HtmlSanitizer • Symfony UX

    + CKEditor
  55. 55 Implementation Display: • Twig + HtmlSanitizer

  56. Problems 1. How can I add a <div> around tweets

    on display? 2. How can I upgrade my editor version without breaking existing content? 3. How can I display content in a non-Web context? 4. How can I allow multiple people to edit collaboratively? 56
  57. HTML is not easy to manipulate 57

  58. 4 The state of the art: block-based editors 58

  59. The idea Content is stored as JSON blocks, containing HTML

    only when necessary 59
  60. The rendered HTML is only built at display 60

  61. By using JSON blocks: • Easier to manipulate (“add a

    <div> around tweets”) • Can display content outside the Web • Ease content migration during upgrades • Make live collaboration possible 61
  62. Example: Quill Rich Text Editor 62

  63. 63

  64. Deltas Deltas are an expressive format to describe Quill’s contents

    and changes 64
  65. 65 Describes content…

  66. 66 …but also changes

  67. Security Blocks content should still be: • Escaped (Twig/htmlentities) if

    they won’t contain any HTML • Sanitized if they will 67
  68. Implementation Very similar to CKEditor: Symfony UX to instantiate, Symfony

    Form to extract the data 68
  69. Storage Store the content as JSON in your database: easy

    manipulation! 69
  70. Display Use Quill JS library to render blocks as safe

    HTML … or implement your own logic to display on other platforms! 70
  71. Solutions 1. How can I add a <div> around tweets

    on display? 2. How can I upgrade my editor version without breaking existing content? 3. How can I display content in a non-Web context? => Now very easy! 4. How can I allow multiple people to edit the same content collaboratively? … 71
  72. 5 Live editing with Symfony UX and Mercure 72

  73. Deltas allow us to live stream changes across users! 73

  74. 74 Collaborative editor

  75. 75 Collaborative editor This is a Delta change: small, easy

    bit to synchronize the editor state between users
  76. Conclusion 76

  77. Conclusion • For simple needs: plain text + escape is

    enough (a content editor isn’t necessarily worth it) 77
  78. Conclusion • For simple needs: plain text + escape is

    enough (a content editor isn’t necessarily worth it) • For tech users: Markdown + HtmlSanitizer with a code editor is great and flexible 78
  79. Conclusion • For simple needs: plain text + escape is

    enough (a content editor isn’t necessarily worth it) • For tech users: Markdown + HtmlSanitizer with a code editor is great and flexible • Otherwise: always choose a block-based editor (much more flexible) and use sanitization 79
  80. 80 Thanks! Any questions? You can find me at: @tgalopin

    galopintitouan@gmail.com Slides design by SlidesCarnival