Guest Access Reviews

TL;DR – A super simple way to review all guests with access to a tenant.

In certain scenarios guests from other tenants have to be invited to the enterprise tenant, i.e. B2B. However, good security practices dictate that guests should be reviewed to ensure users do not keep access when no longer needed. The documentation offers a few great options, including the ability to review all Microsoft 365 groups, which allows admins to manage guest access to those groups. However, I’ve worked with organizations that needed to review generic guest access to the tenant, that might have not been particularly associated with a specific group, and they also needed ability to automatically remove those guests from the tenant.

In this scenario, I just had to create a new dynamic group, which I creatively called “All Guests”, using the dynamic membership rule ‘(user.userType -eq “Guest”)‘.

Then I created an Access Review for the new ‘All Guests’ dynamic group. The key here is to ensure the scope is “Guest users only”, this is because the next option will not be available if that is not selected.

Then under “Upon completion settings” I chose the option to “Block user from signing-in for 30 days, then remove user from the tenant“.

Note: This option is only available when the scope is “Guest users only”.

When this option is selected, any users that are denied during the review processes are updated with ‘Block sign in’ set to ‘Yes’ and that remains in place for 30 days. At the end of the 30 days, any users which administrators have not updated the value of ‘Block sign in‘, i.e. those that still have blocked sign-in, are then removed from the tenant.

Reviewers still follow the standard procedure to provide feedback, by accessing the MyAccess URL and approving or denying the access.

Once the access review period is over or the review is manually stopped, the system automatically applies the changes as shown below:

Since the access review included the options above, at the end of the review period we can then see those denied users have been disabled, with ‘Block sign in’ set to ‘Yes’.

After 30 days those users are then automatically removed from the tenant, unless the value of this setting is manually updated by the administrators.

This is a very easy and efficient way to remove those guest users that no longer require access to a tenant.

Passwordless Azure VM SSH login using FIDO2 security keys (Part 3)

This post is part of a series.

Finally, we can see this passwordless ssh login in action. There are two scenarios depicted below. The first one is what happens when the user tries to login from a compliant device. The second one is what happens when the user tries to login from a noncompliant device. Both scenarios show a passwordless authentication, however one is stopped from connecting to the server due to the noncompliant device.

Note: I am demonstrating this flow from devices which have Azure CLI already installed.

(1) SSH login from a compliant device

The authentication flow in the video above is the following:

  1. Try to ssh to the VM “az ssh vm –ip ##.##.##.##“, which fails because I don’t have a token yet, since I haven’t authenticated.
  2. Type “az login” to authenticate, which triggers the new browser window to open.
  3. I chose my user ‘ChristieC’ and I am prompted for the login. The default authentication method for this user is the FIDO2 security key login.
  4. I am presented with the prompt to enter the PIN to unlock the security key (user verification) and I touch the key (user presence) to allow it to proceed.
  5. Now that I am authenticated, I try to ssh again “az ssh vm –ip ##.##.##.##“, which triggers the new browser window to open to very the Conditional Access policy requirements as shown in the message “Your device is required to be managed to access this resource“.
  6. Once my device is verified to be compliant and I accept the certificate, then I’ve successfully connected to the server.
(2) SSH login from a noncompliant device

But what happens if I try to login with the same user, but from a device that is not compliant?

As you can see above, I can still authenticate using the FIDO2 security key, however I cannot ssh to the server from the noncompliant device due the the Conditional Access policy in place. I can then chose to follow the steps to bring that device into compliance.

In summary, this demo shows a passwordless SSH login using FIDO2 security keys as well as some Conditional Access policies to check device compliance.

Passwordless Azure VM SSH login using FIDO2 security keys (Part 2)

This post is a part of a series.

I’ve chosen the scenario where SSH login is only allowed to the user if they are connecting from a compliant device, so I need a Conditional Access policy to enforce that restriction.

Conditional Access Policy

Under cloud apps, I selected “Azure Linux VM Sign-in” and “Azure Windows VM Sign-in”. The demo will just show Linux, but either one will work.

And then I selected to grant access only when the two conditions selected are met:

VM details

The users have been assigned either “Virtual Machine Administrator Login” or “Virtual Machine User Login” roles.

Additionally, this VM was provisioned to allow SSH using Azure AD credentials.

In part 3 of this series we’ll see the passwordless SSH login in action.

Passwordless Azure VM SSH login using FIDO2 security keys (Part 1)

