Sometimes, long running PowerShell scripts encounter the problem of Azure AD access token lifetime expiration. In other words, the default lifetime of tokens issued by Azure AD is too short to allow the script to complete before the token expires. Two solutions exist. Use a token lifetime policy to prolong access token lifetimes or check in code for potential expiration and renew when necessary.
I now have a Microsoft Graph Early Adopter badge. I didn’t ask for it. The badge just arrived via email. Which brings me to how to deliver product feedback. Sure, you can make comments via GitHub, but that ignores a perfectly good feedback portal developed to allow people to give direct feedback (including requests for new features) to Microsoft. You won’t get a badge for providing feedback via the portal, but it’s the right thing to do.
Protected actions are a new preview feature for Azure AD conditional access policies. You can associate protected actions with an authentication context and specify that anyone who wants to use these actions should meet the conditions set in a conditional access policy. Although only a limited set of actions are available in the preview, you can see the value of what Microsoft is doing and how it might apply to actions across the Entra and Azure portals.
Teams Shared Channels are a great way to collaborate across multiple Microsoft 365 tenants. From an administrative side, it’s nice to know about who’s connecting – who’s coming into your tenant to use a Teams shared channel and who’s leaving your tenant to share ideas in a Teams shared channel belonging to another tenant. This article explains how to retrieve that information from Azure AD shared user profiles.
Token protection is a new session control (preview) for Azure AD conditional access policies. The idea is to bind a sign-in token to a user’s device to stop attackers attempting to reuse the token to compromise the user’s account. Only a limited set of Microsoft 365 apps support token protection at present, but it’s an idea that should help if token theft becomes as pervasive as some predict.
The Microsoft Graph PowerShell SDK includes two cmdlets to revoke access for Azure AD accounts. As it turns out, Microsoft would prefer if developers use the Revoke-MgUserSignInSession cmdlet instead of Invoke-MgInvalidateUserRefreshToken, but who would have known if we hadn’t asked the question?
Two years ago, I wrote about how to generate a report about managers and the direct report from the information stored in Azure AD. As it turns out, the Get-User and Get-Recipient cmdlets have a little flaw that can make the data they return inaccurate. To make sure that the data is correct, a new version of the script uses cmdlets from the Microsoft Graph PowerShell SDK. We also format the output in a nicer way, so it’s all good.
In an unannounced move, Microsoft imposed a new limit on Graph requests using the List Users API that include the SignInActivity property. The old limit allowed a request to fetch 999 items; the new reduces it to 120 items. I’m sure that the change is made with the best possible motive, but introducing something like this without warning broke a lot of programs and scripts, and that’s just unacceptable.
Knowledge that Microsoft had plans for Azure AD PowerShell deprecation has been around for a couple of years. Now the time has come when things happen. Cmdlets that set licenses for Azure AD accounts are now retired and will stop working on or before June 30, 2023. If you haven’t already upgraded scripts, it’s time to do so.
The changes in Microsoft 365 keep on coming thick and fast. Changes range from the introduction of fundamental new technology like Microsoft 365 Copilot to an update to a small product detail. In this case, the Azure AD admin center is moving to the Microsoft Entra admin center. Microsoft has its own reasons for making this change, which will ripple out across the community to affect content developers and trainers. Is that a problem? Only if you don’t respond.
Microsoft has integrated Authenticator Lite, a subset of the full Microsoft Authenticator app, into Outlook for iOS and Android. The code allows users to respond to MFA challenges using number matching or one-time codes without leaving Outlook and is intended to help organizations deploy and manage MFA with less friction. Although you can’t use Authenticator Lite if the Authenticator app is present on the same device, integrating MFA capabilities direct into apps sounds like a great idea.
SharePoint Online is embracing Azure AD more closely by forcing new tenants to use the integration between the two Microsoft 365 components. In addition, site sharing will use the Azure AD invitation mechanism instead of SharePoint’s own code. The changes make a lot of sense and shouldn’t cause much disruption for tenants. It’s a good reminder to check the relevant policies that control external access via Azure B2B Collaboration.
The first app in a new community project called IdPowerToys helps Azure AD tenants to document conditional access policy settings in PowerPoint. The information used to document the CA policies is extracted (manually or automatically) from Azure AD, analyzed, and output as a PowerPoint presentation. It’s a nice way to see what CA policies exist in a Microsoft 365 tenant and helpful if you want to rationalize the set of policies in use.
The Azure AD sign-in frequency controls how often accounts must reauthenticate. Setting an unreasonably short value makes it more difficult for people to work because Azure AD constantly nags for credentials, including MFA challenges. I experienced the effect of such a policy last week and it wasn’t nice. Security policies need to be practical and pragmatic as well as effective.
The new Azure AD app property lock feature (in preview) prevents attackers updating the credentials for an Azure AD enterprise app so that they can get an access token and exploit the app’s permissions. This technique has been used in several attacks, notably the infamous SolarWinds exploit in 2021. The app property lock is not mandatory and it’s important to keep on checking the audit log to make sure that attackers don’t creep into your tenant.
Mail contacts have long been used by Exchange organizations to provide an identity for external people. Contacts show up in the GAL to make it easy for users to send messages to external people and they can be included in distribution lists. The downside is that mail contacts are only available to Exchange Online. Perhaps the time is right to consider switching focus to Azure AD guest accounts? We explore the option here.
Microsoft makes a 30-day Teams Premium trial license available to allow customers to test the premium features. Once the trial finishes, it’s a good idea to clean up and remove the Teams Premium trial licenses from the Azure AD accounts that participated in the trial, especially as the trial license has the same display name as the paid-for Teams Premium license. You can accomplish the task through the Microsoft 365 admin center, but we explain how to do the job with PowerShell too. The same technique works to remove any specific license from a set of user accounts.
It’s easy to invite people to become guest users in a Microsoft 365 tenant, but some of the invitees never accept the invitation. Perhaps they don’t need to redeem the invitation to do work or maybe it’s because they don’t want to. In either case, Azure AD guest accounts with unredeemed invitations can accumulate and become stale. In this post, we discuss how to use PowerShell to find and remove those stale accounts in a safe manner.
Azure AD registered devices store some information about the operating system and version used when registration occurs. Although this information changes over time and isn’t updated by Azure AD, it might be of some interest and use to tenant administrators, so we show how to report it here. If you want accurate information, you’ll need to use Intune.
Microsoft plans to support IPv6 connectivity for Azure AD starting on March 31, 2023. The change creates specific requirements for conditional access policies that use named locations to allow or block connections. Administrators will have to add new IPv6 address ranges to named locations to allow users to continue to connect. Apart from that, it’s a matter of making sure that any reporting, analysis, or SIEM applications can deal with the new IPv6 data.
Azure AD Guest Accounts have a habit of becoming stale or obsolete as time progresses. Guest accounts created to share documents or to be a member of a long-forgotten team or group remain in Azure AD until someone comes to clean them up. This article explains how we refreshed a popular script to use cmdlets from the Microsoft Graph PowerShell SDK to report guest accounts with different degrees of staleness.
Azure AD user accounts and Exchange Online mailboxes share many properties, including some for a user’s address. When it comes to countries, Azure AD has the country property while Exchange uses the CountryOrRegion property. Sometimes the two don’t match up. Why does this happen and does it matter in practical terms? What other country or regional settings exist that need to be managed? A simple question sets off a big discussion.
Getting a new device means that some work must be done to ensure that apps work. This article explains how to add QR codes to the Microsoft Authenticator app so that the app has the credentials to respond to MFA challenges. We cover how to get QR codes for Azure AD accounts and how to do the same for guest accounts in other Microsoft 365 tenants.
Several methods exist to add new user accounts to groups automatically. Dynamic group membership is an obvious option, but other choices exist, including org-wide teams (if your organization is under 10,000 accounts) and using PowerShell to manage the automatic addition of new members to a standard distribution list or Microsoft 365 group. This article examines the various methods. Once you understand what’s possible, you can make the right choice.
A fuss erupted about the Azure AD admin center setting to control Azure AD tenant creation by users. Allowing people to have their own tenant can be a good thing, especially for developers who want to have a tenant as a sandbox to test code in. In this article, we discuss what the control is, what it does, and how to set it with PowerShell.
The automation of Azure AD account creation and password updates are straightforward using the Microsoft Graph PowerShell SDK. A little preparation always helps, but once you have all the necessary information, it’s easy to code up the necessary script to generate a new password and add the account – or set of accounts.
The Azure AD admin center now includes the option to pause processing for the membership query for an Azure AD dynamic group. This article reviews how the new feature works and what it might be used for, including a PowerShell script to report the membership processing status of all Azure AD dynamic groups.
Azure AD custom security attributes can mark user and service principal objects for special processing, which is how the app filter for conditional access policies works. It’s nice to be able to interact with data through PowerShell and the Microsoft Graph PowerShell SDK cmdlets support setting, updating, and retrieval of Azure AD custom security attributes. Everything works, but it’s a pity that it’s a little clunky.
Azure AD conditional access policies can now use an app filter based on custom security attributes to restrict access to specific apps. It’s a neat idea that should be popular in larger enterprises where the need exists to manage large numbers of apps. In other news, the Graph X-Ray tool is available in the Windows Store and a neat cmd.ms tool is available to provide shortcuts to Microsoft 365 sites.
Azure AD conditional access policies can exert fine-grained control over the type of external users who can connect and what tenants they belong to. The new capability works especially well alongside Azure B2B Collaboration (guest users) and Azure B2B Direct Connect (used by Teams shared channels). It’s yet another way to impose control over who you allow to connect to your tenant.
Microsoft has made number matching and additional context generally available for its Authenticator app. The new capabilities help users to avoid MFA fatigue. In other words, instead of being challenged with a simple request to approve a sign-in, users must respond by entering a number selected by Azure AD. At the same time, Authenticator can display additional information, such as where the sign-in originated from. It all helps to make Authenticator a more secure way of approving user sign-ins.
In most situations, it’s a good idea to enable Azure AD accounts for SSPR (self-service password reset) to avoid the need for administrators to update user accounts when things go wrong. This article explains how to report accounts that are not yet set up to use SSPR. It’s a check that should happen regularly, perhaps with the aid of Azure Automation.
A reader asked how to update user email addresses and UPNs. As it turns out, this is not a very difficult technical challenge. The problem lies in the aftermath. It’s easy to update the primary SMTP address for a mail-enabled object or assign a new user principal name to an Azure AD account. Then problems might come into view, like needing to adjust the Microsoft Authenticator app to make MFA challenges work for the new UPN.
This article explains how to use PowerShell and the Office 365 audit log to report Azure AD license assignments. The output isn’t pretty, but it works. The code works by finding two different audit events for each license assignment and combining information from both events to create a view of what happened. It’s rough and ready and can be improved, but the principal is proven and that’s what I set out to do.
This article describes how to use the Exchange.ManageAsApp permission to allow Azure AD apps to run Exchange Online PowerShell cmdlets. You can do this in the Azure AD admin center for registered apps, but when the time comes to allow Azure Automation runbooks to sign into Exchange Online with a managed identity, you must assign the permission to the automation account with PowerShell. Easy when you know how, hard when you don’t!
A new setting for Azure AD conditional access policies allows organizations to dictate the authentication strength of accepted connections. This is part of a Microsoft effort to move MFA-enabled Azure AD accounts away from the relatively insecure SMS-based challenges to methods that are less susceptible to attack.
A script written by a Microsoft program manager to remove authentication methods from an Azure AD account caused me to write a script to capture all the authentication methods used in a tenant. I have other similar scripts, but this one records some additional detail for each method. And I have a moan about why the Microsoft Graph PowerShell SDK includes so many cmdlets for interacting with authentication methods. Some consolidation would be nice.
This article describes how to adapt the Microsoft 365 licensing report script to highlight Azure AD accounts that haven’t signed in for a long time. Because Microsoft charges for licenses on a monthly basis, every month that goes by racks up cost for underused accounts. The new version of the script tells you what accounts to check to help you focus on driving down licensing costs.
Audit logs hold lots of information, including records for when Azure AD consent permission grants happen. Checking the audit data can detect illicit grants. Records are in the Azure AD audit log and are also ingested into the Office 365 (unified) audit log, so there’s two places to check. The audit data is interesting and could help administrators work out if a permission grant is illicit. But only if checks are made and people review the reports.
Azure AD registered devices have 15 extension attributes that tenants can use for their own purposes. In this article, we explore how to use the Microsoft Graph PowerShell SDK to update extension attributes for registered devices, and even better, access the content in the extension attributes afterward.
{"id":null,"mode":"button","open_style":"in_modal","currency_code":"EUR","currency_symbol":"\u20ac","currency_type":"decimal","blank_flag_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/blank.gif","flag_sprite_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/flags.png","default_amount":100,"top_media_type":"featured_image","featured_image_url":"https:\/\/office365itpros.com\/wp-content\/uploads\/2022\/11\/cover-141x200.jpg","featured_embed":"","header_media":null,"file_download_attachment_data":null,"recurring_options_enabled":true,"recurring_options":{"never":{"selected":true,"after_output":"One time only"},"weekly":{"selected":false,"after_output":"Every week"},"monthly":{"selected":false,"after_output":"Every month"},"yearly":{"selected":false,"after_output":"Every year"}},"strings":{"current_user_email":"","current_user_name":"","link_text":"Virtual Tip Jar","complete_payment_button_error_text":"Check info and try again","payment_verb":"Pay","payment_request_label":"Office 365 for IT Pros","form_has_an_error":"Please check and fix the errors above","general_server_error":"Something isn't working right at the moment. Please try again.","form_title":"Office 365 for IT Pros","form_subtitle":null,"currency_search_text":"Country or Currency here","other_payment_option":"Other payment option","manage_payments_button_text":"Manage your payments","thank_you_message":"Thank you for supporting the work of Office 365 for IT Pros!","payment_confirmation_title":"Office 365 for IT Pros","receipt_title":"Your Receipt","print_receipt":"Print Receipt","email_receipt":"Email Receipt","email_receipt_sending":"Sending receipt...","email_receipt_success":"Email receipt successfully sent","email_receipt_failed":"Email receipt failed to send. Please try again.","receipt_payee":"Paid to","receipt_statement_descriptor":"This will show up on your statement as","receipt_date":"Date","receipt_transaction_id":"Transaction ID","receipt_transaction_amount":"Amount","refund_payer":"Refund from","login":"Log in to manage your payments","manage_payments":"Manage Payments","transactions_title":"Your Transactions","transaction_title":"Transaction Receipt","transaction_period":"Plan Period","arrangements_title":"Your Plans","arrangement_title":"Manage Plan","arrangement_details":"Plan Details","arrangement_id_title":"Plan ID","arrangement_payment_method_title":"Payment Method","arrangement_amount_title":"Plan Amount","arrangement_renewal_title":"Next renewal date","arrangement_action_cancel":"Cancel Plan","arrangement_action_cant_cancel":"Cancelling is currently not available.","arrangement_action_cancel_double":"Are you sure you'd like to cancel?","arrangement_cancelling":"Cancelling Plan...","arrangement_cancelled":"Plan Cancelled","arrangement_failed_to_cancel":"Failed to cancel plan","back_to_plans":"\u2190 Back to Plans","update_payment_method_verb":"Update","sca_auth_description":"Your have a pending renewal payment which requires authorization.","sca_auth_verb":"Authorize renewal payment","sca_authing_verb":"Authorizing payment","sca_authed_verb":"Payment successfully authorized!","sca_auth_failed":"Unable to authorize! Please try again.","login_button_text":"Log in","login_form_has_an_error":"Please check and fix the errors above","uppercase_search":"Search","lowercase_search":"search","uppercase_page":"Page","lowercase_page":"page","uppercase_items":"Items","lowercase_items":"items","uppercase_per":"Per","lowercase_per":"per","uppercase_of":"Of","lowercase_of":"of","back":"Back to plans","zip_code_placeholder":"Zip\/Postal Code","download_file_button_text":"Download File","input_field_instructions":{"tip_amount":{"placeholder_text":"How much would you like to tip?","initial":{"instruction_type":"normal","instruction_message":"How much would you like to tip? Choose any currency."},"empty":{"instruction_type":"error","instruction_message":"How much would you like to tip? Choose any currency."},"invalid_curency":{"instruction_type":"error","instruction_message":"Please choose a valid currency."}},"recurring":{"placeholder_text":"Recurring","initial":{"instruction_type":"normal","instruction_message":"How often would you like to give this?"},"success":{"instruction_type":"success","instruction_message":"How often would you like to give this?"},"empty":{"instruction_type":"error","instruction_message":"How often would you like to give this?"}},"name":{"placeholder_text":"Name on Credit Card","initial":{"instruction_type":"normal","instruction_message":"Enter the name on your card."},"success":{"instruction_type":"success","instruction_message":"Enter the name on your card."},"empty":{"instruction_type":"error","instruction_message":"Please enter the name on your card."}},"privacy_policy":{"terms_title":"Terms and conditions","terms_body":null,"terms_show_text":"View Terms","terms_hide_text":"Hide Terms","initial":{"instruction_type":"normal","instruction_message":"I agree to the terms."},"unchecked":{"instruction_type":"error","instruction_message":"Please agree to the terms."},"checked":{"instruction_type":"success","instruction_message":"I agree to the terms."}},"email":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email address"},"success":{"instruction_type":"success","instruction_message":"Enter your email address"},"blank":{"instruction_type":"error","instruction_message":"Enter your email address"},"not_an_email_address":{"instruction_type":"error","instruction_message":"Make sure you have entered a valid email address"}},"note_with_tip":{"placeholder_text":"Your note here...","initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"empty":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"not_empty_initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"saving":{"instruction_type":"normal","instruction_message":"Saving note..."},"success":{"instruction_type":"success","instruction_message":"Note successfully saved!"},"error":{"instruction_type":"error","instruction_message":"Unable to save note note at this time. Please try again."}},"email_for_login_code":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email to log in."},"success":{"instruction_type":"success","instruction_message":"Enter your email to log in."},"blank":{"instruction_type":"error","instruction_message":"Enter your email to log in."},"empty":{"instruction_type":"error","instruction_message":"Enter your email to log in."}},"login_code":{"initial":{"instruction_type":"normal","instruction_message":"Check your email and enter the login code."},"success":{"instruction_type":"success","instruction_message":"Check your email and enter the login code."},"blank":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."},"empty":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."}},"stripe_all_in_one":{"initial":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"empty":{"instruction_type":"error","instruction_message":"Enter your credit card details here."},"success":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"invalid_number":{"instruction_type":"error","instruction_message":"The card number is not a valid credit card number."},"invalid_expiry_month":{"instruction_type":"error","instruction_message":"The card's expiration month is invalid."},"invalid_expiry_year":{"instruction_type":"error","instruction_message":"The card's expiration year is invalid."},"invalid_cvc":{"instruction_type":"error","instruction_message":"The card's security code is invalid."},"incorrect_number":{"instruction_type":"error","instruction_message":"The card number is incorrect."},"incomplete_number":{"instruction_type":"error","instruction_message":"The card number is incomplete."},"incomplete_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incomplete."},"incomplete_expiry":{"instruction_type":"error","instruction_message":"The card's expiration date is incomplete."},"incomplete_zip":{"instruction_type":"error","instruction_message":"The card's zip code is incomplete."},"expired_card":{"instruction_type":"error","instruction_message":"The card has expired."},"incorrect_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incorrect."},"incorrect_zip":{"instruction_type":"error","instruction_message":"The card's zip code failed validation."},"invalid_expiry_year_past":{"instruction_type":"error","instruction_message":"The card's expiration year is in the past"},"card_declined":{"instruction_type":"error","instruction_message":"The card was declined."},"missing":{"instruction_type":"error","instruction_message":"There is no card on a customer that is being charged."},"processing_error":{"instruction_type":"error","instruction_message":"An error occurred while processing the card."},"invalid_request_error":{"instruction_type":"error","instruction_message":"Unable to process this payment, please try again or use alternative method."},"invalid_sofort_country":{"instruction_type":"error","instruction_message":"The billing country is not accepted by SOFORT. Please try another country."}}}},"fetched_oembed_html":false}