EWS managed API: Is user A able to impersonate User B in a windows app? - exchange-server

I need to determine whether domain UserA -- currently running a Windows desktop application -- has permissions to impersonate another user in Exchange, say UserB.
I can try to do something like read UserB's inbox messages, but I was after a cleaner way to do it.
Is there no way to load the UserA's Exchange roles and look for ApplicationImpersonation or something else?
So the setup is like this:
ExchangeService service = new ExchangeService(exchangeVersion);
service.UseDefaultCredentials = true;
service.AutodiscoverUrl(userEmail);
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.PrincipalName, UserToImpersonate);
// Looking for something like this:
if (!service.CanImpersonate(userEmail, UserToImpersonate) )
{
Exception ex = new Exception(userEmail + " can't impersonate " + UserToImpersonate);
throw ex;
}

Not using EWS you would need to use the Exchange Management Shell cmdlets https://learn.microsoft.com/en-us/powershell/module/exchange/role-based-access-control/get-managementroleassignment?view=exchange-ps to check if applicationimpersonation is enable for a particular user. EWS is a Mailbox API and the setting your talking about is an administrative setting so the best you can do with EWS is deal with the exception and suggest corrective action.

Related

How to impersonate a user and insert a calendar in its behalf using service account?

I'm trying to create calendars and share them with my organization's users using a service account.
What I would like to obtain is the ability to manage the created calendars both from my website code (using the service account) and from the regular google calendar web interface.
So i thought I could create a dumb user account (with credentials), impersonate it with a service account and then create and share my calendars and manage events both from my weba pp code and google regular user interface.
Is it the right way to proceed? Am I missing something?
If my last guess is right how can I achieve it using laravel and google-api-clients for PHP?
Thank you for your advices
After Sleeping on it I realized there's no need to impersonate a user and insert a new calendar.
To manage a service account calendar from the officiale web interface you can simply share it with owner rights to the "dumb user"
With something like this:
//create calendar
$calendar = new Google_Service_Calendar_Calendar();
$calendar->setSummary('calendarname');
$calendar->setTimeZone('Europe/Berlin');
$service = new Google_Service_Calendar();
$createdCalendar = $service->calendars->insert($calendar);
//share it with your dumb user
$rule = new Google_Service_Calendar_AclRule();
$scope = new Google_Service_Calendar_AclRuleScope();
$scope->setType("user");
$scope->setValue('dumbuser#organization.com');
$rule->setScope($scope);
$rule->setRole("owner");
$createdRule = $service->acl->insert(createdCalendar->getId(), $rule);
So my problem is solved for the moment, the only question I'm still thinking about is how can I impersonate a user with service account credential? Well I'll think about it when it will be really useful

How to check Exchange the Application Impersonation Permission of a meeting resource by EWS managed API?

I want to get the calendar information of the meeting resource by an Application Impersonation account.
I need to check if the Application Impersonation account has permission to get the calendar information from the meeting resource.
(As I know the meeting resource can be set to refuse the access by the Application Impersonation account)
You can't do what you want using EWS as the only way to check the underlying permissions would be to use the Exchange Management Shell cmdlet. However the easiest way is just process the result of EWS operation you make eg with the EWS managed API if you don't have impersonation rights then you will received an error which will indicate that you don't have Impersonation rights. eg
try
{
//EWS request
}catch(Exception Exception)
{
if(Exception is ServiceResponseException)
{
switch (((ServiceResponseException)Exception).ErrorCode)
{
case ServiceError.ErrorImpersonateUserDenied:
break;
case ServiceError.ErrorImpersonationDenied:
break;
case ServiceError.ErrorImpersonationFailed:
break;
}
}
}

Using streaming notifications with delegate access

So far all information that I read about streaming notifications says that you are expected to use impersonation with streaming subscriptions when you want to subscribe to not your mailboxes. This sounds reasonable when you have service application that accesses user mailboxes. In my case I need to subscribe to calendars of room mailboxes.
Based on this answer: Getting notification from Resource calendar in EWS room mailboxes usually have their account disabled and I need to use delegation.
So what is proper way to subscribe and maintain affinity when using delegation? Should I just ignore setting the impersonation header and do everything else as described in How to: Maintain affinity between a group of subscriptions and the Mailbox server in Exchange?
When you creating folder object, pass the other user email address which shared his calendar with you. AS below
folders[0] = new FolderId(WellKnownFolderName.Calendar, new Mailbox("OtherUserEmail"));
And then subscribe.
service.SubscribeToStreamingNotifications
For resource rooms I use impersonation as the preferred access. I know that in general the AD userids for room resources are disabled for login in AD, but my guess is that affects only Windows login. Technically when you impersonate, you don't really login as the room user. You log in as the service account with those credentials, and then indicate with the impersonation id that you want Exchange to pretend it's actually the room making all the requests you are about to make.

