I'm writing an application that needs to create Calendar events on a user's Outlook Calendar. However, I will not have access to their passwords, and they will most likely not be involved in the workflow to enter them at any point.
Is it possible to create these events with the user being authenticated? If not, are there alternatives?
This is for an on-premise Exchange Server, not Exchange Online.
You can use app impersonation, as long as the admin can add a service account and grant app impersonation. See https://msdn.microsoft.com/en-us/library/office/dd633680(v=exchg.80).aspx for more details.
If the user can use his Windows Login to login to the Exchange Server, you can simply use that - if your application runs on the users machine under his account. EWS-managed-API does that out-of-the-box.
If not, you could create an additional user on the Exchange Server, who creates the appointments on his own account and invites everyone per email.
Related
How to send service emails
from my backend with smtp.google.com or Gmail API while making sure
the secret stored on the backend server can only be used to send emails from a specific sender?
Goal
send user account activation emails from my backend
use smtp.google.com or Gmail API (i.e. no own SMTP server)
authenticate with OAuth2.0 (i.e. don't enable "less secure apps")
Current state
implemented the email sending part
for testing, I created a noreply#**.** Google Suite account
for testing, I generated an accessToken via OAuth2 Playground
using the accessToken I can send emails via smtp.googl.com
Problem
Google suggests to use a service account for this
But to send emails from no-reply#x.y I have to enable Domain-wide Delegation
Domain-wide delegation allows to impersonate every domain account
the secret stored on the backend should only allow to send mails from no-reply#**.**
Lets start with send user account activation emails from my server I am gong to assume that you have a web app. This web app allows users to register with your system. Now when a user registers with your system you want to automatically send them an account creation email. Your idea is to use Google rather than setting up your own smtp server and sending these emails from your own system. Not a bad idea really.
Lets think about this for a minute the emails would need to be sent automatically so you need some kind of service sending them. To do that you want to use a service account. Again this is a great idea using a pre authorized service account that you will not need to have a user to authorize the app.
The only issue is that service accounts do not work with normal gmail accounts. To use a service account with Gmail api you need to use a google workspace domain account. The workspace domain admin would then be able to add permissions to the service account letting it act like a user on the domain. In this case your idea of no-reply.
So your workspace domain account would have a user called no-reply. The domain admin would then configure domain wide delegation to the service account allowing it to pretend that it is the user called no-reply. For all intents and purposes the service account is the no-reply user. It will be able to send mails as if they are coming from that user.
For all this to work you will need the workspace account with that user.
Have a look at the following link, it's actually one of Google's better examples it shows how to set up the delegation.
Perform Google Workspace Domain-Wide Delegation of Authority
Here you create a service account with credentials, allow this account to impersonate other users (e.g. the no-reply user), to only use the Gmail API and to only use it to send emails.
the documentation is a bit outdated, you can skip the step Grant users access to this service account and create the service account key afterwards via the service account edit function: Manage keys
in the step Domain wide delegation you need Google Admin not the Google Cloud Platform Admin Console as in the previous step
Just remember to swap out the lines about
https://www.googleapis.com/auth/admin.directory.user,
https://www.googleapis.com/auth/admin.directory.group
and use
https://www.googleapis.com/auth/gmail.send
instead as you want to access the Gmail API and only allow the service account to send (not read) emails
tip
in the sample code in that link
.setServiceAccountUser(userEmail)
userEmail is the email address of the user you want to impersonate in this case no-reply#x.y
So I guess what I am saying is that what you want to do is definitely possible, however, it may be easier just to set up your own SMTP server.
We are integrating Google Calendar with our room booking system. Users in GSuite domain should login on our reservation screen and book a room. So far I made use of an service account with domain wide delegation to impersonate the users (the setSubject() method, passing the e-mail address of the impersonated user). Everything works, although this way we cannot verify if the user we want to impersonate is logged in successfully or not, the event will be just created with him as the organizer, because setSubject() only requires the email to work properly.
In IBM Domino, when using an Java XPage I was able to compare passwords of the user, not in plain text but there was a function which compared plain text with user's hashed password and returned true if they were equal.
As I see Google doesn't have such a thing if I'm right. How could I check if the user can successfully log in programmatically?
If you want to perform actions in Google Calendar on behalf of a currently logged-in user from a web browser, you might want to use OAuth2 for Web Server Applications instead of using a service account with impersonation.
Reviewing this, but not clear. Not looking to do this for just my user and can run with elevated application rights with access to all calendars.
https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/calendar_list_events
Yes you just need to make sure you give your application the following permission
Calendars.Read.Shared Read user and shared calendars Allows the app to read events in all calendars that the user can access, including delegate and shared calendars.
ref https://developer.microsoft.com/en-us/graph/docs/concepts/permissions_reference
So as long as the calling account then has access to the Room Mailbox (eg via Delegation so they can access the same thing in Outlook etc) you just use the following endpoint
https://graph.microsoft.com/v1.0/users('room#domain.com')/calendar/events
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.
We are trying to integrate Microsoft Exchange (sync appointments) into our web site (SPA)(Software as a Service), for this we are looking at EWS managed API as the preferred route, we have the end users email, but we do not want to store there exchange passwords (as they are generally same as users domain password), in such a scenario which is the best approach to take. Please Help.
The preferred way would be to define a new Exchange id for your integration program and allow it impersonation rights for each user whose mailbox you want to examine. The managed API will allow you to specify an impersonation id on each call. You authenticate with your program's userid and password, but have the rights within the Exchange store of the user you are impersonating. Thus you only have to manage a single password for your program and need not know users' passwords. Setting up the impersonation rights requires some fancy PowerShell commands from the Exchange Admin, but you only do it once.