diff --git a/src/backoffice/locale/de/LC_MESSAGES/django.po b/src/backoffice/locale/de/LC_MESSAGES/django.po
index fe2cb0db938a0fca183f517592fe9de4423e6bf9..c4e059433066244d5286a649776005bf7a24c8cd 100644
--- a/src/backoffice/locale/de/LC_MESSAGES/django.po
+++ b/src/backoffice/locale/de/LC_MESSAGES/django.po
@@ -240,6 +240,27 @@ msgstr "Redeem Token"
 msgid "BadgeToken__Badge_back__button %(badge)s"
 msgstr "Zurück zu %(badge)s"
 
+msgid "BadgeToken__introduction"
+msgstr "Mit diesem Token kannst du Teilnehmenden eine Badge verleihen. Dazu hast du mehrere Möglichkeiten. Um die Informationen im aktuellen Design anzuzeigen folge diesem Link:"
+
+msgid "BadgeToken__redeem__info_link"
+msgstr "Auf der Website"
+
+msgid "BadgeToken__redeem_link_label"
+msgstr "Einlöse-Link"
+
+msgid "BadgeToken__redeem_link__introduction"
+msgstr "Mit diesem Link können sich Teilnehmende die Badge holen (wird z.B. auch im QR Code verwendet)"
+
+msgid "BadgeToken__redeem_token_label"
+msgstr "Einlöse-Token"
+
+msgid "BadgeToken__redeem_token__introduction"
+msgstr "Mit diesem Token können sich Benutzer die Badge in ihrem Profile hinzufügen"
+
+msgid "BadgeToken__no_qr__introduction"
+msgstr "Der QR Code für dieses Token konnte nicht gefunden werden, bitte speicher das Token um einen neuen zu generieren."
+
 msgid "BadgeToken__token__help"
 msgstr "Mit diesem Token können sich Teilnehmende das Badge holen!"
 
@@ -252,12 +273,6 @@ msgstr "Anzahl der Einlösungen"
 msgid "BadgeToken__redeemed_count__help"
 msgstr "Wie viele Teilnehmende haben sich das Badge mit diesem Token geholt?"
 
-msgid "BadgeToken__show_badge_redeem_page"
-msgstr "Einlöseseite anzeigen"
-
-msgid "BadgeToken__no_qr__introduction"
-msgstr "Der QR Code für dieses Token konnte nicht gefunden werden, bitte speicher das Token um einen neuen zu generieren."
-
 msgid "Badges"
 msgstr "Badges"
 
diff --git a/src/backoffice/locale/en/LC_MESSAGES/django.po b/src/backoffice/locale/en/LC_MESSAGES/django.po
index 3c10871739105cefd64e89e40e6bcb5a66ae58c0..85291c0e4c340a43cc0d483e82d3f57ed97b1511 100644
--- a/src/backoffice/locale/en/LC_MESSAGES/django.po
+++ b/src/backoffice/locale/en/LC_MESSAGES/django.po
@@ -240,6 +240,27 @@ msgstr "Redeem Token"
 msgid "BadgeToken__Badge_back__button %(badge)s"
 msgstr "Back to %(badge)s"
 
+msgid "BadgeToken__introduction"
+msgstr "You can use this token to award participants a badge. You have several options. To display the information in the current design, follow this link:"
+
+msgid "BadgeToken__redeem__info_link"
+msgstr "On the website"
+
+msgid "BadgeToken__redeem_link_label"
+msgstr "Redemption link"
+
+msgid "BadgeToken__redeem_link__introduction"
+msgstr "Participants can use this link to get the badge (also used in the QR code, for example)"
+
+msgid "BadgeToken__redeem_token_label"
+msgstr "Redemption token"
+
+msgid "BadgeToken__redeem_token__introduction"
+msgstr "With this token, users can add the badge to their profile"
+
+msgid "BadgeToken__no_qr__introduction"
+msgstr "The QR code for this token could not be found, please save the token to generate a new one."
+
 msgid "BadgeToken__token__help"
 msgstr "Participants can use this token to get the badge!"
 
