diff --git a/README.md b/README.md
index 593db3ccb77fbeadf30d9903696074dc273f21b9..2ca0bf7a23e587c0e638e8247b877255a6597d44 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,7 @@ A web service to manage LDAP users, groups and permissions.
 - python3-ldap3
 - python3-flask
 - python3-flask-sqlalchemy
+- python3-qrcode
 - git (cli utility, musst be in path)
 
 ## development
diff --git a/uffd/template_helper.py b/uffd/template_helper.py
index 66e1e3347bef06a68854d34207b8c4c487904635..0dff9a43eeca4bcf736d0d76cfabb1e1f8bae695 100644
--- a/uffd/template_helper.py
+++ b/uffd/template_helper.py
@@ -1,12 +1,27 @@
+from flask import Markup
+
+import qrcode, qrcode.image.svg
+
 import random
 import subprocess
 from datetime import timedelta, datetime
+import io
 
 def register_template_helper(app):
 	# debian ships jinja2 without this test...
 	def equalto(a, b):
 		return a == b
 
+	@app.template_filter()
+	def qrcode_svg(content, **attrs):
+		img = qrcode.make(content, image_factory=qrcode.image.svg.SvgPathImage)
+		svg = img.get_image()
+		for key, value, in attrs.items():
+			svg.set(key, value)
+		buf = io.BytesIO()
+		img.save(buf)
+		return Markup(buf.getvalue().decode())
+
 	@app.url_defaults
 	def static_version_inject(endpoint, values): #pylint: disable=unused-variable
 		if endpoint == 'static':