Enabling Time-based Restrictions in Conditional Access

The ability to restrict a user’s access to domain-bound systems has been a feature of Active Directory since Windows 2000 server, through the use of the Logon-Hours attribute in the Active Directory schema.

Not much has changed with this over the years, it provides a simple function, whereas if a user attempts to log into their system outside of the permitted hours, they will simply be denied. 

Looking at what is now Microsoft Entra, some professionals complain about the lack of feature parity between the two similarly named services, whereas some enthusiastically embrace the modern work approach to identity and access. Fundamentally, the on-premises and cloud-based identity solutions work on the same premise, to deliver identity and access management services, but their executions are quite different and with good reason to be.

Unfortunately, to this day, a similar solution to time-based access control in Microsoft Entra (formerly Azure Active Directory) is not yet available. That being said, the possibility of similar controls in Microsoft Entra is a nice thought, providing the challenge of changing time zones and simple evasion techniques is not too cumbersome for Microsoft to resolve. In this post I explore some findings which lead me to believe something may be changing.

Identifying potential time-based restrictions through Conditional Access

Currently, there has been no announcement or even a tease from Microsoft that they are working on time-base restrictions in Conditional Access, this is all speculation around information that is publically available. 

It is evident that no such settings to control access based on time/day exist through the Conditional Access wizard in the Microsoft Entra admin center, but what if we checked Microsoft Graph?

Well, by making a simple GET requested to the Beta endpoint for my Conditional Access policies (https://graph.microsoft.com/beta/policies/conditionalAccessPolicies) we can see an empty property returned called times.

Conditional Access times
Conditional Access times

Of course, this isn’t much to go by. Putting out some questions on social media forums like Twitter and Reddit only sparked further speculation about how to interact with this property and what it could be for, as even though it is only present against the beta endpoint, it’s still being returned publically. I mention this as although in most cases to avoid unexplained error, the GA version (v1.0) of Microsoft Graph is recommended, still, in many Microsoft docs and recommendations, the beta endpoint is still used/required, which poses the question of why this information is being returned at all?

If you haven’t used it yet, follow my guide on How to use the Microsoft Graph Explorer tool. This is a great tool for any PowerShell user to help you find permissions, find code samples and write scripts!

Possible time settings in Conditional Access

Another way to identify details in the Microsoft Graph response to Conditional Access policies is through the developer tools in Chromium web browsers (Edge or Google Chrome for example). This is something I go into a lot of detail on in my blog post: How To Use Invoke-MgGraphRequest with PowerShell.

To summarise, you can use the inspect network tools feature built into these web browser to view Microsoft Graph responses and payloads as you make changes through the portal. You can then use this information to make the same change programmatically next time.

Specifically, while creating a new Conditional Access policy, upon clicking save and waiting for my change request to appear, I noticed a prior validation request taking place:

CA graph requests
CA graph requests

Upon viewing the payload of this request, you can see how it parses templated/example data for the purpose of validation, and in this case, the data and format of time-base conditions:

Time settings in Microsoft Graph
Time settings in Microsoft Graph

This data in properly formatted JSON, looks like the following. Take note of some important values such as date range, daysOfWeek, startTime & endTime, timezoneID and isExcludeSet. Each of these values could be indicative of future settings.

"time": {
      "applyCondition": false,
      "all": 0,
      "included": {
        "dateRange": {
          "startDateTime": "2023-8-16 0:0:0",
          "endDateTime": "2023-8-17 0:0:0"
        },
        "daysOfWeek": {
          "allDay": false,
          "day": [
            0,
            1,
            2,
            3,
            4,
            5,
            6
          ],
          "startTime": "2023-8-16 0:0:0",
          "endTime": "2023-8-17 0:0:0"
        },
        "timezoneId": "",
        "type": 0,
        "isExcludeSet": false
      },
      "excluded": {
        "dateRange": {
          "startDateTime": "2023-8-16 0:0:0",
          "endDateTime": "2023-8-17 0:0:0"
        },
        "daysOfWeek": {
          "allDay": false,
          "day": [
            0,
            1,
            2,
            3,
            4,
            5,
            6
          ],
          "startTime": "2023-8-16 0:0:0",
          "endTime": "2023-8-17 0:0:0"
        },
        "timezoneId": "",
        "type": 0,
        "isExcludeSet": false
      }
},

Conclusion

Unfortunately, the parameters being exposed by the public Graph API can only be speculated on. Are these settings a red herring, or are they being actively developed at Microsoft? 

At the time of writing this post, no public announcement has been made and the information contained in this post is derived of what is made available through responses by the Microsoft Graph Beta API.

Daniel Bradley

My name is Daniel Bradley and I work with Microsoft 365 and Azure as an Engineer and Consultant. I enjoy writing technical content for you and engaging with the community. All opinions are my own.

Leave a Reply