@@ -252,12 +273,6 @@ msgstr "Number of redemptions"
 msgid "BadgeToken__redeemed_count__help"
 msgstr "How many participants got the badge with this token?"
 
-msgid "BadgeToken__show_badge_redeem_page"
-msgstr "Link to redeem page"
-
-msgid "BadgeToken__no_qr__introduction"
-msgstr "The QR code for this token could not be found, please save the token to generate a new one."
-
 msgid "Badges"
 msgstr "badges"
 
@@ -2253,3 +2268,6 @@ msgstr "StaticPage and all corresponding revisions deleted."
 
 msgid "StaticPageRevision__deleted"
 msgstr "StaticPageRevision deleted."
+
+#~ msgid "BadgeToken__show_badge_redeem_page"
+#~ msgstr "Link to redeem page"
diff --git a/src/backoffice/templates/backoffice/assembly_badge_token.html b/src/backoffice/templates/backoffice/assembly_badge_token.html
index 50d16e448e541cc7e08705a14879e9479831703d..2164bf6511c701631a52863d2769c7db90977e70 100644
--- a/src/backoffice/templates/backoffice/assembly_badge_token.html
+++ b/src/backoffice/templates/backoffice/assembly_badge_token.html
@@ -11,7 +11,7 @@
   <div class="row mb-3">
     <div class="col-md-12">
       <div class="card border-default">
-        <div class="card-header {% if new %}bg-success{% else %}bg-default{% endif %}">
+        <div class="card-header {% if new %} bg-success {% else %} bg-default {% endif %}">
           {% if create_token_form.create %}
             {% trans "Create" %}
           {% endif %}
@@ -25,7 +25,49 @@
         </div>
         <div class="card-body">
           <div class="row">
-            <div class="{% if create_token_form.create %}col-md-12{% else %}col-md-10{% endif %}">
+
+            {% if not create_token_form.create %}
+              <div class="col-md-12">
+                <div class="row mx-1 alert alert-info">
+                  <div class="col-md-10">
+
+                    <div class="mb-2">
+                      {% trans "BadgeToken__introduction" %} <a href="{% hub_absolute 'plainui:badge_token' pk=create_token_form.instance.id %}">{% trans "BadgeToken__redeem__info_link" %}</a>
+                    </div>
+                    <div class="input-group mb-1">
+                      <span class="input-group-text" id="redeem_link_label">{% trans "BadgeToken__redeem_link_label" %}</span>
+                      <input type="text"
+                             class="form-control read-only select-all"
+                             readonly
+                             id="redeem_link"
+                             value="{% hub_absolute 'plainui:manage_badges' redeem_token=create_token_form.instance.token i18n=False %}">
+                    </div>
+                    <div id="redeem_link_help" class="form-text mb-2">{% trans "BadgeToken__redeem_link__introduction" %}</div>
+                    <div class="input-group mb-1">
+                      <span class="input-group-text" id="redeem_token_label">{% trans "BadgeToken__redeem_token_label" %}</span>
+                      <input type="text"
+                             class="form-control read-only select-all"
+                             readonly
+                             id="redeem_token"
+                             value="{{ create_token_form.instance.token }}">
+                    </div>
+                    <div id="redeem_token_help" class="form-text">{% trans "BadgeToken__redeem_token__introduction" %}</div>
+                  </div>
+                  <div class="col-md-2">
+                    {% if create_token_form.instance.has_qr_code %}
+                      <div class="float-end bg-white">
+                        <img class="w-100"
+                             src="{{ create_token_form.instance.qr_full.url }}"
+                             alt="Full QR Code to redeem token">
+                      </div>
+                    {% else %}
+                      <div class="container text-bg-danger">{% trans "BadgeToken__no_qr__introduction" %}</div>
+                    {% endif %}
+                  </div>
+                </div>
+              </div>
+            {% endif %}
+            <div class="col-md-12">
               <form class="form" action="" method="post" enctype="multipart/form-data">
                 {% csrf_token %}
                 {% if not create_token_form.create %}