Creating a service for user (S4U) token

The Windows Task Scheduler can create tasks that run with the account of a particular user, without storing the user password. They call it "S4U", service for user. This should work something like the scheduler creates such a token for the current user and can use it to run the scheduled process under that user account. They claim that it cannot access network or encrypted resources with this system. The scheduler itself runs with the SYSTEM account for it to work. Here's an article that describes it. The relevant quote from it:
TASK_LOGON_S4U is yet another option that provides a more secure
alternative. It takes advantage of a service for user (S4U) logon to
run the task on behalf of the specified user, but without having to
store the password. Since the Task Scheduler runs within the local
system account, it can create a S4U logon session and receive a token
that can not only be used for identification, but also for
impersonation on the local computer. Normally a S4U token is only good
for identification.
I need to use this authentication scheme in my application, but can't let the Task Scheduler do it but need to do it myself, because I need it for any number of accounts. Whenever a user registers a task with my application, any followup tasks must run under the same user. But since they cannot overlap, I need to do the serialisation myself.
I cannot find any information about this "S4U" thing. How could I implement it in my application? C# preferred, but WINAPI and C is okay.
Update: This is what I've tried, and it doesn't work.
// The WindowsIdentity(string) constructor uses the new
// Kerberos S4U extension to get a logon for the user
// without a password.
WindowsIdentity wi = new WindowsIdentity(identity);
WindowsImpersonationContext wic = null;
try
{
wic = wi.Impersonate();
// Code to access network resources goes here.
}
catch()
{
// Ensure that an exception is not propagated higher in the call stack.
}
finally
{
// Make sure to remove the impersonation token
if( wic != null)
wic.Undo();
}
But I've got the impression now, that you can't just say you want to be a certain user. Not even as System. You need to be logged in as that user and can generate some token that allows you to become that user later again, without the password. So this must be a two-step thing, first I need to get the token and store it on disk; later I can use that token to impersonate. None of the examples explains this.
"The computer may not be joined to the domain"
S4U requires access to a KDC. S4U is actually two protocols. S4U2Self and S4U2Proxy. What it is doing is using an addition to Kerberos to get service tickets for a user, but that account that goes and gets the ticket has to have a special delegation enabled on it. See here for this set up.
But unless you are actually letting the process die etc, why not just get the users service ticket or TGT? Is your application local or is it a service running remote to the user?
Task scheduler needs to go get a new one because a service ticket isn't valid forever. Or in some delegation schemes the user hasn't passed a service ticket to the Application Server and then the AS goes and requests and service ticket via S4U2Self, and then uses that service ticket to request a ticket to a second service via S4U2Proxy.

Using Delegates with Exchange Web Services

Has anyone used delegates with exchnage web services? I would like one user to be able to control other users' calendars in Exchange. I'm finding this problem to be a little tricky, and I'd like to see how others have been able to get it to work properly.
I'm just getting started here, but i managed to get access to Resource calendars via a delegate account.
I used the recommendations from this article about delegate account and resource accounts. (Resource accounts are tricky because they are disabled in the AD, and you have to use a delegate account to get access to them)
After setting up the delegate account on the server, I set up the ExchangeServerBinding using the credentials of the delegate account:
ExchangeServiceBinding binding = new ExchangeServiceBinding();
binding.Url = #"https://dc1.litwareinc.com/ews/exchange.asmx";
// Setup binding with username and password of the delegate account
binding.Credentials =
new NetworkCredential(delegateuserName, delegatepassword, "litwareinc.com");
(I'm using Microsofts prepared virtual server image for testing)
Then when accessing the mailbox, I set up a FindItemType request and use the smtp address of the account i want to access:
// Prepare request
var findItemRequest = new FindItemType();
// Setup the mailbox using the smtp address of the account wanted
var mailbox = new EmailAddressType {EmailAddress = mailboxId};
findItemRequest.ParentFolderIds =
new[] {new DistinguishedFolderIdType {Mailbox = mailbox}};
((DistinguishedFolderIdType) findItemRequest.ParentFolderIds[0]).Id =
DistinguishedFolderIdNameType.calendar;
findItemRequest.Traversal = ItemQueryTraversalType.Shallow;
// Add ItemResponseShapeType and Calendarview to request here ...
// The create a FindItemResponseType using the binding and the request
var response = binding.FindItem(findItemRequest);
So in short:
Setup an account with delegate access on the Exchange server, this can be done via owa or with a Exchange Shell script
Use the account with delegate access on the ExchangeServiceBinding object
Access target account using a FindItemType with the target account smtp-addres as EmailAddressType
Regards
Jesper Hauge

Resources