TL;DR – Passwordless ssh to Azure VMs using FIDO2 security keys.

There are many great articles and documents on passwordless authentication, many of them are linked here. However, I wanted to focus on passwordless SSH login using FIDO2 security keys. And then I figured, why not go a little further and show this in action with some Conditional Access policies to check device compliance for good measure. That’s the topic of the posts in this series:

A super fast FIDO history recap…

The original FIDO standard is now referred to as U2F, which stands for Universal Second Factor, that is the MFA ‘flavor’ of FIDO. The new and improved (and fully passwordless) ‘flavor’ is UAF, which stands for Universal Authentication Framework, that’s FIDO2 and it uses WebAuthn and CTAP2 protocols. The most important detail is that both are based on public key cryptography and both are strongly resistant to phishing. However, FIDO2 UAF is the only passwordless protocol.

How does FIDO2 work?

It’s important to show how FIDO2 UAF works because that’s what makes it phishing resistant. However, I only highlight the most important steps below, but feel free to read more about it at the FIDO Alliance website.

The diagram above depicts the login authentication flow for FIDO2 passwordless (UAF). Prior to this point the user has already registered the security key with the relying party, that’s why the authenticator already has the private key and the relying party has the equivalent public key. The authentication flow steps are as follows:

  1. User requests access to the relying party.
  2. The relying party presents a challenge and its web origin.
  3. The browser derives the relying party id (RP ID) from the web origin value. In the case of Azure AD, the challenge passed is a nonce (‘number once’). This prevents the token replay attacks, because it can only be used once.
  4. The authenticator finds that unique pair for that specific user and that specific relying party and then prompts the user for the verification (pin or biometric). This prevents man-in-the-middle (MitM) attacks because the attacker won’t have the same web origin.
  5. Once the user verifies it’s the correct human, then the authenticator uses that private key to encrypt the challenge (nonce) and sends the authenticator data back to the browser, which sends it back to the relying party.
  6. The relying party then validates that the challenge was signed by the correct private key and that the nonce hasn’t been used yet and then it grants the id_token.

Note: WebAuthn is the protocol used between the browser and the relying party API, and CTAP is the protocol from the authenticator to browser.

Keep in mind the authenticator generates a unique key pair per user per relying party (web origin). So, I can use the same authenticator for two different users for the same relying party, but each has a unique key pair associated. And I can also store key pairs for different relying parties in the same authenticator. Additionally, the private key is only kept in the authenticator and it is not passed through the channels. The same goes for the PIN or biometric used to unlock the authenticator, they are not passed through the channels. This authentication process protects against phishing, man-in-the-middle, and token replay attacks.

Azure AD Setup

For this demo the only authentication method we need enabled is FIDO2 Security Key:

Although not required, it is highly recommended to restrict the specific security keys that can be registered by the users on the tenant. This is especially important for those organizations that have very specific compliance requirements. This is a fantastic security feature which unfortunately is not available with other identity providers. Some AAGUID values can be found here: Yubico, AuthnTrend. You can also find the AAGUID value from the authenticator registration information as noted here.

Please reference the Microsoft documentation for a current list of FIDO2 security keys that are known to be compatible with Azure AD UAF (passwordless).

In part 2 of this series I’ll go over the Conditional Access policy to only allow access from a compliant device.

Federating AWS with Azure AD

TL;DR – For an enterprise level authentication and authorization solution, federate AWS single-accounts with Azure AD.

Security best practices dictate that AWS root accounts should be used only on rare occasions. All root accounts should enable MFA, remove any access keys, and set up monitoring to alert in case the root account is used. For day-to-day work users should access their AWS services with their IAM users and the best practice is to federate that access with a reliable identity provider (IdP), such as Azure AD.

There are two main options to federate authentication for AWS accounts. In this blog I will show you the two options and I’ll explain why I prefer one over the other.


The first option is to federate AWS SSO. This is configured with the AWS SSO instance within the AWS Organization. As a reminder, AWS Organizations allow administrators to manage several AWS accounts. The single sign-on integration is done between AWS SSO and the Azure tenant. With this configuration, the users in Azure AD are assigned to the AWS SSO enterprise application, so they are not assigned to a specific AWS account. The assignment of users to the specific permission sets is done within AWS SSO. Those permission sets are what determine the user’s specific role(s) within the specific AWS accounts.

And this is the end-user experience when federating AWS SSO:

From MyApps, the user clicks on the AWS SSO enterprise application that was assigned to them in Azure AD, then they are presented with an AWS SSO menu of accounts and roles that were assigned to them via AWS SSO, which they can then click on to access the account with that specific role.

Please keep in mind the following details when using this setup:

  • Users and groups have to exist locally in AWS SSO, so this solution will provision users to AWS SSO when they are assigned to the AWS SSO enterprise application.
  • In a similar manner, users are disabled (not deleted) when they are removed from the AWS SSO enterprise application.
  • Since the roles are assigned within AWS SSO, Azure AD is not aware of which roles are assigned to which users. This becomes important if you need specific Conditional Access policies or specific access reviews and/or access packages within Identity Governance.
  • Supports SP and IdP initiated login, since the users exist locally on AWS SSO.
(2) AWS Single-Account Access

The second option is to federate the AWS Single Account. This is configured with each individual AWS account. The integration is done between the AWS account and the Azure tenant. Therefore, when the users in Azure AD are assigned to the AWS account enterprise application, they are assigned to a specific AWS account. Azure AD is fully aware of the specific account the users are assigned to as well as the specific AWS roles they are assigned to.

And this is the end-user experience when federating a single account:

From MyApps, the user clicks on the specific AWS single-account enterprise application that was assigned to them in Azure AD, then they are presented with the option of the roles that were assigned to them for that account, which they can then select to access the account with that specific role.

Please keep in mind the following details when using this setup:

  • Users and groups do NOT exist locally on AWS. That’s right, users and groups do not need to be provisioned or deprovisioned in AWS.
  • The provisioning configuration ensures roles created in AWS are synchronized to Azure AD, so they can be assigned to users.
  • Azure AD is fully aware of which roles are assigned to which users for specific accounts.
  • This configuration allows implementation of Conditional Access policies for the specific AWS accounts.
  • Only supports IdP initiated login, since the users do not exist locally in AWS.
  • To ensure AWS CloudTrail data accuracy, add the source identity attribute to identify the user responsible for AWS actions performed while assuming IAM roles.
  • When CLI access is required, the temporary credential can be generated using the AssumeRoleWithSAML CLI command. This will last as long as the session is valid (default is 12 hours).
Drumroll, please…

By now you probably guessed which option I lean towards. The AWS Single-Account access configuration should be selected for enterprises that have specific compliance requirements that include identity governance or any organization that wants to implement a zero trust model, since “least privileged access” is at the foundation.

There are several benefits to this configuration.

  • The lack of users in AWS means that users or their entitlements do not have to be removed in AWS when employees are terminated. 
  • The configuration allows the tracking of the specific AWS roles within Azure AD, which means access packages* can be created and then automatically assigned or be made available to be requested by users with their appropriate approvals.
  • Those access packages can also have associated access reviews* to ensure access is removed when no longer needed.
  • Specific Conditional Access* policies can be created for the specific AWS accounts. For example, you may require access to production AWS accounts only from compliant devices, but maybe the rules are not as tight for development AWS accounts.
  • Having one central identity governance solution means organizations have the ability to meet compliance, auditing, and reporting requirements. This also means that the principles of least privilege and segregation of duties* can realistically be enforced.

Some organizations have tried to manage AWS accounts with AWS SSO and implement some level of identity governance using security groups. However, as the organizations grow, it becomes unnecessarily complex and challenging to meet compliance requirements for the reasons described in detail in my previous post.

* More on those topics in follow-up posts.

Roles vs Groups

TL;DR – For an enterprise level solution that authorizes user access, use application roles as much as possible instead of security groups.

One of the principles of the zero trust model is “least privileged access”, which is very well documented. However, I am focusing on a specific area that sometimes goes unnoticed until it’s too late and it becomes painful to correct.

This is my attempt to warn security architects and anyone planning to implement a zero trust model to ensure they pay attention to this detail because it can be costly to correct later on.

First, some basics.

In general terms authentication (Authn) is the process of verifying a user is who they say they are, whereas authorization (Authz) covers what the user should have access to, the specific permissions that have been (hopefully) assigned to the user based on the job they do. This post focuses on authorization (Authz), the access the user gets once they are authenticated.

Authorization can be based on various triggers, among them group membership and/or role assignment:

  • Groups are a logical collection of users, which can have specific privileges assigned to them. Groups can be on-prem AD groups that are synchronized to cloud or cloud-only groups [Ref: M365 and AAD groups]. Groups are not necessarily tied to an application, but security groups can be used in multiple applications and can be used for access control purposes.  They can also be nested, meaning that group 1 can be a member of group 2, and so on.
  • Roles are used to assign permissions to users and groups. Roles are specific to a function within a specific application.
