User Impersonation — a secure, easy way to troubleshoot remotely
What is User Impersonation?
User Impersonation allows Administrators to access and operate as if they were logged in as that User.
Administrators can impersonate other authenticated users for testing purposes and view impersonation logs.
Why is this feature important?
This feature is useful when testing permissions and content that only your Partner Users can see. For example, if a Partner User has encountered an issue while using the system, an Administrator can use the User Impersonation feature to troubleshoot.
When impersonating another user, the administrator has access to exactly what that user can access in the system, including the same menus and modules. The instance records anything the administrator does while impersonating another user as having been done by that user.
Impersonation limitations:
- Impersonations are logged in the System Log. The Server record impersonated activities for auditing.
- Impersonate user will be having a read-only access for user impersonation.
Introducing Super Token:
For implementing Impersonation we will be using a Super-Token, This Super token will belong to Impersonate user token. This super token is use for maintaining audit logs of a impersonate user and switching back to user environment once impersonation is done.
Implementation:
- Impersonate User Token : We will be creating a temporary token of a client in x-access-token and impersonate token in super-x-access-token
/** Setting x-access-token and super-x-access-token **/
final ImpersonateResponseInfo impersonateResponseInfo = new ImpersonateResponseInfo();
impersonateResponseInfo.setImpersonateAccessToken(token);
impersonateResponseInfo.setUserAccessToken(authenticationResultType.getIdToken());
2. Impersonate Session : We will be creating one more session class for storing Impersonate user session details -
/** Class to set impersonate user session details **/@Componentpublic class ImpersonateUserSession extends UserSession{}
3. User Session and Ready Only Access : We need to store impersonal session data along with user session data using interceptors with read only permissions.
/** Fetching super-x-access-token from header **/final String impersonateUserToken = request
.getHeader(ApiConstants.IMPERSONATE_ADMIN_ACCESS_TOKEN);
if(StringUtils.isNoneEmpty(impersonateUserToken))
{
this.setImpersonateUserSession(impersonateUserToken);
this.setUserPermission(user);
}/** Setter implementation for impersonate user **/public void setImpersonateUserSession(final String token) {
try {
final UserDetails userDetails = TokenHelper.decode(token);
if (!ObjectUtils.allNotNull(userDetails.getUserId(), userDetails.getTenantId())) {
throw new UnauthorizedException(ApiConstants.USER_NOT_PRESENT_ERR);
}
final ImpersonateUserSession user = impersonateUserSession.get();
user.setTenantId(userDetails.getTenantId());
user.setId(userDetails.getUserId());
user.setEmail(userDetails.getEmail());
user.setApplicationPermissions(
this.rolePermissionService
.getUserRoles(userDetails.getUserId(), userDetails.getTenantId())
.getPermissions());
user.setToken(token);
} catch (final IOException e) {
log.error("Exception occurred while decoding the token.", e);
throw new UnauthorizedException(ApiConstants.UNAUTHORIZED_USER_ERR);
}
}/** Providing read only access to user **/public void setUserPermission(final UserSession user) {
user.setApplicationPermissions(ImmutableMap
.of(Permissions.ERP,
Arrays.asList(Permissions.ORG_SETUP_R, Permissions.ORGANIZATION_SETTINGS_R)));
}
4. Audit: We are providing impersonate user id to Spring AuditAware to track and log impersonate user’s activity.
/** Setting impersonate user id as current auditor for impersonate
user. **/@Override
public Optional<Long> getCurrentAuditor() {
try {
final UserSession session =
Objects.nonNull(impersonateUserSession.get()) ? impersonateUserSession.get(): userSessionProvider.get();
return Optional.of(session.getId());
} catch (Exception ex) {
log.info(
"In getCurrentAuditor() - Request coming from source which does not need authentication.");
return Optional.of(-1L);
}
}
Conclusion:
Using super-x-access-token and x-access-token we can provide client access to a impersonate user with restricted permissions. Also, we can store all audit details with Impersonate user id for Auditing purpose. Maintaining impersonate User Session using super-x-access-token also help us in switching back to impersonate user account.