diff --git a/.env.example b/.env.example
index 045895946626fc01dcbd3573d30f9836496f2db6..a5773760e786c31e97a23493d756c0b1f454ac42 100644
--- a/.env.example
+++ b/.env.example
@@ -1,4 +1,5 @@
 API="http://fda-gateway-service:9095"
-MAIL_USERNAME="eMATRIKELNUMMER" // TU student e-mail server
-MAIL_PASSWORD="PASSWORD" // TU student e-mail server
-ADMIN_PASSWORD="admin"
\ No newline at end of file
+MAIL_HOST="stmp.example.com"
+MAIL_PORT="587"
+MAIL_USERNAME="user"
+MAIL_PASSWORD="pass"
\ No newline at end of file
diff --git a/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/AuthenticationEndpoint.java b/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/AuthenticationEndpoint.java
index 3d21d5e1d1be172cbad01112b61a2b7a4d261659..48fb5183c665e648ce9e132a46675c2514c37b18 100644
--- a/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/AuthenticationEndpoint.java
+++ b/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/AuthenticationEndpoint.java
@@ -3,6 +3,7 @@ package at.tuwien.endpoints;
 import at.tuwien.api.auth.JwtResponseDto;
 import at.tuwien.api.auth.LoginRequestDto;
 import at.tuwien.api.user.UserDto;
+import at.tuwien.exception.OrcidMalformedException;
 import at.tuwien.exception.UserEmailNotVerifiedException;
 import at.tuwien.exception.UserNotFoundException;
 import at.tuwien.mapper.UserMapper;
