Azure AD, apps and consent grant (service accounts)

In the past months. I’ve seen a lot of tickets and question from developer, service owner and some IT pros in regards of OAuth, consent and permissions (delegated/application).

Especially 3rd party applications and their documentation is missing very often some details. Therefore, I’m writing this post.

Continue reading

ApplicationAccessPolicy for EWS

I’m really excited about the fact that Microsoft fulfilled the ask for supporting Exchange Web Services (EWS) protocol in ApplicationAccessPolicy as announced here:

https://techcommunity.microsoft.com/t5/exchange-team-blog/application-access-policy-support-in-ews/ba-p/2110361

Unfortunately Microsoft seems to make it harder for you to add EWS permission full_access_as_app to your app.

Continue reading

Microsoft Graph: Get group info

As mentioned in my previous post here, daily tasks shifted and so I had a closer look into Microsoft Graph. In this post it’s about retrieving group information.

Background

In my daily work, I often have to deal with topics, where I need to collect more information about a group. Yes, the new UI in the AAD portal helps, but doesn’t provide all the information. On the other side there are a ton of PowerShell modules e.g.: MSOL, AzureAD or AzureADPreview.

Sorry, but I’m unhappy as not one module, gives me all information. In fact in some cases I have to use MSOL and AzureADPreview in order to get the whole picture. Besides the fact that some Cmdlets just throw an error in larger environements.

Solution

The only solution for me was to use Microsoft Graph and therefore, I wrote a function called Get-MSGraphGroup. Same like my other function Get-MSGraphUser, it incorporates all techniques from Microsoft Graph:

The function has the following parameters:

.SYNOPSIS
    This function uses Microsoft Office application for retrieving access token and queries Microsoft Graph for group properties.
.DESCRIPTION
    The Microsoft Office with ClientID d3590ed6-52b3-4102-aeff-aad2292ab01c can be used to retrieve an access token with the scopes AuditLog.Read.All, Calendar.ReadWrite, Calendars.Read.Shared, Calendars.ReadWrite, Contacts.ReadWrite, DeviceManagementConfiguration.Read.All, DeviceManagementConfiguration.ReadWrite.All, Directory.AccessAsUser.All, Directory.Read.All, email, Files.Read, Files.Read.All, Group.Read.All, Group.ReadWrite.All, Mail.ReadWrite, openid, People.Read, People.Read.All, profile, User.Read.All, User.ReadWrite, Users.Read
.PARAMETER Group
    The parameter Group defines the id of the group. Unless you use the parameter ByMail. If this parameter is used in addition, the function tries to get the id of the group by searching for a group with the specified e-mail address.
.PARAMETER AccessToken
    This optional parameter AccessToken can be used if you want to use your own application with delegated or application permission. The parameter takes a previously acquired access token.
.PARAMETER ByMail
    The parameter ByMail is a switch, which can be used in combination with Group, when an e-mail address instead of an id is used.
.PARAMETER Filter
    The parameter Filter can be used, when you want to use a complex filter.
.PARAMETER ShowProgress
    The parameter ShowProgress will show the progress of the script.
.PARAMETER ReturnMembers
    Switch to return members of group.
.PARAMETER ReturnMembersTransitive
    Switch to return transitive members of group.
.PARAMETER Threads
    The parameter Threads defines how many Threads will be created. Only used in combination with MultiThread.
.PARAMETER MultiThread
    The parameters MultiThread defines whether the script is running using multithreading.
.PARAMETER Authority
    The authority from where you get the token.
.PARAMETER ClientId
    Application ID of the registered app.
.PARAMETER ClientSecret
    The secret, which is used for Client Credentials flow.
.PARAMETER Certificate
    The certificate, which is used for Client Credentials flow.
.PARAMETER MaxRetry
    How many retries for each user in case of error.
.PARAMETER TimeoutSec
    TimeoutSec for Cmdlet Invoke-RestMethod.
.PARAMETER MaxFilterResult
    MaxFilterResult when Filter is used.
.EXAMPLE
    Get-MSGraphGroup -Group ServicesSales@bla.com -ByMail
    Get-MSGraphGroup -Group 6288514a-9840-4426-as05-d2955a03ea27
    Get-MSGraphGroup -Filter Get-MSGraphGroup -Filter "startswith(mail,'ServicesSale')"
.NOTES
    If you want to use your own application make sure you have all the necessary minimum permission assigned: Group.Read.All (this might change in the future. Consult the full permission reference for Microsoft Graph)

It has basically same functionality like Get-MSGraphUser, with the difference that it retrieves data from groups.

Performance

The function also supports multi threading using PowerShell runspaces. On top of this it is important to understand the following parameters:

  • ReturnMembers
  • ReturnMembersTransitive

