diff --git a/gui/src/components/api.js b/gui/src/components/api.js
index ef2d589b0a4cf7085e3fd2737a630dedee182121..bf0576d1e4b454c00749edcbe5237ccb55426847 100644
--- a/gui/src/components/api.js
+++ b/gui/src/components/api.js
@@ -192,13 +192,8 @@ class Api {
     this.onStartLoading = () => null
     this.onFinishLoading = () => null
 
+    this._swaggerClient = Swagger(`${apiBase}/swagger.json`)
     this.keycloak = keycloak
-    this.isLoggedIn = true && user
-    user = user || {}
-    this.auth_headers = {
-      'X-Token': user.token
-    }
-    this.swaggerPromise = Api.createSwaggerClient(user.token).catch(handleApiError)
 
     // keep a list of localUploads, these are uploads that are currently uploaded through
     // the browser and that therefore not yet returned by the backend
diff --git a/nomad/app/api/admin.py b/nomad/app/api/admin.py
index c1254f1b11552204b489b3df32c3a67c6d9bed29..807a70ddbe09343279069b14f050cabe3fce9dec 100644
--- a/nomad/app/api/admin.py
+++ b/nomad/app/api/admin.py
@@ -12,13 +12,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from flask import request
-from flask_restplus import abort, Resource, fields
+from flask_restplus import abort, Resource
 
 from nomad import infrastructure, config
 
 from .api import api
-from .auth import admin_login_required
+from .auth import authenticate
 
 
 ns = api.namespace('admin', description='Administrative operations')
@@ -29,7 +28,7 @@ class AdminResetResource(Resource):
     @api.doc('exec_reset_command')
     @api.response(200, 'Reset performed')
     @api.response(400, 'Reset not available/disabled')
-    @admin_login_required
+    @authenticate(admin_only=True)
     def post(self):
         """
         The ``reset`` command will attempt to clear the contents of all databased and
@@ -40,7 +39,7 @@ class AdminResetResource(Resource):
         if config.services.disable_reset:
             abort(400, message='Operation is disabled')
 
-        infrastructure.reset(repo_content_only=True)
+        infrastructure.reset()
 
         return dict(messager='Reset performed.'), 200
 
@@ -50,7 +49,7 @@ class AdminRemoveResource(Resource):
     @api.doc('exec_remove_command')
     @api.response(200, 'Remove performed')
     @api.response(400, 'Remove not available/disabled')
-    @admin_login_required
+    @authenticate(admin_only=True)
     def post(self):
         """
         The ``remove``command will attempt to remove all databases. Expect the
@@ -65,28 +64,3 @@ class AdminRemoveResource(Resource):
         infrastructure.remove()
 
         return dict(messager='Remove performed.'), 200
-
-
-pidprefix_model = api.model('PidPrefix', {
-    'prefix': fields.Integer(description='The prefix. All new calculations will get an id that is greater.', required=True)
-})
-
-
-# TODO remove after migration
-@ns.route('/pidprefix')
-class AdminPidPrefixResource(Resource):
-    @api.doc('exec_pidprefix_command')
-    @api.response(200, 'Pid prefix set')
-    @api.response(400, 'Bad pid prefix data')
-    @api.expect(pidprefix_model)
-    @admin_login_required
-    def post(self):
-        """
-        The ``pidprefix``command will set the pid counter to the given value.
-
-        This might be useful while migrating data with old pids.
-        """
-
-        infrastructure.set_pid_prefix(**request.get_json())
-
-        return dict(messager='PID prefix set.'), 200
diff --git a/nomad/app/api/auth.py b/nomad/app/api/auth.py
index ab04a6809bc40ea6f893d2e975b30455da4c9c14..533faca1d3634f1ee60b522cb960baff30282279 100644
--- a/nomad/app/api/auth.py
+++ b/nomad/app/api/auth.py
@@ -41,7 +41,7 @@ import uuid
 
 from nomad import config, processing, utils, infrastructure, datamodel
 
-from .app import api
+from .api import api
 
 
 # Authentication scheme definitions, for swagger
diff --git a/nomad/app/api/repo.py b/nomad/app/api/repo.py
index 22d1904caafe2f093219c6dabfb0a9255832814c..95a64bb35e7ce1483d963ed5b253b2ab412196e4 100644
--- a/nomad/app/api/repo.py
+++ b/nomad/app/api/repo.py
@@ -26,7 +26,7 @@ from nomad import search, utils, datamodel
 from nomad.app.utils import rfc3339DateTime
 from nomad.app.optimade import filterparser
 
-from .api import api, rfc3339DateTime
+from .api import api
 from .auth import authenticate
 from .common import pagination_model, pagination_request_parser, calc_route
 
@@ -357,7 +357,7 @@ class RepoPidResource(Resource):
     @api.doc('resolve_pid')
     @api.response(404, 'Entry with PID does not exist')
     @api.marshal_with(repo_calc_id_model, skip_none=True, code=200, description='Entry resolved')
-    @login_if_available
+    @authenticate()
     def get(self, pid: int):
         search_request = search.SearchRequest()
 
diff --git a/nomad/cli/admin/admin.py b/nomad/cli/admin/admin.py
index 41822409f824b99cdcf68d6d59b7b99056c60bb7..8eb5d12c7bb838fe36ea22d451a9818e0594636f 100644
--- a/nomad/cli/admin/admin.py
+++ b/nomad/cli/admin/admin.py
@@ -15,7 +15,6 @@
 import click
 import datetime
 import elasticsearch.helpers
-import json
 
 from nomad import processing as proc, search, datamodel, infrastructure, utils, config
 
diff --git a/nomad/infrastructure.py b/nomad/infrastructure.py
index 92c6c007ca38adc1b0aaae24d7f5e7d22c9642f6..151b4058da3142bb98026fe8ad4de7ee9dcbc59c 100644
--- a/nomad/infrastructure.py
+++ b/nomad/infrastructure.py
@@ -278,10 +278,11 @@ class Keycloak():
             user_id = user.user_id
 
         if email is not None and user_id is None:
-            try:
+            with utils.lnr(logger, 'Could not use keycloak admin client'):
                 user_id = self._admin_client.get_user_id(email)
-            except Exception:
-                raise KeyError('User does not exist')
+
+            if user_id is None:
+                raise KeyError('User %s does not exist' % email)
 
         assert user_id is not None, 'Could not determine user from given kwargs'
 
diff --git a/nomad/search.py b/nomad/search.py
index e60804a2867543203f9a95e7bae692214cd98eb1..9a85add85b111602c668292dcfcf553e7c297163 100644
--- a/nomad/search.py
+++ b/nomad/search.py
@@ -286,7 +286,7 @@ class SearchRequest:
                 raise ValueError('Authentication required for owner value user')
             q = Q('term', published=False) & Q('term', owners__user_id=user_id)
         elif owner_type == 'admin':
-            if user_id is None or not coe_repo.User.from_user_id(user_id).is_admin:
+            if user_id is None or not datamodel.User.get(user_id=user_id).is_admin:
                 raise ValueError('This can only be used by the admin user.')
             q = None
         else:
diff --git a/tests/app/test_api.py b/tests/app/test_api.py
index 6d933dbad728de85d52c6da60dc9bf34c1d65ab5..83c39206c1628dddde45899cf2507a0a8c9c59e2 100644
--- a/tests/app/test_api.py
+++ b/tests/app/test_api.py
@@ -25,7 +25,7 @@ from urllib.parse import urlencode
 import base64
 
 from nomad.app.utils import rfc3339DateTime
-from nomad.app.auth import generate_upload_token
+from nomad.app.api.auth import generate_upload_token
 from nomad import search, parsing, files, config, utils, infrastructure
 from nomad.files import UploadFiles, PublicUploadFiles
 from nomad.processing import Upload, Calc, SUCCESS
@@ -196,7 +196,7 @@ class TestUploads:
         assert upload['process_running']
 
         additional_keys = ['with_embargo']
-        if publish_with_metadata and 'external_id' in metadata:
+        if 'external_id' in metadata:
             additional_keys.append('external_id')
 
         self.block_until_completed(api, upload_id, test_user_auth)
@@ -597,18 +597,21 @@ class TestRepo():
         search.Entry.from_calc_with_metadata(calc_with_metadata).save(refresh=True)
 
         calc_with_metadata.update(
-            calc_id='2', uploader=other_test_user.user_id, published=True, with_embargo=False,
-            upload_time=today - datetime.timedelta(days=5))
+            calc_id='2', uploader=other_test_user.user_id, published=True,
+            with_embargo=False, pid=2, upload_time=today - datetime.timedelta(days=5),
+            external_id='external_id')
         calc_with_metadata.update(
             atoms=['Fe'], comment='this is a specific word', formula='AAA', basis_set='zzz')
         search.Entry.from_calc_with_metadata(calc_with_metadata).save(refresh=True)
 
         calc_with_metadata.update(
-            calc_id='3', uploader=other_test_user.user_id, published=False, with_embargo=False)
+            calc_id='3', uploader=other_test_user.user_id, published=False,
+            with_embargo=False, pid=3, external_id='external_id')
         search.Entry.from_calc_with_metadata(calc_with_metadata).save(refresh=True)
 
         calc_with_metadata.update(
-            calc_id='4', uploader=other_test_user.user_id, published=True, with_embargo=True)
+            calc_id='4', uploader=other_test_user.user_id, published=True,
+            with_embargo=True, pid=4, external_id='external_id')
         search.Entry.from_calc_with_metadata(calc_with_metadata).save(refresh=True)
 
     def assert_search(self, rv: Any, number_of_calcs: int) -> dict:
diff --git a/tests/test_search.py b/tests/test_search.py
index 1ddfd26a6c0872de502070cfa990c07883aee3fe..7d310d6b96391191c2d4bbdf828ede3e2b410daf 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -16,7 +16,7 @@ from typing import List
 from elasticsearch_dsl import Q
 import pytest
 
-from nomad import datamodel, search, processing, parsing, infrastructure, config, coe_repo
+from nomad import datamodel, search, processing, parsing, infrastructure, config
 from nomad.search import Entry, SearchRequest
 
 
@@ -137,7 +137,7 @@ def test_search_totals(elastic, example_search_data):
     assert 'quantities' not in results
 
 
-def test_search_quantity(elastic, normalized: parsing.LocalBackend, test_user: coe_repo.User, other_test_user: coe_repo.User):
+def test_search_quantity(elastic, normalized: parsing.LocalBackend, test_user: datamodel.User, other_test_user: datamodel.User):
     calc_with_metadata = datamodel.CalcWithMetadata(upload_id='test upload id', calc_id='test id')
     calc_with_metadata.apply_domain_metadata(normalized)
     calc_with_metadata.uploader = test_user.user_id