diff --git a/src/client/models/UserOutExtended.ts b/src/client/models/UserOutExtended.ts
index 388029c42f15f285a1f5add98255160f37b07340..4b0aa20a5c17d903740c1b1cfef598e178b62337 100644
--- a/src/client/models/UserOutExtended.ts
+++ b/src/client/models/UserOutExtended.ts
@@ -20,5 +20,9 @@ export type UserOutExtended = {
      * Lifesicence ID of the user
      */
     lifescience_id?: (string | null);
+    /**
+     * Timestamp when the invitation token was created as UNIX timestamp
+     */
+    invitation_token_created_at?: (number | null);
 };
 
diff --git a/src/client/services/AuthService.ts b/src/client/services/AuthService.ts
index 27d3f3fabdec5a79f22ee03ee65b40b87e0941d8..2ca01686cd70b916d4a985f87ccee423df7a3d81 100644
--- a/src/client/services/AuthService.ts
+++ b/src/client/services/AuthService.ts
@@ -8,14 +8,16 @@ import { OpenAPI } from '../core/OpenAPI';
 import { request as __request } from '../core/request';
 export class AuthService {
     /**
-     * Redirect to LifeScience OIDC Login
+     * Kickstart the login flow
      * Redirect route to OIDC provider to kickstart the login process.
+     * @param invitationToken Unique token to validate an invitation
      * @param provider The OIDC provider to use for login
-     * @param next Will be appended to redirect response in the callback route as URL query parameter `next_path`
+     * @param next Will be appended to redirect response in the callback route as URL query parameter `next`
      * @returns void
      * @throws ApiError
      */
     public static authLogin(
+        invitationToken?: string,
         provider?: OIDCProvider,
         next?: string,
     ): CancelablePromise<void> {
@@ -23,6 +25,7 @@ export class AuthService {
             method: 'GET',
             url: '/auth/login',
             query: {
+                'invitation_token': invitationToken,
                 'provider': provider,
                 'next': next,
             },
@@ -65,6 +68,7 @@ export class AuthService {
     }
     /**
      * Logout
+     * Logout the user from the system by deleting the bearer cookie.
      * @returns void
      * @throws ApiError
      */
diff --git a/src/client/services/UserService.ts b/src/client/services/UserService.ts
index e8a4680902ac0345e732ffcfc146bfae11a10f06..b9da482a054a7df0631b0c95129dbfdf71abb8eb 100644
--- a/src/client/services/UserService.ts
+++ b/src/client/services/UserService.ts
@@ -13,7 +13,7 @@ import { request as __request } from '../core/request';
 export class UserService {
     /**
      * Create User
-     * Create a new user in the system and notify him. The smtp MUST be the same as the one saved by the OIDC provider.
+     * Create a new user in the system and notify him.
      *
      * Permission `user:create` required.
      * @param requestBody
@@ -172,4 +172,31 @@ export class UserService {
             },
         });
     }
+    /**
+     * Resend Invitation
+     * Resend the invitation link for an user that has an open invitation.
+     *
+     * Permission `user:create` required.
+     * @param uid UID of a user
+     * @returns UserOutExtended Successful Response
+     * @throws ApiError
+     */
+    public static userResendInvitation(
+        uid: string,
+    ): CancelablePromise<UserOutExtended> {
+        return __request(OpenAPI, {
+            method: 'PATCH',
+            url: '/users/{uid}/invitation',
+            path: {
+                'uid': uid,
+            },
+            errors: {
+                400: `Error decoding JWT Token`,
+                401: `Not Authenticated`,
+                403: `Not Authorized`,
+                404: `Entity not Found`,
+                422: `Validation Error`,
+            },
+        });
+    }
 }
diff --git a/src/components/admin/CreateUserModal.vue b/src/components/admin/CreateUserModal.vue
index 3556d8d31ee380ca41f7f4c1006629d610ede247..e73772f9266edf9e56659a96b6e818a1b8a144d4 100644
--- a/src/components/admin/CreateUserModal.vue
+++ b/src/components/admin/CreateUserModal.vue
@@ -45,7 +45,7 @@ function createUser() {
     formState.loading = true;
     formState.registeredUserName = formState.user.display_name;
     userRepository
-      .createUser(formState.user)
+      .inviteUser(formState.user)
       .then((user) => {
         emit("user-created", user);
         formState.validated = false;
@@ -76,11 +76,11 @@ onMounted(() => {
 
 <template>
   <bootstrap-toast toast-id="create-user-success-toast">
-    Successfully registered user {{ formState.registeredUserName }}
+    Successfully invited user {{ formState.registeredUserName }}
   </bootstrap-toast>
   <bootstrap-toast toast-id="create-user-error-toast" color-class="danger">
     <template #default
-      >Couldn't regsiter user
+      >Couldn't invite user
       {{ formState.registeredUserName }}
     </template>
     <template #body>Error: {{ formState.errorMessage }}</template>
@@ -90,7 +90,7 @@ onMounted(() => {
     :static-backdrop="true"
     modal-label="Create user"
   >
-    <template #header>Register a user</template>
+    <template #header>Invite a user</template>
     <template #body>
       <form
         id="create-user-form"
diff --git a/src/router/index.ts b/src/router/index.ts
index 7c4188f0c4952115953da9fd261d427db063d1e6..5b0b11e881bae9c07d7492bce00f49088edd0a5a 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -31,8 +31,9 @@ const router = createRouter({
         title: "Login",
       },
       props: (route) => ({
-        returnPath: route.query.return_path ?? undefined,
+        returnPath: route.query.next ?? undefined,
         loginError: route.query.login_error ?? undefined,
+        invitationToken: route.query.invitation_token ?? undefined,
       }),
     },
     {
diff --git a/src/stores/users.ts b/src/stores/users.ts
index 6cb49f235011f4d4a1f86fd32234c495dcd6e008..259749fe1e00891ec6a8f38397f7680ee29609ba 100644
--- a/src/stores/users.ts
+++ b/src/stores/users.ts
@@ -113,12 +113,18 @@ export const useUserStore = defineStore({
         roles: roles,
       });
     },
-    createUser(userIn: UserIn): Promise<UserOutExtended> {
+    inviteUser(userIn: UserIn): Promise<UserOutExtended> {
       return UserService.userCreateUser(userIn).then((user) => {
         useNameStore().addNameToMapping(user.uid, user.display_name);
         return user;
       });
     },
+    resendInvitationEmail(uid: string): Promise<UserOutExtended> {
+      return UserService.userResendInvitation(uid).then((user) => {
+        useNameStore().addNameToMapping(user.uid, user.display_name);
+        return user;
+      });
+    },
     searchUser(searchString: string): Promise<UserOut[]> {
       return UserService.userSearchUsers(searchString).then((users) => {
         const nameStore = useNameStore();
diff --git a/src/views/LoginView.vue b/src/views/LoginView.vue
index d8fff7e2c5388fac61202a07b026f88c7163eb78..1c041e6f9e00ddc7ef7176ae9c844204d3058885 100644
--- a/src/views/LoginView.vue
+++ b/src/views/LoginView.vue
@@ -11,6 +11,7 @@ const router = useRouter();
 const props = defineProps<{
   returnPath?: string;
   loginError?: string;
+  invitationToken?: string;
 }>();
 
 const store = useUserStore();
@@ -24,9 +25,17 @@ onBeforeMount(() => {
   }
 });
 
-const returnPathQuery = computed<string>(() =>
-  props.returnPath ? `&next=${encodeURI(props.returnPath)}` : "",
-);
+const loginPath = computed<string>(() => {
+  const loginUrl = new URL(`${OpenAPI.BASE}/auth/login?provider=lifescience`);
+  console.log(props);
+  if (props.returnPath) {
+    loginUrl.searchParams.append("next", encodeURI(props.returnPath));
+  }
+  if (props.invitationToken) {
+    loginUrl.searchParams.append("invitation_token", props.invitationToken);
+  }
+  return loginUrl.href;
+});
 
 onMounted(() => {
   errorToast = new Toast("#loginErrorToast");
@@ -69,15 +78,16 @@ onMounted(() => {
   <div
     class="card text-center ms-md-auto position-fixed top-50 start-50 translate-middle shadow"
   >
-    <div class="card-header">Login</div>
+    <div v-if="invitationToken" class="card-header">Invitation</div>
+    <div v-else class="card-header">Login</div>
     <div class="card-body">
-      <p class="card-text text-secondary">
+      <p v-if="invitationToken" class="card-text text-secondary">
+        Connect your newly created CloWM account with your LifeScience account
+      </p>
+      <p v-else class="card-text text-secondary">
         Login to this service with LifeScience
       </p>
-      <a
-        :href="`${OpenAPI.BASE}/auth/login?provider=lifescience${returnPathQuery}`"
-        class="m-2"
-      >
+      <a :href="loginPath" class="m-2">
         <img src="/src/assets/images/ls-login.png" alt="[LS Login]" />
       </a>
     </div>
diff --git a/src/views/admin/AdminUsersView.vue b/src/views/admin/AdminUsersView.vue
index e390a01b605bdad8aee03f9f98a9ecf4a98f9bb9..378cee0370ee0a909a7d0bc3712e42628b772048 100644
--- a/src/views/admin/AdminUsersView.vue
+++ b/src/views/admin/AdminUsersView.vue
@@ -9,7 +9,8 @@ import CreateUserModal from "@/components/admin/CreateUserModal.vue";
 
 const userRepository = useUserStore();
 type RoleList = RoleEnum[];
-let successToast: Toast | undefined;
+let successRoleToast: Toast | undefined;
+let successInvitationToast: Toast | undefined;
 let errorToast: Toast | undefined;
 
 const userState = reactive<{
@@ -62,7 +63,7 @@ function saveUserRoles(index: number) {
     .then((user) => {
       userState.users[index] = user;
       userState.editUserRoles[index] = false;
-      successToast?.show();
+      successRoleToast?.show();
     })
     .catch((err) => {
       userState.errorMessage = err.body?.detail;
@@ -80,13 +81,29 @@ function resetUserRoles(index: number) {
   );
 }
 
+function resendInvitationEmail(uid: string) {
+  userState.loading = true;
+  userRepository
+    .resendInvitationEmail(uid)
+    .then(() => {
+      successInvitationToast?.show();
+    })
+    .finally(() => {
+      userState.loading = false;
+    });
+}
+
 onMounted(() => {
-  successToast = new Toast("#change-role-success-toast");
+  successRoleToast = new Toast("#change-role-success-toast");
+  successInvitationToast = new Toast("#resend-invitation-success-toast");
   errorToast = new Toast("#change-role-error-toast");
 });
 </script>
 
 <template>
+  <bootstrap-toast toast-id="resend-invitation-success-toast">
+    Successfully resend invitation email
+  </bootstrap-toast>
   <bootstrap-toast toast-id="change-role-success-toast">
     Successfully change roles of user {{ userState.editedUser?.display_name }}
   </bootstrap-toast>
@@ -108,7 +125,7 @@ onMounted(() => {
       data-bs-toggle="modal"
       data-bs-target="#create-user-modal"
     >
-      Register User
+      Invite User
     </button>
   </div>
   <form @submit.prevent="searchUsers" id="admin-user-search-form">
@@ -234,13 +251,35 @@ onMounted(() => {
           </div>
         </td>
         <td class="text-end" v-else>
-          <button
-            type="button"
-            class="btn btn-sm btn-secondary"
-            @click="userState.editUserRoles[index] = true"
-          >
-            Edit Roles
-          </button>
+          <div class="btn-group">
+            <button
+              type="button"
+              class="btn btn-sm btn-secondary"
+              @click="userState.editUserRoles[index] = true"
+            >
+              Edit Roles
+            </button>
+            <button
+              v-if="user.invitation_token_created_at"
+              type="button"
+              class="btn btn-secondary btn-sm dropdown-toggle dropdown-toggle-split"
+              data-bs-toggle="dropdown"
+              aria-expanded="false"
+            >
+              <span class="visually-hidden">Toggle Dropdown</span>
+            </button>
+            <ul class="dropdown-menu">
+              <li>
+                <a
+                  class="dropdown-item"
+                  :class="{ disabled: userState.loading }"
+                  :aria-disabled="userState.loading"
+                  @click="resendInvitationEmail(user.uid)"
+                  >Resend invitation email</a
+                >
+              </li>
+            </ul>
+          </div>
         </td>
       </tr>
     </tbody>