@@ -50,7 +51,7 @@ public class AuthenticationEndpoint {
     @PutMapping
     @Transactional(readOnly = true)
     @Operation(summary = "Validate token", security = @SecurityRequirement(name = "bearerAuth"))
-    public ResponseEntity<UserDto> authenticateUser(Principal principal) throws UserNotFoundException {
+    public ResponseEntity<UserDto> authenticateUser(Principal principal) throws UserNotFoundException, OrcidMalformedException {
         final UserDto user = userMapper.userToUserDto(userService.findByUsername(principal.getName()));
         return ResponseEntity.accepted()
                 .body(user);
diff --git a/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java b/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java
index c7665d6fd6a8f7502da64e30b27e7a9a251cc5cf..aa3e3a1cf0c1bb564942a7ddbe6d877ca72f0dae 100644
--- a/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java
+++ b/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java
@@ -30,6 +30,7 @@ import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
 import java.security.Principal;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -62,11 +63,13 @@ public class UserEndpoint {
     @Transactional(readOnly = true)
     @PreAuthorize("hasRole('ROLE_DATA_STEWARD') or hasRole('ROLE_DEVELOPER')")
     @Operation(summary = "List users", security = @SecurityRequirement(name = "bearerAuth"))
-    public ResponseEntity<List<UserDto>> list() {
+    public ResponseEntity<List<UserDto>> list() throws OrcidMalformedException {
         final List<User> users = userService.findAll();
-        return ResponseEntity.ok(users.stream()
-                .map(userMapper::userToUserDto)
-                .collect(Collectors.toList()));
+        final List<UserDto> out = new LinkedList<>();
+        for (User user : users) {
+            out.add(userMapper.userToUserDto(user));
+        }
+        return ResponseEntity.ok(out);
     }
 
     @PostMapping
@@ -74,7 +77,7 @@ public class UserEndpoint {
     @Operation(summary = "Create user")
     public ResponseEntity<UserDto> register(@NotNull @Valid @RequestBody SignupRequestDto data)
             throws UserEmailExistsException,
-            UserNameExistsException, RoleNotFoundException, UserEmailFailedException, BrokerUserCreationException {
+            UserNameExistsException, RoleNotFoundException, UserEmailFailedException, BrokerUserCreationException, OrcidMalformedException {
         final User user = userService.create(data);
         queueService.createUser(data);
         final Token token = tokenService.create(user);
@@ -90,7 +93,7 @@ public class UserEndpoint {
     @Transactional
     @Operation(summary = "Forgot user information")
     public ResponseEntity<UserDto> forgot(@NotNull @Valid @RequestBody UserForgotDto data)
-            throws UserNotFoundException, UserEmailFailedException {
+            throws UserNotFoundException, UserEmailFailedException, OrcidMalformedException {
         final User user = userService.forgot(data);
         final Token token = tokenService.create(user);
         final Context context = new Context();
@@ -118,23 +121,11 @@ public class UserEndpoint {
         httpServletResponse.setStatus(302);
     }
 
-    @PutMapping("/token")
-    @Transactional
-    @PreAuthorize("hasRole('ROLE_RESEARCHER')")
-    @Operation(summary = "Update user token", security = @SecurityRequirement(name = "bearerAuth"))
-    public ResponseEntity<UserDto> updateTokens(@NotNull @Valid @RequestBody UserTokenModifyDto data,
-                                                @NotNull Principal principal)
-            throws UserNotFoundException {
-        final User entity = userService.updateToken(data, principal);
-        return ResponseEntity.status(HttpStatus.ACCEPTED)
-                .body(userMapper.userToUserDto(entity));
-    }
-
     @GetMapping("/{id}")
     @Transactional(readOnly = true)
     @PreAuthorize("hasRole('ROLE_DEVELOPER') or hasPermission(#id, 'READ_USER')")
     @Operation(summary = "Find some user", security = @SecurityRequirement(name = "bearerAuth"))
-    public ResponseEntity<UserDto> find(@NotNull @PathVariable("id") Long id) throws UserNotFoundException {
+    public ResponseEntity<UserDto> find(@NotNull @PathVariable("id") Long id) throws UserNotFoundException, OrcidMalformedException {
         final User entity = userService.find(id);
         return ResponseEntity.status(HttpStatus.OK)
                 .body(userMapper.userToUserDto(entity));
@@ -146,7 +137,7 @@ public class UserEndpoint {
     @Operation(summary = "Update user", security = @SecurityRequirement(name = "bearerAuth"))
     public ResponseEntity<UserDto> update(@NotNull @PathVariable("id") Long id,
                                           @NotNull @Valid @RequestBody UserUpdateDto data)
-            throws UserNotFoundException {
+            throws UserNotFoundException, OrcidMalformedException {
         final User entity = userService.update(id, data);
         return ResponseEntity.status(HttpStatus.ACCEPTED)
                 .body(userMapper.userToUserDto(entity));
@@ -158,7 +149,7 @@ public class UserEndpoint {
     @Operation(summary = "Update user roles", security = @SecurityRequirement(name = "bearerAuth"))
     public ResponseEntity<UserDto> updateRoles(@NotNull @PathVariable("id") Long id,
                                                @NotNull @Valid @RequestBody UserRolesDto data)
-            throws UserNotFoundException, RoleNotFoundException, RoleUniqueException {
+            throws UserNotFoundException, RoleNotFoundException, RoleUniqueException, OrcidMalformedException {
         final User entity = userService.updateRoles(id, data);
         return ResponseEntity.status(HttpStatus.ACCEPTED)
                 .body(userMapper.userToUserDto(entity));
@@ -170,7 +161,7 @@ public class UserEndpoint {
     @Operation(summary = "Update user password", security = @SecurityRequirement(name = "bearerAuth"))
     public ResponseEntity<UserDto> updatePassword(@NotNull @PathVariable("id") Long id,
                                                   @NotNull @Valid @RequestBody UserPasswordDto data)
-            throws UserNotFoundException, BrokerUserCreationException {
+            throws UserNotFoundException, BrokerUserCreationException, OrcidMalformedException {
         final User entity = userService.updatePassword(id, data);
         queueService.modifyUserPassword(entity, data);
         return ResponseEntity.status(HttpStatus.ACCEPTED)
@@ -183,7 +174,7 @@ public class UserEndpoint {
     @Operation(summary = "Update user email", security = @SecurityRequirement(name = "bearerAuth"))
     public ResponseEntity<UserDto> updateEmail(@NotNull @PathVariable("id") Long id,
                                                @NotNull @Valid @RequestBody UserEmailDto data)
-            throws UserNotFoundException {
+            throws UserNotFoundException, OrcidMalformedException {
         final User entity = userService.updateEmail(id, data);
         return ResponseEntity.status(HttpStatus.ACCEPTED)
                 .body(userMapper.userToUserDto(entity));
diff --git a/fda-authentication-service/rest-service/src/main/resources/application-docker.yml b/fda-authentication-service/rest-service/src/main/resources/application-docker.yml
index a9589c3777f27824ddb5e11722d57fc25bc2a22c..78f3bd5c161dd3c9f6eab2dce483d1d2ea3ec2f0 100644
--- a/fda-authentication-service/rest-service/src/main/resources/application-docker.yml
+++ b/fda-authentication-service/rest-service/src/main/resources/application-docker.yml
@@ -52,5 +52,5 @@ fda:
     replyto: "${MAIL_REPLY_TO}"
 jwt:
   issuer: "${JWT_ISSUER}"
-  secret: "${JWT_SECRET"
+  secret: "${JWT_SECRET}"
   expiration.ms: "${JWT_EXPIRATION}" # 24 hrs
\ No newline at end of file
diff --git a/fda-authentication-service/rest-service/src/main/resources/application.yml b/fda-authentication-service/rest-service/src/main/resources/application.yml
index a9f6e883099bb10d2aacfa9f5ea9d56a05e5d7ac..bdb5b07e6d3b79ab38dfee0d0a177ab606178311 100644
--- a/fda-authentication-service/rest-service/src/main/resources/application.yml
+++ b/fda-authentication-service/rest-service/src/main/resources/application.yml
@@ -22,8 +22,8 @@ spring:
     loadbalancer.ribbon.enabled: false
   mail:
     default-encoding: UTF-8
-    host: "${SMTP_HOST}"
-    port: "${SMTP_PORT}"
+    host: mail.student.tuwien.ac.at
+    port: 993
     username: "${SMTP_USERNAME}"
     password: "${SMTP_PASSWORD}"
     properties.mail.smtp:
diff --git a/fda-authentication-service/services/src/main/java/at/tuwien/exception/OrcidMalformedException.java b/fda-authentication-service/services/src/main/java/at/tuwien/exception/OrcidMalformedException.java
new file mode 100644
index 0000000000000000000000000000000000000000..29c85b49142eef8515532214effd45e5a60e231a
--- /dev/null
+++ b/fda-authentication-service/services/src/main/java/at/tuwien/exception/OrcidMalformedException.java
@@ -0,0 +1,20 @@
+package at.tuwien.exception;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(code = HttpStatus.BAD_REQUEST)
+public class OrcidMalformedException extends Exception {
+
+    public OrcidMalformedException(String msg) {
+        super(msg);
+    }
+
+    public OrcidMalformedException(String msg, Throwable thr) {
+        super(msg, thr);
+    }
+
+    public OrcidMalformedException(Throwable thr) {
+        super(thr);
+    }
+}
diff --git a/fda-authentication-service/services/src/main/java/at/tuwien/mapper/UserMapper.java b/fda-authentication-service/services/src/main/java/at/tuwien/mapper/UserMapper.java
index 3819e30bce2bfdbd21854ec86f10e4c613ad9376..05b1aa764b67395f4759adab83c46cb356159427 100644
--- a/fda-authentication-service/services/src/main/java/at/tuwien/mapper/UserMapper.java
+++ b/fda-authentication-service/services/src/main/java/at/tuwien/mapper/UserMapper.java
@@ -7,6 +7,7 @@ import at.tuwien.api.auth.SignupRequestDto;
 import at.tuwien.api.user.*;
 import at.tuwien.entities.user.RoleType;
 import at.tuwien.entities.user.User;
+import at.tuwien.exception.OrcidMalformedException;
 import org.mapstruct.Mapper;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.GrantedAuthority;
@@ -47,7 +48,7 @@ public interface UserMapper {
     }
 
     @Transactional(readOnly = true)
-    default UserDto userToUserDto(User data) {
+    default UserDto userToUserDto(User data) throws OrcidMalformedException {
         return UserDto.builder()
                 .id(data.getId())
                 .username(data.getUsername())
@@ -58,7 +59,8 @@ public interface UserMapper {
                 .titlesBefore(data.getTitlesBefore())
                 .titlesAfter(data.getTitlesAfter())
                 .emailVerified(data.getEmailVerified())
-                .hasInvenioToken(data.getInvenioToken() != null)
+                .affiliation(data.getAffiliation())
+                .orcid(userToUncompressedOrcid(data))
                 .authorities(data.getRoles()
                         .stream()
                         .map(this::roleTypeToGrantedAuthorityDto)
@@ -82,6 +84,32 @@ public interface UserMapper {
                 .build();
     }
 
+    default String userUpdateDtoToCompressedOrcid(UserUpdateDto data) {
+        if (data.getOrcid() == null) {
+            return null;
+        }
+        return data.getOrcid().replace("-", "");
+    }
+
+    default String userToUncompressedOrcid(User data) throws OrcidMalformedException {
+        if (data.getOrcid() == null) {
+            return null;
+        }
+        if (data.getOrcid().length() != 16) {
+            log.error("Provided ORCID is not compressed");
+            log.debug("provided orcid {} is not compressed, length is {}", data.getOrcid(), data.getOrcid().length());
+            throw new OrcidMalformedException("Provided ORCID is not compressed");
+        }
+        return new StringBuilder(data.getOrcid().substring(0, 4))
+                .append("-")
+                .append(data.getOrcid(), 4, 8)
+                .append("-")
+                .append(data.getOrcid(), 8, 12)
+                .append("-")
+                .append(data.getOrcid(), 12, 16)
+                .toString();
+    }
+
     default GrantVirtualHostPermissionsDto signupRequestDtoToGrantComponentDto() {
         return GrantVirtualHostPermissionsDto.builder()
                 .virtualHost("/")
diff --git a/fda-authentication-service/services/src/main/java/at/tuwien/service/UserService.java b/fda-authentication-service/services/src/main/java/at/tuwien/service/UserService.java
index bd9ecbe2e5ae2faaca3e21e179e48783caf76f3d..d7877d78a2494ffcb6e9274b3dd705299437c9a2 100644
--- a/fda-authentication-service/services/src/main/java/at/tuwien/service/UserService.java
+++ b/fda-authentication-service/services/src/main/java/at/tuwien/service/UserService.java
@@ -74,7 +74,7 @@ public interface UserService {
      * @return The updated user.
      * @throws UserNotFoundException The user was not found.
      */
-    User update(Long id, UserUpdateDto data) throws UserNotFoundException;
+    User update(Long id, UserUpdateDto data) throws UserNotFoundException, OrcidMalformedException;
 
     /**
      * Updates a user with given id and updated roles.
@@ -98,16 +98,6 @@ public interface UserService {
      */
     User updatePassword(Long id, UserPasswordDto data) throws UserNotFoundException;
 
-    /**
-     * Updates a user with the given id and updated Invenio tokens.
-     *
-     * @param data      The updated Invenio token.
-     * @param principal The authentication principal.
-     * @return The updated user.
-     * @throws UserNotFoundException The user was not found.
-     */
-    User updateToken(UserTokenModifyDto data, Principal principal) throws UserNotFoundException;
-
     /**
      * Updates a user with the given id and updated email.
      *
diff --git a/fda-authentication-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java b/fda-authentication-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java
index 627a75dceb2bf23d12298ba67fd296d4b1e6b1c3..1a258e19c8873538d16de789d052bb5aeb353b50 100644
--- a/fda-authentication-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java
+++ b/fda-authentication-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java
@@ -127,15 +127,23 @@ public class UserServiceImpl implements UserService {
 
     @Override
     @Transactional
-    public User update(Long id, UserUpdateDto data) throws UserNotFoundException {
+    public User update(Long id, UserUpdateDto data) throws UserNotFoundException, OrcidMalformedException {
         /* check */
         final User user = find(id);
+        /* check */
+        if (data.getOrcid() != null && !validateOrcid(data.getOrcid())) {
+            log.error("Checksum of the provided ORCID does not match");
+            log.debug("checksum of the provided orcid {} does not match", data.getOrcid());
+            throw new OrcidMalformedException(data.getOrcid());
+        }
         /* save */
         user.setTitlesBefore(data.getTitlesBefore());
         user.setTitlesAfter(data.getTitlesAfter());
         user.setFirstname(data.getFirstname());
         user.setLastname(data.getLastname());
         user.setUsername(user.getUsername());
+        user.setAffiliation(data.getAffiliation());
+        user.setOrcid(userMapper.userUpdateDtoToCompressedOrcid(data));
         log.debug("mapped data {} to new user {}", data, user);
         final User entity = userRepository.save(user);
         log.info("Updated user with id {}", entity.getId());
@@ -143,6 +151,37 @@ public class UserServiceImpl implements UserService {
         return entity;
     }
 
+    /**
+     * Validates a given ORCID checksum (ISO 7064 11,2)
+     * Source: https://support.orcid.org/hc/en-us/articles/360006897674-Structure-of-the-ORCID-Identifier
+     *
+     * @param orcid The ORCID.
+     * @return True if the ORCID provided is valid, false otherwise.
+     */
+    protected static Boolean validateOrcid(String orcid) {
+        if (orcid == null) {
+            return true;
+        }
+        if (orcid.length() != 19) {
+            log.error("Provided ORCID has an invalid length");
+            log.debug("provided orcid {} has an invalid length {}, is not 19", orcid, orcid.length());
+            return false;
+        }
+        int total = 0;
+        for (int i = 0; i < orcid.length() - 1; i++) {
+            if (orcid.charAt(i) == '-') {
+                continue;
+            }
+            int digit = Character.getNumericValue(orcid.charAt(i));
+            total = (total + digit) * 2;
+        }
+        int remainder = total % 11;
+        int result = (12 - remainder) % 11;
+        final String check = result == 10 ? "X" : String.valueOf(result);
+        log.trace("orcid checksum is '{}'", check);
+        return orcid.substring(18).equals(check);
+    }
+
     @Override
     @Transactional
     public User updateRoles(Long id, UserRolesDto data)
@@ -187,19 +226,6 @@ public class UserServiceImpl implements UserService {
         return entity;
     }
 
-    @Override
-    @Transactional
-    public User updateToken(UserTokenModifyDto data, Principal principal) throws UserNotFoundException {
-        /* check */
-        final User user = findByUsername(principal.getName());
-        /* save */
-        user.setInvenioToken(data.getInvenioToken());
-        final User entity = userRepository.save(user);
-        log.info("Updated user with id {}", entity.getId());
-        log.debug("updated user {}", entity);
-        return entity;
-    }
-
     @Override
     @Transactional
     public User updateEmail(Long id, UserEmailDto data) throws UserNotFoundException {
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/container/image/ImageBriefDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/container/image/ImageBriefDto.java
index 313e5b115ec2a262df4d90643b806cebe5bb18b3..0624a29e775d4f9d6a44d2fab1c832dc21a929e3 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/container/image/ImageBriefDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/container/image/ImageBriefDto.java
@@ -22,10 +22,6 @@ public class ImageBriefDto {
     @Parameter(required = true, example = "mariadb")
     private String repository;
 
-    @ToString.Exclude
-    @Parameter(required = true, example = "base64:aaaa")
-    private String logo;
-
     @NotBlank
     @Parameter(required = true, example = "10.5")
     private String tag;
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/container/image/ImageDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/container/image/ImageDto.java
index 2fbae1b8a18b704380472361a3032cf4ee90830d..832d2e586cf19696af7f77ee01fe19ffd3bb274b 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/container/image/ImageDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/container/image/ImageDto.java
@@ -36,10 +36,6 @@ public class ImageDto {
     @Parameter(required = true, example = "org.postgresql.Driver")
     private String driverClass;
 
-    @ToString.Exclude
-    @Parameter(required = true)
-    private String logo;
-
     @JsonProperty("date_formats")
     private List<ImageDateDto> dateFormats;
 
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java
index 5040bc5c26777138b715a8ea1c09f58d808c4986..167d9e50be8f53725c2d6291b7c287478df691f6 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java
@@ -42,9 +42,11 @@ public class UserBriefDto {
     @Parameter(name = "last name")
     private String lastname;
 
-    @ToString.Exclude
-    @JsonIgnore
-    private String invenioToken;
+    @Parameter(name = "affiliation")
+    private String affiliation;
+
+    @Parameter(name = "orcid")
+    private String orcid;
 
     @NotNull
     @Parameter(name = "mail address")
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java
index 7a70a14adef3746fce6fc882d7ca086805bf3c34..de6281ff33bb3eb4ecd361d3051b5f4fc316ccd9 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java
@@ -43,6 +43,12 @@ public class UserDto {
     @Parameter(name = "last name")
     private String lastname;
 
+    @Parameter(name = "affiliation")
+    private String affiliation;
+
+    @Parameter(name = "orcid")
+    private String orcid;
+
     @Parameter(name = "list of containers")
     private List<ContainerDto> containers;
 
@@ -52,13 +58,6 @@ public class UserDto {
     @Parameter(name = "list of identifiers")
     private List<ContainerDto> identifiers;
 
-    @ToString.Exclude
-    @JsonIgnore
-    private String invenioToken;
-
-    @JsonProperty("has_invenio_token")
-    private Boolean hasInvenioToken;
-
     @ToString.Exclude
     @JsonIgnore
     @Parameter(name = "password hash")
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserUpdateDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserUpdateDto.java
index 1e76d2c7923a63f320235f7c85f9647f61dec9f1..e7fb05063f277a21a62fd8bf0a4d11764c34d244 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserUpdateDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserUpdateDto.java
@@ -31,4 +31,10 @@ public class UserUpdateDto {
     @Parameter(name = "last name")
     private String lastname;
 
+    @Parameter(name = "affiliation")
+    private String affiliation;
+
+    @Parameter(name = "orcid")
+    private String orcid;
+
 }
diff --git a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java
index 8d832c77ff3bf13f04aa7948ceb93adb3847d50a..9024d66090faf539a87317ff08ab45193a0ec243 100644
--- a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java
+++ b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java
@@ -51,9 +51,11 @@ public class User {
     @Column(name = "main_email", unique = true, nullable = false)
     private String email;
 
-    @ToString.Exclude
-    @Column(name = "invenio_token")
-    private String invenioToken;
+    @Column
+    private String affiliation;
+
+    @Column
+    private String orcid;
 
     @Column(name = "main_email_verified", nullable = false)
     private Boolean emailVerified;
diff --git a/fda-metadata-db/setup-schema.sql b/fda-metadata-db/setup-schema.sql
index bfd746d5c5ff9240f6dd00573f99d2bb7b2cab0c..ed96b7636eaa9ccf37c0f586e076314714ff7939 100644
--- a/fda-metadata-db/setup-schema.sql
+++ b/fda-metadata-db/setup-schema.sql
@@ -149,12 +149,13 @@ CREATE TABLE IF NOT EXISTS mdb_users
     First_name           VARCHAR(50),
     Last_name            VARCHAR(50),
     Gender               gender,
-    Preceding_titles     VARCHAR(50),
-    Postpositioned_title VARCHAR(50),
+    Preceding_titles     VARCHAR(255),
+    Postpositioned_title VARCHAR(255),
+    orcid                VARCHAR(16),
+    affiliation          VARCHAR(255),
     Main_Email           VARCHAR(255)                not null,
     main_email_verified  bool                        not null default false,
     password             VARCHAR(255)                not null,
-    invenio_token        VARCHAR(255),
     created              timestamp without time zone NOT NULL DEFAULT NOW(),
     last_modified        timestamp without time zone,
     PRIMARY KEY (UserID),
diff --git a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java
index 1f64b414818f8cc45a1b8bf5d5cb124ded52b550..118d5ae77bca603f830b8102af73e2fcddbe3a34 100644
--- a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java
+++ b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java
@@ -96,7 +96,7 @@ public class QueryEndpoint extends AbstractEndpoint {
                                                       @NotNull @PathVariable("queryId") Long queryId,
                                                       @NotNull Principal principal)
             throws QueryStoreException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
-            ContainerNotFoundException, TableMalformedException, FileStorageException, NotAllowedException {
+            ContainerNotFoundException, TableMalformedException, FileStorageException, NotAllowedException, QueryMalformedException {
         if (!hasQueryPermission(databaseId, queryId, "QUERY_EXPORT", principal)) {
             log.error("Missing export query permission");
             throw new NotAllowedException("Missing export query permission");
diff --git a/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java b/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java
index dd157660706c436660109b399e61ed748fbf65de..04b477670263eb844d2f05767bb798da5b4e464a 100644
--- a/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java
+++ b/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java
@@ -14,7 +14,6 @@ import at.tuwien.querystore.Query;
 import at.tuwien.entities.database.table.Table;
 import at.tuwien.entities.database.table.columns.TableColumn;
 import at.tuwien.exception.ImageNotSupportedException;
-import net.sf.jsqlparser.statement.select.FromItem;
 import net.sf.jsqlparser.statement.select.SelectItem;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
@@ -29,8 +28,8 @@ import java.text.Normalizer;
 import java.time.*;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatterBuilder;
-import java.time.temporal.ChronoUnit;
 import java.util.*;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -40,6 +39,9 @@ public interface QueryMapper {
 
     org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(QueryMapper.class);
 
+    DateTimeFormatter mariaDbFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+            .withZone(ZoneId.of("UTC"));
+
     @Deprecated
     @Mappings({
             @Mapping(source = "query", target = "statement")
@@ -297,27 +299,39 @@ public interface QueryMapper {
                 });
         query.append("FROM `")
                 .append(table.getInternalName())
-                .append("` INTO OUTFILE '/tmp/")
-                .append(filename)
-                .append("' CHARACTER SET utf8");
+                .append("`");
         if (timestamp != null) {
             query.append(" FOR SYSTEM_TIME AS OF TIMESTAMP'")
-                    .append(LocalDateTime.ofInstant(timestamp, ZoneId.of("Europe/Vienna")))
+                    .append(mariaDbFormatter.format(timestamp))
                     .append("'");
         }
+        query.append(" INTO OUTFILE '/tmp/")
+                .append(filename)
+                .append("' CHARACTER SET utf8");
         query.append(";");
         return query.toString();
     }
 
-    default String queryToRawExportQuery(Query query, String filename) {
+    default String queryToRawExportQuery(Query query, String filename) throws QueryMalformedException {
         if (query.getQuery().contains(";")) {
             log.trace("Remove ending ; from statement [{}]", query.getQuery());
             query.setQuery(query.getQuery().substring(0, query.getQuery().indexOf(";")));
         }
-        final StringBuilder statement = new StringBuilder(query.getQuery())
-                .append(" FOR SYSTEM_TIME AS OF TIMESTAMP'")
-                .append(LocalDateTime.ofInstant(query.getExecution(), ZoneId.of("Europe/Vienna")))
-                .append("' INTO OUTFILE '/tmp/")
+        /* insert the FOR SYSTEM_TIME ... part after the FROM in the query */
+        final StringBuilder versionPart = new StringBuilder(" FOR SYSTEM_TIME AS OF TIMESTAMP'")
+                .append(mariaDbFormatter.format(query.getExecution()))
+                .append("' ");
+        final Pattern pattern = Pattern.compile("from `?[a-zA-Z0-9_]+`?", Pattern.CASE_INSENSITIVE) /* https://mariadb.com/kb/en/columnstore-naming-conventions/ */;
+        final Matcher matcher = pattern.matcher(query.getQuery());
+        if (!matcher.find()) {
+            log.error("Failed to find 'from' clause in query");
+            throw new QueryMalformedException("Failed to find from clause");
+        }
+        log.debug("found group from {} to {} in '{}'", matcher.start(), matcher.end(), query.getQuery());
+        final StringBuilder statement = new StringBuilder(query.getQuery().substring(0, matcher.end(0)))
+                .append(versionPart)
+                .append(query.getQuery().substring(matcher.end(0)))
+                .append(" INTO OUTFILE '/tmp/")
                 .append(filename)
                 .append("' CHARACTER SET utf8 FIELDS TERMINATED BY ',';");
         log.trace("raw export query: [{}]", statement);
diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java b/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java
index 7ae593261fd1f4451e53e7e644e825d302ee3958..64cc05e1198b9dbd8a19dd8a2a8b78430c4a9d7e 100644
--- a/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java
+++ b/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java
@@ -127,7 +127,7 @@ public interface QueryService {
      */
     ExportResource findOne(Long containerId, Long databaseId, Long queryId)
             throws DatabaseNotFoundException, ImageNotSupportedException, TableMalformedException,
-            ContainerNotFoundException, FileStorageException, QueryStoreException, QueryNotFoundException;
+            ContainerNotFoundException, FileStorageException, QueryStoreException, QueryNotFoundException, QueryMalformedException;
 
     /**
      * Count the total tuples for a given table id within a container-database id tuple at a given time.
diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java
index 10ce827b9e4405a1021955a040ce08d915fba6df..4e1c9f0692af9eb4af9e47ec46638c0fa3209516 100644
--- a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java
+++ b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java
@@ -206,7 +206,7 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
     @Transactional(readOnly = true)
     public ExportResource findOne(Long containerId, Long databaseId, Long queryId)
             throws DatabaseNotFoundException, ImageNotSupportedException, TableMalformedException,
-            ContainerNotFoundException, FileStorageException, QueryStoreException, QueryNotFoundException {
+            ContainerNotFoundException, FileStorageException, QueryStoreException, QueryNotFoundException, QueryMalformedException {
         /* find */
         final Database database = databaseService.find(databaseId);
         final Query query = storeService.findOne(containerId, databaseId, queryId);
diff --git a/fda-ui/components/DBToolbar.vue b/fda-ui/components/DBToolbar.vue
index 375cb79746c193b7056758f6ac616932333b7f85..7ffba3adc339d338b9e5f0964c0bb44bb3b150b0 100644
--- a/fda-ui/components/DBToolbar.vue
+++ b/fda-ui/components/DBToolbar.vue
@@ -7,13 +7,13 @@
       </v-toolbar-title>
       <v-spacer />
       <v-toolbar-title>
-        <v-btn class="mr-2" :disabled="!token" :to="`/container/${$route.params.container_id}/database/${databaseId}/table/import`">
+        <v-btn class="mr-2 mb-1" :disabled="!token" :to="`/container/${$route.params.container_id}/database/${databaseId}/table/import`">
           <v-icon left>mdi-cloud-upload</v-icon> Import CSV
         </v-btn>
-        <v-btn color="secondary" class="mr-2 white--text" :disabled="!token" :to="`/container/${$route.params.container_id}/database/${databaseId}/query/create`">
+        <v-btn color="secondary" class="mr-2 mb-1 white--text" :disabled="!token" :to="`/container/${$route.params.container_id}/database/${databaseId}/query/create`">
           <v-icon left>mdi-wrench</v-icon> Create Subset
         </v-btn>
-        <v-btn color="primary" :disabled="!token" :to="`/container/${$route.params.container_id}/database/${databaseId}/table/create`">
+        <v-btn color="primary" class="mb-1" :disabled="!token" :to="`/container/${$route.params.container_id}/database/${databaseId}/table/create`">
           <v-icon left>mdi-table-large-plus</v-icon> Create Table
         </v-btn>
       </v-toolbar-title>
diff --git a/fda-ui/components/TableList.vue b/fda-ui/components/TableList.vue
index ebb6ca3aacfe03faeabd42182c28344f2db3e553..cbcfb4478a5b01cc39fe3b6ea75028996a078d02 100644
--- a/fda-ui/components/TableList.vue
+++ b/fda-ui/components/TableList.vue
@@ -11,7 +11,7 @@
         <v-expansion-panel-header>
           {{ item.name }}
         </v-expansion-panel-header>
-        <v-expansion-panel-content>
+        <v-expansion-panel-content class="mb-2">
           <v-row dense>
             <v-col>
               <v-list dense>
diff --git a/fda-ui/components/TableSchema.vue b/fda-ui/components/TableSchema.vue
index f4b5347517361bc0a62c6239eec18517c054cce9..78aa0699f115c0e446fc8699e67949d432c005ea 100644
--- a/fda-ui/components/TableSchema.vue
+++ b/fda-ui/components/TableSchema.vue
@@ -106,12 +106,6 @@ export default {
         return []
       }
     },
-    form: {
-      type: Boolean,
-      default () {
-        return false
-      }
-    },
     back: {
       type: Boolean,
       default () {
@@ -146,7 +140,6 @@ export default {
     }
   },
   mounted () {
-    this.valid = this.form
     this.loadDateFormats()
   },
   methods: {
diff --git a/fda-ui/components/dialogs/PersistQuery.vue b/fda-ui/components/dialogs/PersistQuery.vue
index 1634dcd2001e6db30cf9ef0eb38b0cd69b2218dc..507ccf5a9927f92014bf260e1d7022cc6bdcae0d 100644
--- a/fda-ui/components/dialogs/PersistQuery.vue
+++ b/fda-ui/components/dialogs/PersistQuery.vue
@@ -75,6 +75,7 @@
             <v-col cols="3">
               <v-text-field
                 v-model="creator.orcid"
+                :rules="[v => validateOrcid(v) || $t('Invalid ORCID')]"
                 name="orcid"
                 label="ORCID" />
             </v-col>
@@ -152,7 +153,7 @@
 </template>
 
 <script>
-import { formatDateUTC } from '@/utils'
+import { formatDateUTC, isValidOrcid } from '@/utils'
 export default {
   data () {
     return {
@@ -173,6 +174,12 @@ export default {
         is_public: null,
         publisher: null
       },
+      user: {
+        firstname: null,
+        lastname: null,
+        affiliation: null,
+        orcid: null
+      },
       relatedTypes: [
         { value: 'DOI' },
         { value: 'URL' },
@@ -257,7 +264,7 @@ export default {
   },
   mounted () {
     this.loadUser()
-    this.addCreator()
+      .then(() => this.addCreatorSelf())
     this.loadDatabase()
   },
   methods: {
@@ -265,6 +272,19 @@ export default {
       this.$parent.$parent.$parent.persistQueryDialog = false
       this.$emit('close', { action: 'closed' })
     },
+    validateOrcid (orcid) {
+      return isValidOrcid(orcid)
+    },
+    addCreatorSelf () {
+      if (!this.user.firstname || !this.user.lastname) {
+        this.addCreator()
+      }
+      this.identifier.creators.push({
+        name: `${this.user.lastname}, ${this.user.firstname}`,
+        orcid: this.user.orcid,
+        affiliation: this.user.affiliation
+      })
+    },
     addCreator () {
       this.identifier.creators.push({
         name: null,
@@ -326,6 +346,7 @@ export default {
         res = await this.$axios.put('/api/auth', null, {
           headers: this.headers
         })
+        this.user = res.data
         console.debug('user data', res.data)
       } catch (err) {
         this.$toast.error('Failed load user data')
diff --git a/fda-ui/components/query/Builder.vue b/fda-ui/components/query/Builder.vue
index 984d5e606e510b4f8ed9e18c241277f307a7263c..ff784984cfa7600a667c18f5b4dc1bad6c0eb9a8 100644
--- a/fda-ui/components/query/Builder.vue
+++ b/fda-ui/components/query/Builder.vue
@@ -1,28 +1,27 @@
 <template>
   <div>
     <v-toolbar flat>
-      <v-toolbar-title>Create Query</v-toolbar-title>
+      <v-toolbar-title>Create Subset</v-toolbar-title>
       <v-spacer />
       <v-toolbar-title>
-        <v-btn v-if="false" :disabled="!canExecute || !token" color="blue-grey white--text" @click="save">
-          Save without execution
-        </v-btn>
         <v-btn :disabled="!canExecute || !token" color="primary" @click="execute">
           <v-icon left>mdi-run</v-icon>
           Execute
         </v-btn>
       </v-toolbar-title>
     </v-toolbar>
-    <v-tabs
-      v-model="tabs"
-      centered>
-      <v-tab>
-        Create Subset
-      </v-tab>
-      <v-tab>
-        Raw SQL
-      </v-tab>
-    </v-tabs>
+    <v-toolbar flat>
+      <v-tabs
+        color="primary"
+        v-model="tabs">
+        <v-tab>
+          Simple
+        </v-tab>
+        <v-tab>
+          Expert
+        </v-tab>
+      </v-tabs>
+    </v-toolbar>
     <v-card flat>
       <v-tabs-items v-model="tabs">
         <v-tab-item>
diff --git a/fda-ui/components/query/Raw.vue b/fda-ui/components/query/Raw.vue
index 73160fbf516b7ffcb4042d2457fa6d613633034a..f5a62ae2e3af5b9df8e9af6bee644a60e36e8714 100644
--- a/fda-ui/components/query/Raw.vue
+++ b/fda-ui/components/query/Raw.vue
@@ -28,7 +28,7 @@ export default {
   },
   data () {
     return {
-      content: this.value || 'SELECT `id` FROM "myTable"',
+      content: this.value || '-- MariaDB 10.5 Query\n',
       theme: 'xcode'
     }
   },
@@ -53,7 +53,7 @@ export default {
   methods: {
     editorInit (editor) {
       editor.setOptions({
-        fontSize: '11pt',
+        fontSize: '12pt',
         readOnly: this.disabled,
         behavioursEnabled: !this.disabled
       })
diff --git a/fda-ui/pages/container/_container_id/database/_database_id/info.vue b/fda-ui/pages/container/_container_id/database/_database_id/info.vue
index e9ee0abe79786a818341bf3ab60a05f10d43c5ba..0a3af4e5a74361841fd655645530d068bae5e266 100644
--- a/fda-ui/pages/container/_container_id/database/_database_id/info.vue
+++ b/fda-ui/pages/container/_container_id/database/_database_id/info.vue
@@ -92,7 +92,7 @@
 <script>
 import DBToolbar from '@/components/DBToolbar'
 import EditDB from '@/components/dialogs/EditDB'
-import { formatTimestampUTCLabel } from '@/utils'
+import { formatTimestampUTCLabel, formatUser } from '@/utils'
 
 export default {
   components: {
@@ -165,18 +165,7 @@ export default {
       return this.database.publication === null ? '(none)' : this.database.publication
     },
     creator () {
-      if (this.database.creator.firstname && this.database.creator.lastname) {
-        let creator = ''
-        if (this.database.creator.titles_before) {
-          creator += (this.database.creator.titles_before + ' ')
-        }
-        creator += (this.database.creator.firstname + ' ' + this.database.creator.lastname)
-        if (this.database.creator.titles_after) {
-          creator += (this.database.creator.titles_after + ' ')
-        }
-        return creator
-      }
-      return this.database.creator.username
+      return formatUser(this.database.creator)
     }
   },
   mounted () {
diff --git a/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue b/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue
index 65adfc6c8df715f0315e629939e06b92f6ccb715..b7ef2bdbad23610c8f746cf20035012860e92add 100644
--- a/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue
+++ b/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue
@@ -8,13 +8,19 @@
       </v-toolbar-title>
       <v-spacer />
       <v-toolbar-title>
-        <v-btn v-if="!identifier.id && !loadingIdentifier" color="secondary" class="mr-2" :disabled="!executionUTC || !token" @click.stop="openDialog()">
+        <v-btn v-if="!identifier.id && !loadingIdentifier" color="secondary" class="mr-2" :disabled="error || !executionUTC || !token" @click.stop="openDialog()">
           <v-icon left>mdi-content-save-outline</v-icon> Save
         </v-btn>
-        <v-btn v-if="result_visibility" color="primary" :loading="downloadLoading" @click.stop="download">
+        <v-btn v-if="result_visibility" :disabled="error" color="primary" :loading="downloadLoading" @click.stop="download">
           <v-icon left>mdi-download</v-icon> Data .csv
         </v-btn>
-        <v-btn v-if="identifier.id" color="secondary" class="ml-2" :loading="metadataLoading" @click.stop="metadata">
+        <v-btn
+          v-if="identifier.id"
+          :disabled="error"
+          color="secondary"
+          class="ml-2"
+          :loading="metadataLoading"
+          @click.stop="metadata">
           <v-icon left>mdi-code-tags</v-icon> Metadata .xml
         </v-btn>
       </v-toolbar-title>
@@ -52,10 +58,10 @@
                 <v-skeleton-loader v-if="loadingDatabase" type="text" class="skeleton-small" />
                 <span v-if="!loadingDatabase">{{ database.publisher }}</span>
               </v-list-item-content>
-              <v-list-item-title v-if="database.license.identifier" class="mt-2">
+              <v-list-item-title v-if="database.license" class="mt-2">
                 Database License
               </v-list-item-title>
-              <v-list-item-content v-if="database.license.identifier">
+              <v-list-item-content v-if="database.license">
                 <v-skeleton-loader v-if="loadingDatabase" type="text" class="skeleton-xsmall" />
                 <a v-if="!loadingDatabase" :href="database.license.uri">{{ database.license.identifier }}</a>
               </v-list-item-content>
diff --git a/fda-ui/pages/container/_container_id/database/_database_id/table/create.vue b/fda-ui/pages/container/_container_id/database/_database_id/table/create.vue
index e882415dddfb95f528f3c924d659c364a037f2fb..2345caf0abdf821f9c8fbe84de81b75622ef5d02 100644
--- a/fda-ui/pages/container/_container_id/database/_database_id/table/create.vue
+++ b/fda-ui/pages/container/_container_id/database/_database_id/table/create.vue
@@ -51,7 +51,7 @@
       </v-stepper-step>
 
       <v-stepper-content step="2">
-        <TableSchema :form="valid" :columns="tableCreate.columns" @close="schemaClose" />
+        <TableSchema :back="true" :columns="tableCreate.columns" @close="schemaClose" />
       </v-stepper-content>
     </v-stepper>
   </div>
@@ -153,7 +153,11 @@ export default {
       this.loading = false
     },
     schemaClose (event) {
-      console.trace('schema closed', event)
+      console.debug('schema closed', event)
+      if (!event.success) {
+        this.step = 1
+        return
+      }
       this.createTable()
     }
   }
diff --git a/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue b/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue
index bd10a893222e5d4f60f8a9ed1bd21d716e679f37..7c8e38a4b553dc9f94377eb9d6577788052775ad 100644
--- a/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue
+++ b/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue
@@ -171,7 +171,7 @@
       </v-stepper-step>
 
       <v-stepper-content step="4">
-        <TableSchema :form="validStep4" :back="true" :columns="tableCreate.columns" @close="schemaClose" />
+        <TableSchema :back="true" :columns="tableCreate.columns" @close="schemaClose" />
       </v-stepper-content>
 
       <v-stepper-step
diff --git a/fda-ui/pages/container/index.vue b/fda-ui/pages/container/index.vue
index 18d492ae9a604152717fdc4b4f9ceade37f3e300..ae455fe553a2a7e71303ef02500019324254207e 100644
--- a/fda-ui/pages/container/index.vue
+++ b/fda-ui/pages/container/index.vue
@@ -64,7 +64,7 @@
 <script>
 import { mdiDatabaseArrowRightOutline } from '@mdi/js'
 import CreateDB from '@/components/dialogs/CreateDB'
-import { formatTimestampUTCLabel } from '@/utils'
+import { formatTimestampUTCLabel, formatUser } from '@/utils'
 
 export default {
   components: {
@@ -105,18 +105,7 @@ export default {
   },
   methods: {
     formatCreator (creator) {
-      if (creator.firstname && creator.lastname) {
-        let name = ''
-        if (creator.titles_before) {
-          name += creator.titles_before + ' '
-        }
-        name += creator.firstname + ' ' + creator.lastname
-        if (creator.titles_after) {
-          name += ' ' + creator.titles_after
-        }
-        return name
-      }
-      return creator.username
+      return formatUser(creator)
     },
     async loadContainers () {
       this.createDbDialog = false
diff --git a/fda-ui/pages/user/index.vue b/fda-ui/pages/user/index.vue
index 8d090a47c8c8a3fea22826b6b396dd0312abb405..85cf94f44da9f32271aa553d4163e5e6e25e635e 100644
--- a/fda-ui/pages/user/index.vue
+++ b/fda-ui/pages/user/index.vue
@@ -90,6 +90,24 @@
                 label="Titles After" />
             </v-col>
           </v-row>
+          <v-row dense>
+            <v-col cols="5">
+              <v-text-field
+                v-model="user.affiliation"
+                hint="e.g. University of xyz"
+                label="Affiliation" />
+            </v-col>
+          </v-row>
+          <v-row dense>
+            <v-col cols="5">
+              <v-text-field
+                v-model="user.orcid"
+                :rules="[v => validateOrcid(v) || $t('Invalid ORCID')]"
+                maxlength="19"
+                hint="e.g. 0000-0002-1825-0097"
+                label="ORCID" />
+            </v-col>
+          </v-row>
           <v-row dense>
             <v-col cols="5">
               <v-btn
@@ -136,6 +154,7 @@
   </div>
 </template>
 <script>
+import { isValidOrcid } from '@/utils'
 export default {
   data () {
     return {
@@ -151,7 +170,9 @@ export default {
         firstname: null,
         titles_after: null,
         titles_before: null,
-        email_verified: false
+        email_verified: false,
+        affiliation: null,
+        orcid: null
       },
       reset: {
         password: null
@@ -213,6 +234,12 @@ export default {
       }
       this.loading = false
     },
+    validateOrcid (orcid) {
+      if (!orcid) {
+        return true
+      }
+      return isValidOrcid(orcid)
+    },
     async resend () {
       try {
         this.loading = true
@@ -248,20 +275,19 @@ export default {
           titles_before: this.user.titles_before,
           titles_after: this.user.titles_after,
           firstname: this.user.firstname,
-          lastname: this.user.lastname
+          lastname: this.user.lastname,
+          affiliation: this.user.affiliation,
+          orcid: this.user.orcid
         }, this.config)
         console.debug('update', res.data)
         this.error = false
         this.$toast.success('Successfully updated user info')
       } catch (err) {
         console.error('update', err)
+        this.$toast.error('Failed to update user info')
         this.error = true
       }
       this.loading = false
-    },
-    setToken () {
-      this.user.has_invenio_token = false
-      this.api.invenio_token = ''
     }
   }
 }
diff --git a/fda-ui/utils/index.js b/fda-ui/utils/index.js
index d61b3165e553eeb4cfcde6e3c14ed1e902aa8a03..44d82b1ef560064c37cef242a7cc4140ee8ab5aa 100644
--- a/fda-ui/utils/index.js
+++ b/fda-ui/utils/index.js
@@ -28,6 +28,47 @@ function isNonNegativeInteger (str) {
   return str >>> 0 === parseFloat(str)
 }
 
+/**
+ * https://support.orcid.org/hc/en-us/articles/360006897674-Structure-of-the-ORCID-Identifier
+ * @param str The ORCID
+ * @returns {boolean} True if ORCID is valid, false otherwise
+ */
+function isValidOrcid (str) {
+  if (str == null) {
+    return false
+  }
+  if (str.length !== 19) {
+    return false
+  }
+  let total = 0
+  for (let i = 0; i < str.length; i++) {
+    const digit = parseInt(str.charAt(i))
+    if (isNaN(digit)) {
+      continue
+    }
+    total = (total + digit) * 2
+  }
+  const remainder = total % 11
+  const result = (12 - remainder) % 11
+  const check = result === 10 ? 'X' : result.toString()
+  return str.substr(18) === check
+}
+
+function formatUser (user) {
+  if (user.firstname && user.lastname) {
+    let name = ''
+    if (user.titles_before) {
+      name += user.titles_before + ' '
+    }
+    name += user.firstname + ' ' + user.lastname
+    if (user.titles_after) {
+      name += ' ' + user.titles_after
+    }
+    return name
+  }
+  return user.username
+}
+
 function formatDateUTC (str) {
   if (str === null) {
     return null
@@ -65,5 +106,7 @@ module.exports = {
   formatTimestampUTC,
   formatTimestampUTCLabel,
   formatDateUTC,
-  isNonNegativeInteger
+  isNonNegativeInteger,
+  isValidOrcid,
+  formatUser
 }