By default only the total number of members will be returned. IF you need to get all members, you can use one of those switches. Be aware that this can take a while and depends on how many members a group has.

You might wonder about the difference between both:

ReturnMembers will return only members of a group. This can also be another group. It will not recursively resolve all levels down to a user object.

ReturnMembersTransitive will exactly do this for you: recursively retrieve flat list of all users.

Example

Just to give you a real-life example. We receive very often tickets, where it is asked about checking Exchange for issues as it seems not all members of a group received an important e-mail.

Well, before it was some kind of hassle to get the flat list of users. Now with this it’s easy as you can just use Microsoft Graph and transitiveMembers.

Where can I get the code?

As mentioned in previous posts, I’m super lazy and that’s why I have it somehow automated to load all my little helpers in combination with a tweaked PowerShell profile. You can find my little helpers here:

https://github.com/IngoGege/Miscellaneous/blob/master/ExchangePowerShell/HelperFunctions.ps1

You might wonder about the needed application and permissions. No worries as you can use (partially) the app “Microsoft Office” (appId: d3590ed6-52b3-4102-aeff-aad2292ab01c), which is available to everyone and has even the scope Group.Read.All or Directory.Read.All. Usually these permissions require Global Admin consent!

Conclusion

I hope this code helps YOU in your daily work. Feedback is always welcome!

Microsoft Graph: Get user info

Over the last weeks I had a steep learning curve with Microsoft Graph. In my daily job and especially as we moved to M365 it’s absolutely necessary querying attributes for users.

On-premises you most likely would use Get-AdUser or even just ADSI to do so. With the move to M365 you will call Microsoft Graph. And of course make use of OAuth2.0 flows for authentication and authorization.

Continue reading

The future of Exchange Online automation with EXOv2

I know that this topic is really a topic with gets high attention.At the moment there is nothing available in Microsoft Graph, which would make it possible to manage objects in Exchange Online.

The few things, which exists, are more for end-user (e.g.: accessing their e-mails, calendar or tasks) and for auditing and reporting (e.g.: Security API). Nothing available for managing a mailbox permissions or attributes. Not even like simple CustomAttribute1-15.

Now Microsoft released a new Exchange Online PowerShell module: EXOv2.

Continue reading

EXO V2 module, earlier .NET versions and pesky TLS1.0/1.1

It’s been a while that the new module for managing Exchange Online using PowerShell.If not yet aware, please check out how to Use the Exchange Online PowerShell V2 module.

It’s not perfect (yet!), but huge improvements and Microsoft is working hard to get the module improved.

On my transition to the new module, I was made aware of connectivity issues by some colleagues:

New-ExoPSSession : An error occurred while sending the request..
At C:\Program Files\WindowsPowerShell\Modules\ExchangeOnlineManagement\0.3582.0\ExchangeOnlineManagement.psm1:401 char:30…

PSSession = New-ExoPSSession -ExchangeEnvironmentName $ExchangeEnviro …

But the issue existed ONLY when using the parameter -Credential

Continue reading

The end is near (for legacy auth)!

Microsoft announced first the deprecation of Basic Authentication for Exchange Online and EWS protocol starting Oct. 13, 2020 here.

Note: At this time this affected ONLY the protocol EWS for mailboxes on Exchange Online!

Later it was announced that this also happens for other protocols like Exchange Active Sync (EAS), POP, IMAP and PowerShell at the same time here, in order to improve security.

Looking at the protocols, you might wonder about REST. This was announced for REST API v1.0 shortly after the announcement for EWS here and highlighted again here.

With this, there is no doubt that Basic Authentication is dead for Exchange Online and Microsoft Graph and every vendor should look into alternatives for authentication AND also update their products. There are still way too many products without support of Modern Auth.

The deprecation of Basic Authentication raises a few questions:

  • How can I access mailboxes with my service account?
  • My application needs access to all or only a subset of calendars. How can I securely configure this?
  • I need to Send-As or Send-on-Behalf of recipients’ e-mail addresses. What do I have to configure?

In this post I’m trying to cover some scenarios and try to explain advantages and disadvantages.

Note: This article is ONLY covering OAuth and Exchange Online! I assume you’re using a Bearer token for authentication in your request!

Continue reading

OAuth: Get-AccessToken

Since everything is shifting towards cloud, folks are looking more and more into possibilities and how cloud features can be incorporated into products.

One crucial topic is all around Authentication and Authorization. OAuth is the most used word in the past month,when I was approached by developers and they wanted to access somehow Exchange related data. I realized that many people having problems writing their code and usually we get blamed that we haven’t registered an application correctly in Azure AD.

Thus it’s on us to prove everything is okay and therefore I wrote a simple script for testing several scenarios in an easy way to make sure everything is configured correctly and you’re able to retrieve tokens.

Continue reading