@@ -63,24 +105,19 @@
                 </div>
               </form>
             </div>
-            {% if not create_token_form.create %}
-              <div class="col-md-2 d-flex flex-column">
-                {% if create_token_form.instance.has_qr_code %}
-                  <div>
-                    <img class="w-100"
-                         src="{{ create_token_form.instance.qr_full.url }}"
-                         alt="Full QR Code to redeem token">
-                    <a href="{% hub_absolute 'plainui:badge_token' pk=create_token_form.instance.id %}"
-                       class="btn btn-info">{% trans "BadgeToken__show_badge_redeem_page" %}</a>
-                  </div>
-                {% else %}
-                  <div class="container text-bg-danger">{% trans "BadgeToken__no_qr__introduction" %}</div>
-                {% endif %}
-              </div>
-            {% endif %}
           </div>
         </div>
       </div>
     </div>
   </div>
 {% endblock content %}
+
+{% block scripts %}
+  <scripts nonce="{{ request.csp_nonce }}">
+$(document).ready(function() {
+$('.select-all').click(function() {
+$(this).select();
+});
+});
+  </scripts>
+{% endblock scripts %}
diff --git a/src/core/models/assemblies.py b/src/core/models/assemblies.py
index 8990771ec281287afde06b9e82804aa0fa103c52..d5c6244df38e965d590a3977e98b727ebbfb4950 100644
--- a/src/core/models/assemblies.py
+++ b/src/core/models/assemblies.py
@@ -85,7 +85,7 @@ class Assembly(TaggedItemMixin, ActivityLogMixin, RulesModel):
         verbose_name = _('Assembly')
         verbose_name_plural = _('Assemblies')
         rules_permissions = {
-            'view': is_assembly_member,
+            'view': is_assembly_member | has_perms('core.view_assembly', require_staff=True),
             'add': is_authenticated,
             'change': is_assembly_manager | has_perms('core.change_assembly', require_staff=True),
             'delete': is_assembly_manager | has_perms('core.delete_assembly', require_staff=True),
diff --git a/src/core/models/badges.py b/src/core/models/badges.py
index 16b07ac096233797c23ee5949668c2a7c200e6d4..338a50e509dab7443e97d0868c0ec84f0a8349a7 100644
--- a/src/core/models/badges.py
+++ b/src/core/models/badges.py
@@ -276,7 +276,7 @@ class BadgeToken(models.Model):
         if not self.has_qr_code:
             from core.templatetags.hub_absolute import hub_absolute  # pylint: disable=import-outside-toplevel
 
-            qr_full = segno_make(f"{hub_absolute('plainui:manage_badges')}?redeem_token={self.token}", micro=False)
+            qr_full = segno_make(hub_absolute('plainui:manage_badges', i18n=False, redeem_token=self.token), micro=False)
             buffer = io.BytesIO()
             qr_full.save(buffer, kind='svg', scale=3, dark='#555')
             buffer_value = buffer.getvalue().decode('utf-8').replace('#555', 'currentColor')
diff --git a/src/plainui/urls.py b/src/plainui/urls.py
index c6ac7b5d65f7c09d5ed3c91d3cc86511ca4c4d07..69bcc2b6e001f7296bf141bd664100588295003c 100644
--- a/src/plainui/urls.py
+++ b/src/plainui/urls.py
@@ -29,6 +29,7 @@ urlpatterns = [
     path('logout', views.LogoutView.as_view(), name='logout'),
     path('me', views.ProfileView.as_view(), name='userprofile'),
     path('me/manage_badges', views.ManageBadgesView.as_view(), name='manage_badges'),
+    path('me/manage_badges/redeem/<str:redeem_token>', views.ManageBadgesView.as_view(), name='manage_badges'),
     path('me/manage_badges/settings', views.BadgeSettingsView.as_view(), name='manage_badges__settings'),
     path('me/manage_badges/<uuid:pk>/accept', views.ManageBadgeView.as_view(mode='accept'), name='manage_badges__accept'),
     path('me/manage_badges/<uuid:pk>/update', views.ManageBadgeView.as_view(mode='update'), name='manage_badges__update'),
diff --git a/src/plainui/views/badges.py b/src/plainui/views/badges.py
index dbc254e8b0596f854d073341b9a48adda9ae2fac..4f5ebe98350e76c8c239e2ea7320cf78ab090a84 100644
--- a/src/plainui/views/badges.py
+++ b/src/plainui/views/badges.py
@@ -24,7 +24,7 @@ from django.views.generic.base import TemplateView
 from django.views.generic.detail import DetailView
 from django.views.generic.edit import FormView, UpdateView
 
-from core.models import Assembly, Badge, BadgeToken, UserBadge
+from core.models import Badge, BadgeToken, UserBadge
 from core.models.badges import TokenInvalid
 from core.models.conference import ConferenceMember
 from core.views.list_views import FilteredListView
@@ -108,6 +108,15 @@ class RedeemTokenDetailView(ConferenceRequiredMixin, DetailView):
     model = BadgeToken
     template_name = 'plainui/badges/token_detail.html.j2'
     context_object_name = 'token'
+    require_user = True
+
+    def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
+        if not BadgeToken.type_is(token := self.get_object()):  # pragma: no cover
+            raise ValueError('Token is not a badge token')
+        if self.request.user.has_perm('core.view_assembly', token.badge.issuing_assembly):
+            return super().get(request, *args, **kwargs)
+        else:
+            return HttpResponseRedirect(f"{reverse('plainui:manage_badges')}?redeem_token={token.token}")
 
     def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
         # Regenerate the qr code if needed
@@ -119,12 +128,6 @@ class RedeemTokenDetailView(ConferenceRequiredMixin, DetailView):
             'conf': self.conf,
         }
 
-    def get_queryset(self) -> QuerySet[BadgeToken]:
-        manageable = Assembly.objects.manageable_by_user(user=self.request.user, conference=self.conf, staff_can_manage=False)
-        qs = super().get_queryset()
-        qs = qs.filter(badge__issuing_assembly__in=manageable)
-        return qs
-
 
 @method_decorator(ratelimit(group='redeem_badge', key='user', rate=settings.BADGE_RATE_LIMIT), name='dispatch')
 class RedeemBadgeView(ConferenceRequiredMixin, FormView):
@@ -164,7 +167,7 @@ class RedeemBadgeView(ConferenceRequiredMixin, FormView):
         return context
 
     def get(self, request: HttpRequest, *args: str, **kwargs: Any) -> HttpResponse:
-        token = request.GET.get('redeem_token')
+        token = request.GET.get('redeem_token', kwargs.get('redeem_token'))
         try:
             self.form = RedeemBadgeForm({'token': token, 'purpose': 'redeem_token'}, conference=self.conf)
             if self.form.is_valid():
@@ -235,7 +238,11 @@ class ManageBadgesView(ConferenceRequiredMixin, TemplateView):
         return context
 
     def dispatch(self, request, *args, **kwargs):
-        if (hasattr(request, 'GET') and request.GET.get('redeem_token')) or (hasattr(request, 'GET') and request.POST.get('purpose', None) == 'redeem_token'):
+        if (
+            (hasattr(request, 'GET') and request.GET.get('redeem_token'))
+            or (hasattr(request, 'GET') and request.POST.get('purpose', None) == 'redeem_token')
+            or kwargs.get('redeem_token')
+        ):
             return RedeemBadgeView.as_view(external_context=self.get_context_data())(request, *args, **kwargs)
         return super().dispatch(request, *args, **kwargs)