We have a console app that we want to run on a schedule in the context of service_account1.
The app needs to access Outlook account for service_account2 using Graph API and read incoming emails.
I am trying to figure out the way to access service_account2 mailbox without requiring user intervention and skipping the consent screen.
One option I see is to manually get authentication code from /authorize endpoint by signing in as service_account2 and consenting to mailbox access by the application. This will give me the authentication code that I can use to get access_token and refresh_token programmatically and that would do the trick.
Is there a way to programmatically do it without having this initial manual step?
For daemon process/console app where you don't want user to explicitly sign-in, you can use client credentials grant.
You can create an application in Azure AD for your process and then use clientid and client secret to access the required resources. For mailbox your resource would be something like /users/{userPrincipalName}/mailfolders/inbox/messages under the graph api.
Here’s a sample for client credentials grant flow from daemon app - https://github.com/Azure-Samples/active-directory-dotnet-daemon/blob/master/README.md
Specifically for avoiding an explicit consent part see steps 9, 10 under this link - https://github.com/Azure-Samples/active-directory-dotnet-daemon/blob/master/README.md#step-2--register-the-sample-with-your-azure-active-directory-tenant.
Steps refer to 'TodoListService' as sample api, but in your case it will be graph I suppose.
Configure Permissions for your application. To that extent, in the
Settings menu, choose the 'Required permissions' section and then,
click on Add, then Select an API, and type TodoListService in the
textbox. Then, click on Select Permissions and select 'TodoListAdmin'.
This will allow this client app to access the service app using
TodoListAdmin role.
At this stage permissions are assigned correctly but client app is a
daemon service so it cannot accept the consent via UI to use the
service app. To avoid this situation, please click on "Grant
permissions" which will accept the consent for the app at the admin
level.
Late answer but it may help someone. I had a similar situation where I wanted to use a daemon to read from a shared mailbox but admins in my organization were not allowing the Mail.Read permission because of its capabilities to read from all mailboxes. I had to restrict the app to only one mailbox to get the consent from admin.
There is an option to scope the application permission to specific mailbox. This ensures that you are not reading from any other mailbox but only the ones you are allowed to. I used the client credential flow in my daemon.
Check the documentation here - https://learn.microsoft.com/en-us/graph/auth-limit-mailbox-access
Related
I have a Windows service that cycles through four different mailboxes, reads the emails into a CMS system, then deletes the emails. I have been using simple sign-on with IMAP, but apparently Microsoft has deprecated this option and I need to move to Microsoft Identity.
In my corporate environment I cannot use an app account due to security issues, so I have to use user logins.
Can I authenticate to a user using Microsoft Identity headless in a Windows service? I don't want to have to authenticate manually each time the service starts up, plus I am not even sure if I can have 4 Microsoft user accounts active at the same time. Any direction would be appreciated.
I'm assuming you mean the EWS web api.
To use Microsoft oauth you need a azure application registration with the delegated api permission EWS.AccessAsUser.All.
With this setup you can either access the mailbox of a user with the users login token (i.e. either using their username and password or interactive user login) or you can use user impersonation.
To use user impersonation you need a username and password of a user that is allowed to access the mailboxes you need access for.
Another way to go is to setup a azure application registration with a application api permission to EWS.AccessAsUser.All. This allows you access to all mailboxes. I would not recommend this as people may not like the fact you can access any mailbox in an organization.
Following the code examples from the URL above will get you access to only online mailboxes. To support a hybrid setup where the mailbox is either online or on-premise the missing link is to autodiscover the mailbox server URL(so you don't hardcode it to the Exchange online URL). This has been made very simple with autodiscover v2. It's a simple https request where the result is the URL of the exchange server to use.
I would recommend using the user impersonation along with autodiscover v2 for the most secure and most flexible setup.
I have been working on a c# application which performs gmail operations on a domain of users. What I am currently doing is using a service account to impersonate users using domain wide delegation. I am able to use the google admin directory sdk to get the list of user emails in the domain in order to impersonate the users. I then use the gmail API to perform account operations on the impersonated user.
To do all this I have to:
1a) manually install the json credential file for the service account
2a) enable domain-wide delegation
3a) enable the appropriate scopes to allow api calls for gmail
I am able to see instances of other applications which have the following flow:
1b) Login to super admin google account
2b) Using the workspace marketplace, perform a domain install to install an application for all domain users.
3b) Launch the app, which redirects to the applications web app.
I noticed that after the application redirects, they are able to access all data for all user's in the domain. From what I understand, installing the app allowed (2a) and (3a) to occur. So the proper scopes were set and the app is usable throughout the entire domain. My question is how are other applications able to achieve accessing all of the data without having to download a credential file for the service account (1a).
From what I gathered, the only way to iteratively access each user's data, you have to use a service account. So once the application redirects, how are they able to access all of the user's data without setting up a service account and how are they able to able to authorize a service account without manually downloading the service account credential file.
I found an video example of a third party app with this flow here:
https://youtu.be/WBNt38b7dQg?t=201
I am writing a .Net code to populate Google sheets from console application.
Reference article https://www.hardworkingnerd.com/how-to-read-and-write-to-google-sheets-with-c/
I understand that we should give access to the service account.
In my organization, I could not share it with the service account and i am hitting the below error.
Sorry, an item cannot be shared outside of [Company]
Is there a way to access/read/write the Google sheets via my own account
Any help on this (.net code) using own account instead of service account will be much appreciated.
Your console application needs to provide credentials that authenticate it, and allow asking for consent from the user (you) for the scopes permitted for that app.
This means, when your application makes a request to the Sheets API, it provides its credentials, and if allowed, the API will redirect the user to the app's consent screen, When consent is given to the application, it is able to perform requests in the name of the user.
The service account is an account that can impersonate a user in the domain, only if it was given domain-wide-authorization. Otherwise it can only access application data (data belonging to your own application).
So if you want an application to access user data, then it (the app) must have valid credentials, for the enabled scopes of the enabled APIs.
You can get OAuth 2.0 Client IDs credentials for your app by following the first 4 steps of this answer and use those instead of the service account credentials.
References:
Sheets API codelab recommended
Sheets API documentation
My use case is as follows. At regular intervals, a daemon process needs to:
Scan an email account in Office 365 for Non-Delivery Reports,
Extract some info from the email body,
Perform a task for the user account identified from that info.
My approach was to use Microsoft Graph (at which I'm new) to get in and do this - however if there is an easier approach please let me know. I'm having trouble with the .NET graph API in authenticating & getting tokens without user interaction.
I have been successful in using a Microsoft Graph console sample (https://github.com/microsoftgraph/console-csharp-connect-sample) to connect to the email account, after doing the usual setting up of the app and its permissions/scopes in Office 365, and using the App ID and "secret" to connect.
However, after spending a whole day researching and trying various ways to authenticate in the sample app, it always pops up a login window (see https://i.imgur.com/SmtPpYd.png) before API actions can be performed. Sadly I've failed to discover how to authenticate and get tokens without user interaction.
Can anyone help me in how this sample needs to be modified - i.e. how the authentication needs to be altered - in order for it to work without asking the user to log in?
I do have full admin access, so can grant whatever permissions needed in Office 365, I just need help working out what to grant and what to alter in the console app to skip the user interaction. This is my first encounter with MS Graph and my head is spinning so please be gentle. :)
Note this will eventually run as a daemon on a server, but initially I'm just trying to learn by performing actions in this console app.
This application sample is using a public client (that can't store secrets because you don't control the device/OS/environment) as you can see here.
Here the acquire a token using apps public identity and user's identity (hence the prompt).
You have to replace it by a ConfidentialClientApplication instead providing an additional secret (that you can generate from the portal) and then replace the acquisition by a client only token request.
As your application is not going to hold any user identity none of the /me shortcuts are going to work.
Lastly, as you want to crawl all users, you need to change the permissions you're requesting to an admin permission/scope and replace User.Read and Mail.Read by User.Read.All and User.Read.All. (don't forget to click on the "grant permissions button" once you save the scopes.
Hopefully that helps
From windows my service I need to be able to subscribe to event notifications in Office 365 meeting room calendars in my tenant. Because of security reasons, there is no way to use push notifications, thus using streaming notifications is only plausible (or polling, but that is the last resort).
But as described on that page, the scope of the subscription can not be changed from current user 'me'. Thus I can not rely on application role assignments (which I can already use to poll the calendars of interest with Graph API).
Of course, I have user credentials for those meeting room accounts - but basic authentication is not supported for a while.
The challenge: my service needs to act on behalf of the meeting room user(s) to subscribe and to receive notifications but from a daemon service, without user interaction.
Practically it will have a management UI, but after adding a meeting room the admin will leave that UI and the service will need to work alone, renew the subscription, re-establish stream in case of server restart.
I suppose, that the device profile is one option.
What approach/flow do you suggest?
I would say you have two options:
You can use the OAuth client credentials grant supported by Azure AD, which allows a service to get access tokens by simply presenting its client ID & client secret (no user creds required). In order to grant this service the authorization to access the calendar of the meeting room, you would have to get the administrator of the tenant to consent to your service one time. The instructions for getting this consent & getting tokens are described in this article. You should be able to use the calendars.read application permission to subscribe to the notifications (though I haven't tried it myself).
The other approach would be to have someone log into your service's management UI with the credentials of the meeting room, and grant consent for the service to access its calendar, using the normal OAuth authorization code grant and the calendars.read scope. Yes, this approach requires user interaction in the management console one time. But, your service will receive back a refresh token that will be long-lived, and can be used to acquire new access tokens without further user interaction. This refresh token is non-expiring by default, which may make it viable for your scenario. The refresh tokens lifetime can however be shortened by a tenant administrator, or can be revoked if someone intentionally disables/deletes your service's access.
The device profile flow is pretty much the second option. It still requires the user to sign-in, and the service still acts on behalf of the user. The only difference is how the user enters their credentials. It sounds like for your purposes, the regular OAuth authorization code flow will be more appropriate than the device profile flow (which is meant mostly for limited input devices).