Applications and services handle authorization in different ways.

A security best practice for enterprise solutions is to have applications and services rely on a central identity provider (IdP) for authentication and authorization whenever possible. This is referred to as SSO (single sign-on) or federation. Reference this quickstart for additional details.

Those applications and services that delegate authentication and sometimes authorization to the central IdP, handle authorization in various different ways:

  • Some applications and services can only handle authorization internally, so we simply need to authenticate the user and the application knows what permissions (groups/roles/privileges/responsibilities/profiles) are assigned to that user. These applications do this various different ways, that includes:
    • The use of LDAP calls to a directory service to check group membership.
    • Through their own internal authorization. Many enterprise applications (SAP, Salesforce, etc.) have their own authorization mechanisms within the application. That means that there is no mapping between the permissions set within the application to any group in any directory and typically this is for a good reason, as we explain below. For applications/services with independent authorization, an integration solution (i.e. SCIM) is required to synchronize the assignment of permissions between the application/service and the identity management solution. This supports the ultimate goal of having a single identity governance solution to view, audit, and modify all roles and assignments that a user has access to. More on that on a follow-up post.
  • Some applications can be configured to receive and process an access token or assertion that is passed when the user logs in. These assertions or access tokens include attributes or claims that tell the relying or service provider what specific groups and/or roles are assigned to the user that is connecting.

The applications that can consume access tokes or assertions will process those claims (roles and/or groups) and proceed with the authorization based on the claims that were passed on that token. For example, if the claim in the access token includes [roles=’Admin’], then the user receives access to a special area granted only to admins. Keep in mind that regardless of the protocol payload (SAML assertion, OIDC access token, or a Kerberos token), they are all bound by a maximum header size.

As noted above these claims can include a variety of attributes, including groups or roles.

  • When groups are used, all groups that the user is a member of are typically included in the token. This includes groups that are not associated with the application/service. Some services, allow the prioritization of groups in the claims by using custom filters per application, but these results can often be unpredictable.
  • For roles, only the roles associated with that specific application are included.

Maybe smaller organizations can initially survive with using groups to determine the level of authorization to applications or services. However, larger enterprises, where users are often members of multiple groups, need to be concerned with the token size. All tokens have a maximum allowable limit due to header size restrictions. For example, Okta’s group limit is 100, Azure/O365 restricts SAML tokens to 150 groups, 200 groups for JWTs. Additionally, this affects Kerberos tokens which prevents login when a user is a member of around 125 groups or more. As such, if a user is a member of 202 groups, then the user will receive errors when trying to login to various applications/services (i.e. HTTP 400).

It’s just a math problem.

Applications and services can have a multitude of permissions. At the time of writing, Salesforce has a maximum of 1500 custom profiles, which is the main permission set within the service, Azure has a maximum of 5000 custom roles per tenant and AWS has a maximum of 5000 IAM roles per AWS account.  Any authorization that needs to be attached to security groups will then require a security group to be created per role per account/tenant. When you take in to consideration that many enterprises have hundreds of tenants and accounts, it starts to compound quite rapidly.  Even if an organization consolidates, typically the math for a large enterprise can realistically result in hundreds of thousands of security groups with users having to be members of hundreds of these groups, which can quickly add up to surpass the maximums mentioned above.

This is not new to the IT industry as many large organizations have experienced the growing pains of discovering these complications as they merge or expand in size and have a desire to increase their security posture. More information can be found by searching online for “token bloat”.

In addition to token bloat, there are also known AD replication issues with group membership sizing as well as the issue of the lifetime of groups, since groups can continue to exist long after the application is removed, and may even be used for other unintended purposes. Consequently, this is why most industry experts recommend that enterprises, or any organizations planning for their future, use role based authorization, instead of group membership due to the above mentioned restrictions and also due to the amount of information that can end up in the token.

How Azure AD makes it easier.

Unlike other IdPs, Azure AD natively handles and manages application roles for enterprise application, including many SaaS services as well as custom applications. Therefore, when assigning users to these services, the administrators can choose specific application roles, which are not mapped to any security groups.

These roles can also be included in access packages that can be assigned to or requested by end users and for which access reviews can be created.

In a follow-up post I will go into the various options that are available, as well as some of my own recommendations when architecting security solutions for identity governance.