This is an often asked question but the solution is simple:

So how does it work?
First we obtain the user’s primary access token with the WtsQueryUserToken  API call. To call this function successfully, the calling application must be running within the context of the LocalSystem account and have the SE_TCB_NAME privilege (LocalSystem has this privilege by default). Since the function returns a primary acces token we can just pass this to CreateProcessAsUser and voila!