With the imminent death of basic auth and a shocking number of application people who have not taken any steps whatsoever to do anything about it I have been creating a LOT of applications to send and receive mail via graph. This is basically building a service principal, giving it the access then using an application access policy to limit it to accessing on a single or group of mailboxes
There are loads of resources on how to do this and test it but nothing I could find with a full setup, test and explanation you can use to get this over to an application guy who has only ever used imap and smtp auth in one place.
So here is my process for creating and testing the app registration, limiting it with an App Access Policy and testing the whole thing with Postman.
There’re 6 steps below:
1 Create your Application Registration
2 Grant the API Permissions
3 Create a client secret
4 Test the Application Registration (Optional)
5 Create an Application Access Policy
6 Test the App Registration and Access Policy (Optional)
1 Create your Application Registration
This is easy to do in Azure AD. Go to aad.portal.azure.com and hit Azure Active Directory then App Registrations.
Click + New Registration and give your app a name, you dont actually need a Redirect URI as we arent authenticating a user but fill yer boots.
Hit Register and you app will be created.
2 Grant the API Permissions
We are going to use Application API permissions not delegated because there is no user sign in going on. This is workable with exchange and mail.xxxx permissions as you can limit them to items using access policies. For everything else you would be creating a massive problem -Files.read for example has no limit your app can read EVERYTHING!!
Once you application is done, go into it and hit API permissions then “Add a permission”. Select the Microft Graph API
Next you want “Application permissions” then to find Mail and grant Mail.Read and Mail.Send
Click the Add permissions button and you will land back at the Configured permissions window. You will notice you new permissions are listed there but with a status of “Not Granted for {Tenant}”
Just click the Grant admin consent for {tenant} button to grant consent
3 Create a client secret
You can of course use certificates if you want but 9/10 app developers will not be ready to support them.
Really for security you should create the Application Access Policy before the client secret but I want to demonstrate the effect of the policy so I am doing it the wrong way round which means that for at least a limited time a client secret will exist with access to all of my mailboxes
Anyway, still in your app registration just go to Certificates and Secrets, hit the Client Secrets tab then click +New Client Secret
In the Add a client secret pop out give the client secret a description (I like to include the date I created it and who I provided it to) and select the duration.
Two things to consider on durations – the first is that this is effectively a password for whatever resources the application can access that has no MFA which lends itself to a shorter duration. The second is that someone has to remember to replace the thing every time the duration runs out and update it in whatever app uses it. This second point sounds like a longer duration is better as you need to update less frequency but in fact the opposite is true, if something has to be done every 6 months then someone will recall how to do it, if something just stops working in 5 years then likely as not no one will remember why. I always say the absolute maximum is 1 year and 6 months is really the best option.
Click Add and you secret will be created and displayed. IMMEDIATELY COPY IT SOMEWHERE SECURE. Whatever password solution you use, put it there as once you leave this windows you cant get it back.
You should also record the application or client ID from the Overview tab.
4 Test the Application Registration (Optional)
No we can test the application, I always like to actually test my apps to make sure it does what I expect and I use postman to do it.
I would 100% say you should do this at least once just so you understand the flow.
So get postman from https://www.postman.com/downloads/ and install it. Open it up, you can skip registration and all that noise.
On the tab bar along the top click + to start a new tab/request. We are going to use a post request to https://accounts.accesscontrol.windows.net/{{your tenant id}}/oauth2/v2.0/token to generate a shiny new token. The only thing we need to set up is the body:
Once you have set the values you can hit send and you should get a access token back:
You can take that token and have look at it in jwt.io if you want to make sure it has the app name and roles you expect but this is not necessary other than for interest or troubleshooting and it isnt advisable to copy tokens around unless you’re pretty sure you know what you are doing or noone important is watching.
Okay now we can check the token actually works, so back in Postman create another new tab/request. This time we are going to run a get to have a look at some mail in a mailbox.
So the URL specifies what mailbox we want to look at e.g. https://graph.microsoft.com/v1.0/users/PicardJL@enterprise.starfleet.com/messages (remember right now this can be ANY mailbox!) and the important bit is the new header we have added, its called “Authorization” and the value is “bearer {your token from the post above}“
Once that’s set up you can send it and you will see a reply with the mailbox contents in JSON:
5 Create an Application Access Policy
An application access policy can restrict an application to be able to access only a set mailbox or group of mailboxes.
They are created in PowerShell using the Exchange Online Module and it reall-y couldn’t be simpler.
New-ApplicationAccessPolicy -AccessRight RestrictAccess -AppId "{Your App ID}" -PolicyScopeGroupId JLPicard@enterprise.starfleet.com -Description "Restrict HRMail app to target mailbox"
Yeah that’s it, whack in your App ID and set the target mailbox (you can also a mail enabled security group and presumably anything else that’s a security principal but not a DL or annoyingly a dynamic DL)
The RestrictAccess right restricts the apop to allow access ONLY to the specified mailbox. You can also use DenyAccess to restrict access to anything other than the specified mailbox but I have honestly never needed to do this.
You can test this using
Test-ApplicationAccessPolicy -Identity kjaneway@voyager.starfleet.com -AppId {Your App ID}
and it will tell you if that app can access the target mailbox.
6 Test the App Registration and Access Policy (Optional)
Okay now* we can headback to postman and test our app and policy.
*Not “now” Application Access Policies can take up to an hour (that I’ve seen) to take effect EVEN IF YOU TESTED THEM IN POWERSHELL AS ABOVE so if you are not testing first as below you should not provide the client secret to whoever wanted it until at least an hour has passed
So Back in postman, run your Post again to get your token
Then run your get to read the mailbox contents:
NOW you can run your get against any other mailbox, e.g. https://graph.microsoft.com/v1.0/users/KJaneway@voyager.starfleet.com/messages
and you will see a nice new message:
Conclusion
So yay! We have an app that can use a single mailbox (it can send and receive, I may one day do a quick post on running a send with Postman but today is not that day)
The very first response you are gonna get after doing this for some Applications fella and explaining it all is not the expected “Wow! Thanks!” its “Ah man I need to read a SharePoint file can I have Files.Read.All as well”? Which, by this method, would allow the app to read anything in SharePoint so you will start a 6 weeks process of explaining to higher and higher level folk why that is not a good idea.
What you want for this is delegated permissions and resource owner password credentials. Which I will write about next!