Manage External Identities with Azure AD B2B/B2C

Last week I hosted a webinar together with our partner Condatis, where we talked about how to manage External Identities with Azure AD B2B/B2C.

Thanks to all who attended it live!

You can now watch it anytime on YouTube:

Stay safe!

Posted in azure ad, Password | Tagged , , , , , | Leave a comment

Using FIDO2 security keys with PowerShell

If you are using a FIDO2 Security Key, such as a YubiKey, you may have run into the issue that you cannot use it to authenticate with your Azure AD account using PowerShell:

IEnoFIDO

As you can see, the needed Sign in with a security key option is missing here.

This is because PowerShell still uses the older Active Directory Authentication Library (ADAL) when prompting for Azure AD credentials. That login prompt is actually rendered using Internet Explorer, and IE will likely never have support for WebAuthN, the protocol that FIDO2 logon requires.

So we have four options:

  • Wait until PowerShell moves from ADAL to MSAL, and sign in prompts are rendered by a modern browser that supports WebAuthN.
  • Wait until each PowerShell Module you need starts supporting its own implementation of modern authentication to Azure AD.
  • Use Cloud Shell, where you can run PowerShell directly in your browser:http://shell.azure.com/powershell

    This option works with FIDO2, but a web-based shell has its limitations.

  • Use Device Authorization Grant Flow to login.
  • This post explains the last option.

    What is Device Authorization Grant Flow

    The Device authorization grant flow is usually used when you need to sign in on “input-constrained devices”, such as IoT devices and printers. In this case, we can view PowerShell as a “device”. The sign in flow is initiated on the device, but the user needs to visit a web page (on any device with a browser that hopefully supports WebAuthN) to complete the sign in. Once the user has signed in, the device (or PowerShell window) can get the needed access tokens and refresh tokens.

    Initiate the Device Authorization Grant Flow

    Run this code in the PowerShell window you want to sign in to Azure AD:

    Note: You do not need to register any new app in Azure AD for this to work since we are using the well-known ClientID for Azure AD PowerShell. You do not have to add any custom values for your tenant either, since we use the Common endpoint. This means that you will automatically be redirected to the tenant the user belongs to when signing in.

    $ClientID = '1b730954-1685-4b74-9bfd-dac224a7b894'
    $TenantID = 'common'
    $Resource = 'https://graph.windows.net/' #Service Endpoint for Azure AD Graph
    
    $DeviceCodeParameters = @{
        Method = 'POST'
        Uri    = "https://login.microsoftonline.com/$TenantID/oauth2/devicecode"
        Body   = @{
            client_id = $ClientId
            resource  = $Resource
        }
    }
    
    $DeviceCodeRequest = Invoke-RestMethod @DeviceCodeParameters
    Write-Host $DeviceCodeRequest.message -ForegroundColor Green
    

    A code will be shown that you need to enter at the following web page to continue the sign in:

    initiate

    Besides https://microsoft.com/devicelogin, you can also use http://aka.ms/devicelogin. Both will redirect you to https://login.microsoftonline.com/common/oauth2/deviceauth.

    Enter the code in the prompt:

    DeviceAuth

    As you can see, we are now signing in on a remote device or service.

    Be aware that this sign in method can be misused in phishing attempts. Only enter codes you generated yourself!

    You can sign in using your regular account name and password, but to sign in using a FIDO2 key, click on Sign-in options:

    Sign-in

    Now we can use our FIDO2 key to authenticate:

    FIDO2

    Once authentication is successful, you can close the page in the web browser. The next step (obtaining tokens) will happen in the PowerShell window:

    close

    Obtain the tokens

    Again, no customization is needed for this script block. We are re-using the device_code from the DeviceCodeRequest we made earlier.

    
    $TokenParameters = @{
        Method = 'POST'
        Uri    = "https://login.microsoftonline.com/$TenantId/oauth2/token"
        Body   = @{
            grant_type = "urn:ietf:params:oauth:grant-type:device_code"
            code       = $DeviceCodeRequest.device_code
            client_id  = $ClientId
        }
    }
    
    $TokenRequest = Invoke-RestMethod @TokenParameters
    $Token = $TokenRequest.access_token
    

    You now have a valid access token in the variable $Token that can be used to authenticate when using Connect-AzureAD. Note that the variable $TokenRequest also contains refresh_token and id_token, if you want to use them.

    Connect to Azure AD

    When using the Connect-AzureAD cmdlet with an access token, you also need to specify the username you used to authenticate and the TenantId. You can find your TenantID using PowerShell:

    
    $TenantDomain = "tomdemo.se"
    (Invoke-WebRequest https://login.windows.net/$TenantDomain/.well-known/openid-configuration|ConvertFrom-Json).token_endpoint.Split('/')[3]
    

    or by going to :

    https://www.whatismytenantid.com/

    Now we are ready to connect to Azure AD:

    Connect-AzureAD -AadAccessToken $Token -AccountId admin@tomdemo.se -TenantId <insert-tenant-id-here>
    

    Now you should be able to run commands from that module, like this one to get the first group:

    
    Get-AzureADGroup -Top 1
    

    What if I need to use the Microsoft Graph?

    That will also work, but you need to change $Resource variable in the first script block to the Service Endpoint of Microsoft Graph (https://graph.microsoft.com/&#8221;) and repeat the process.

    Then you should be able to run queries against the Microsoft Graph, like this one to get the first group:

    $GroupsParameters = @{
        Method  = 'GET'
        Uri     = 'https://graph.microsoft.com/v1.0/groups?$top=1'
        Headers = @{
            'Authorization' = "Bearer $Token" 
        }
    }
    
    $GroupRequest = Invoke-RestMethod @GroupsParameters
    $GroupRequest.value  
    

    How about Exchange Online?

    For this to work, you need to change both the $Resource and the $ClientID variables in the first script block to:

    ClientID = 'a0c73c16-a7e3-4564-9a95-2bdf47383716' # Exchange Online PowerShell Azure Active Directory
    $TenantID = 'common'
    $Resource = 'https://outlook.office365.com/' # Service Endpoint for Exchange Online
    

    When you sign in, you will see that you are signing in to Microsoft Exchange Online Remote PowerShell:

    image

    After you obtain the token you need to create a new credential object based on your username and the token:

    
    $upn = 'admin@tomdemo.se'
    $TokenAsSecString = ConvertTo-SecureString "Bearer $($token)" -AsPlainText -Force
    $credential = New-Object System.Management.Automation.PSCredential($upn,$TokenAsSecString
    

    Now you can connect to Exchange Online using these commands:

    $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://outlook.office365.com/powershell-liveid?BasicAuthToOAuthConversion=true" -Credential $credential -Authentication Basic -AllowRedirection
    Import-PSSession $session
    

    Thanks

    Big thanks to Stefan Schörling (@stefanschorling) for pointing me in the right direction and to Simon Wahlin for his writeup about Device login flow for MS Graph access.

    Posted in Okategoriserade | Leave a comment

    Highlight custom text on any Microsoft Docs page

    Sometimes I want to highlight specific text when I’m sharing a Microsoft Docs-page to someone, like in this example:

    clip_image002

    You can do this yourself by appending the following text after the Docs-link:

    ?view=o365-worldwide#:~:text=Text To highlight

    Unfortunately, this only works in Edge and Chrome, not in Firefox or IE.

    Here’s an example:

    Original Docs-link:
    https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-whatis

    Appended text:
    https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-whatis?view=o365-worldwide#:~:text=cloud-based identity

    Result:

    clip_image004

    The yellow highlighting goes away when you click anywhere on the page or reload it.

    If you want to highlight more text, you can add start text and end text. Everything in-between will be highlighted:

    ?view=o365-worldwide#:~:text=Start of highlight,End of Highlight

    Example:
    https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-whatis?view=o365-worldwide#:~:text=Azure Active Directory (,Microsoft 365.

    Result:

    clip_image006

    I needed to add the ”(” there since the text Azure Active Directory existed many times on the page. Without it, it looked like this:

    clip_image008

    In other words, you will have to test your link to make sure it looks as expected.

    Note that any spaces need to be converted to %20 for the entire link to be clickable:

    https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-whatis?view=o365-worldwide#:~:text=Azure Active Directory (,Microsoft 365.  <- Missed

    https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-whatis?view=o365-worldwide#:~:text=Azure%20Active%20Directory%20(,Microsoft%20365.

    You don’t have to add them all manually. If you copy/paste the entire link into a web browser, it will convert %20 (and any other special characters according to standard HTML URL Encoding) wherever needed.

    I hope this was a helpful tip!

    Posted in Okategoriserade | Tagged , | Leave a comment

    The consequence of not renewing ATA certificate in time

    A customer who uses Microsoft Advanced Threat Analytics (ATA) recently had severe issues with their ATA implementation. At first, the portal started to behave strangely, not showing all information in alerts and some configuration settings were missing. After a restart of the ATA servers, the services failed to start at all.

    The Microsoft.Tri.Center-Errors.log file contained many errors like this:

    2020-01-09 12:34:27.9920 1140 98 Error [CertificateExtension] Microsoft.Tri.Infrastructure.Utils.ExtendedException: There are no matching certificates [StoreLocation=LocalMachine StoreName=My thumbprint=89E1C9790B175D2E6B716CFDDABA3D9F444829F6]

    It turned out that their internal PKI had automatically renewed the certificate that ATA was configured to use. In general, this is what you want from a PKI (auto-renewed certificates), but unfortunately, ATA does not support renewing an existing certificate.

    The reason is that some ATA data is encrypted using the configured certificate, and during certificate renewal, the old certificate is removed, so you lose the ability to decrypt that data.

    So you need to create a new certificate before the old one expires and manually configure ATA to use the new certificate.

    This requirement is clearly stated in the Microsoft ATA-documentation:

    clip_image001

    Source: https://docs.microsoft.com/en-us/advanced-threat-analytics/modifying-ata-center-configuration#the-ata-center-certificate

    You will even get alerts in ATA Health Center about upcoming certificate expiration:

    clip_image003

    Source: https://docs.microsoft.com/en-us/advanced-threat-analytics/monitoring-alerts

    Replacing the certificate is not really that difficult or time-consuming. But if you do not replace the certificate before it expires you will get this alert:

    clip_image005

    Source: https://docs.microsoft.com/en-us/advanced-threat-analytics/monitoring-alerts

    You can see that that when this happens, the only resolution is to redeploy your ATA, and you will lose all your configuration, alerts, and behavior analysis history.

    Other services that use certificates can usually be recovered really easy from issues caused by expired certificates by simply getting a new certificate and pointing the service to the new certificate, but since the “certificate pointing” in ATA is done in the ATA Configuration, which is encrypted by the previous certificate, there is a catch 22 situation here.

    Some people have tried to manually add the thumbprint of a new certificate in the SystemProfile_date.json configuration file, and they have gotten the ATA up and running again. However, they could not edit all ATA settings after that, so they eventually ended up redeploying from scratch.

    Restoring from backup after redeployment will not work either since the backup still points to the old removed certificate. You can still use that backup configuration file as a manual reference on how to configure ATA again , since it is in cleartext.

    So go ahead and make sure that your ATA implementation does not use a certificate that will be automatically renewed, and/or put a reminder in your calendar to renew it before it expires. And monitor those health alerts!

    Update 2020-09-14

    In the newly released ATA version 1.9.3, Microsoft has updated the functionality around certificate renewal notifications:

    Increased advance notice for Center certificate expiration to three months prior to expiration (previously three weeks). Additionally, the notice now provides a clearer description of the severity of failing to renew the certificate.

    You can get the new version by using Windows Update or downloading it here::
    https://www.microsoft.com/download/details.aspx?id=56725

    Posted in ATA, Certificates, PKI, SSL | Tagged , | 1 Comment

    Teams on iOS now supports Sensitivity Labels

    In the newly released version 1.0.91 of Teams for iOS it was announced that it now supports Sensitivity Labels for your Teams:

    (Sorry that the screenshots are in Swedish, you’ll have to trust me or translate it 😀)

    I first tried to create a Team before I upgraded the Teams app, and I did not see any option to select Sensitivity Labels:

    I then updated Teams to the new version, and sure enough, I could now select the Sensitivity of my new Team:

    Always great to see Microsoft Information Protection getting adopted in more and more places.

    Posted in Okategoriserade | Leave a comment

    Copy your AIP Polices to the Security & Compliance Center

    You have for a while been able to copy your AIP Labels to the Security & Compliance Center from the Azure Information Protection Portal.

    But you can now also copy your AIP Policies (in Preview)!

    clip_image002

    You get a warning that any existing policies with the same name will be overwritten.
    Click Yes to proceed:

    clip_image004

    It just takes a moment until you see the completion notification:

    clip_image006

    You will see a summary of the polices that was copied:

    clip_image008
    (I only had one policy in this tenant)

    And sure enough, the new policy appeared right away in the Security & Compliance Center:

    clip_image010

    The policy settings I had configured was also copied:

    clip_image002[4]

    Remember that this feature is still in Preview, so use with caution in production. And as always: test first!

    /Tom

    Posted in AIP, encryption, information protection | Leave a comment

    Using PowerShell to get wildcard certificate from Let’s Encrypt

    This is a guide that shows you how to get a publicly trusted wildcard certificate at no cost from Let’s Encrypt using PowerShell.

    Requirements:

    • Windows PowerShell 5.1
    • .NET Framework 4.7.2 (link to check)
    • Possibility to add CNAME in DNS

    Step by step

    Start PowerShell as admin (see information below for non-admin steps)

    Verify that PowerShell’s ExecutionPolicy allows running scripts (i.e. RemoteSigned or less)

    clip_image002

    Otherwise: Set-ExecutionPolicy RemoteSigned

    Run:

    Install-Module -Name Posh-ACME

    Accept warnings about untrusted repositories (that is, if you accept PSGallery, a common module repository):

    clip_image003

    Run:

    New-PACertificate *.tomdemo.se -AcceptTOS -Contact <your-email> -DnsPlugin AcmeDns -PluginArgs @{ACMEServer='auth.acme-dns.io'} -Install

    clip_image004

    Explanation of the options used:

    *.tomdemo.se The name you want in the certificate. You can add additional comma-separated names
    AcceptTOS Indicates that you accept the Let’s Encrypt Terms of Service (see https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf)
    Contact Email for expiration notification (optional)
    DnsPlugin Which DNS plugin should be used for automatic domain ownership validation. Since my DNS provider Loopia isn’t natively supported by Posh-ACME, I used the ACMEDns option, which requires you to manually add a CNAME record in your DNS provider once, and that can be reused when updating the certificate. Here is a list of DNS providers supported by Posh-ACME: https://github.com/rmbolger/Posh-ACME/wiki/List-of-Supported-DNS-Providers
    PluginArgs Options that depends on chosen DNSPlugin
    Install This option will install the certificate in the computer’s Certificate Store (requires admin permission, see Getting certificate without admin permission below)

    Do not close the PowerShell window!

    Add the CNAME record shown in the output of the command you just ran in the DNS registrar for the domain.
    Here is an example from Swedish DNS registrar Loopia, but your DNS registrar interface may look different:

    clip_image006

    Go back to the PowerShell window and press enter to continue.
    The script will wait 2 minutes for DNS to propagate:

    clip_image007

    After that, you should get the certificate:

    clip_image008

    To see more information about the certificate, you can use the following command:

    Get-PACertificate | Format-List

    clip_image009

    Here you can see basic information about the certificate and that all the relevant files are stored in %LOCALAPPDATA%\Posh-ACME folder, and that it includes a PFX-file if you want to install the certificate on another machine. The default PFX-password is “poshacme”. You can specify your own with the option -PfxPass when running the New-PACertificate command.

    Go to the Local Computer certificate store (run certlm.msc) and verify that the certificate has been installed correctly:

    clip_image011

    clip_image012 clip_image013

    Depending on what service you are using the certificate for, you may need to make extra configuration steps in the service to start using the certificate.

    You can manually renew the certificate by running the following command:
    Submit-Renewal
    clip_image014

    As you can see, it will not renew certificates that are not about to expire yet (I believe it uses 30 days or less validity time). You can override this by running:

    Submit-Renewal -Force

    To automate the renewal, you can create a scheduled task that runs this command daily:

    Create a file called C:\Cert\AutoRenewal.ps1, containing the command “Submit-Renewal” (not the -Fore option, since you don’t want to renew at every check).

    Run the following commands, but first change <password> to your own password
    Note: The scheduled task must run in the context of the user requesting the certificate since validation information is stored in that user’s profile.

    $Trigger = New-ScheduledTaskTrigger -At 10:00am -Daily
    $Action= New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "C:\Cert\AutoRenewal.ps1"
    Register-ScheduledTask -TaskName "Certificate AutoRenewal" -Trigger $Trigger -User "$env:USERDOMAIN\$env:USERNAME" -Password '<password>' -Action $Action -RunLevel Highest –Force

    Test certificates

    For testing, you can switch the Let’s Encrypt server you send your requests to. The test server does not create a publicly trusted certificate but has no rate limiting.

    Read more about rate limiting here: https://letsencrypt.org/docs/rate-limits/

    To use test server:

    Set-PAServer LE_STAGE

    To use production server:

    Set-PAServer LE_PROD

    It will keep using the specified server until you change it again.

    Getting certificate without admin permission

    Most steps above work without admin permission, with the exception of installing the certificate in the Computer certificate store.

    You might need to restrict the scoop of these commands as well:

    Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
    
    Install-Module -Name Posh-ACME -Scope CurrentUser

    Then exclude the -Install option in the New-PACertificate command example above.

    You will still get a valid publicly trusted certificate, and you can move the created pfx-file to a computer where you want to install it (where you are admin).

    Custom Acme-DNS instance

    In my example above, I use the public ACME-Dns service. The advantage of that is that your DNS provider does not have to support API access for the Domain Verification part. Instead, you manually create a CNAME record in your DNS provider once that redirects the DNS validation to ACME-Dns.

    To increase security, you should use your own instance of Acme-DNS, see here: https://github.com/joohoi/acme-dns

    Posted in Okategoriserade | 1 Comment

    Hyper-V Guests with Windows 10 (1903) hangs when using Enhanced Session/RDP?

    Are you also having the issue where accessing your Hyper-V VM Guests works great when connecting via Virtual Machine Connection, but the VM hangs when you try to access it using Enhanced Session or RDP?

    The VM becomes irresponsible and the only solution is to use Turn off (shutdown doesn’t work). The machine starts to continuously consume about 12% or 24% CPU (seems to depend on the number of CPU cores).

    I run client Hyper-V on a Windows 10 (1903) machine, and the guest is also Windows 10. Enhanced Session used to work great, until Windows 10 (1903).

    After some troubleshooting and researching I found out that a new RDP display driver called WDDM was introduced in 1903. By disabling WDDM and reverting to the old XDDM driver the problem went away for me.

    Here’s how to do it:

    Start the Local Group Policy Editor:

    clip_image001

    Navigate here:
    Local Computer Policy
    /Computer Configuration
      /Administrative Templates
       /Windows Components
        /Remote Desktop Services
         /Remote Desktop Session Host
          /Remote Session Environment

    Configure the setting Use WDDM graphics display driver for Remote Desktop Connections to Disabled:

    clip_image003

    In an AD environment you can of course use the regular Group Policy Management.

    You can also create and import a reg-file with the following text:

    Windows Registry Editor Version 5.00
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services]
    "fEnableWddmDriver"=dword:00000000

    Reboot the Guest VM.

    Yay, now I can access that guest VM using Enhanced Session again.

    Posted in Hyper-V, RDP, Windows 10 | Tagged , , | 2 Comments

    Enable FIDO2 credential manager in Windows 10

    Once you have enrolled your FIDO2 security key in Azure AD (which can be done here), you can easily sign-in to web pages that use Azure AD as Identity Provider without needing to enter your password.

    If your security key doesn’t have a fingerprint reader, you need to enter the key’s PIN but remember that this is only to unlock the secret on the key, and it is never sent or stored anywhere outside of the key:

    If you also want to sign-in on a Windows 10 machine with a FIDO2 device (currently supported on Azure AD joined and version 1809 or higher), you need to enable the FIDO security key credential provider on that machine first:

    This can be enabled in one of three ways:

    1. Using Intune, as explained here.

    2. If Intune doesn’t manage the client, you can manually create a provisioning package using Windows Configuration Designer  (an application that is available in the Microsoft Store. The steps are explained here.
    Note that you have to choose All Windows desktop editions, if you choose All Windows editions, the setting isn’t available.

    3. You can enable the FIDO credential provider, you by adding the following Registry Setting:

    Windows Registry Editor Version 5.00
    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Policies\PassportForWork\SecurityKey]
    "UseSecurityKeyForSignin"=dword:00000001

    Copy the text above to a new text file, call it something.reg, double-click it and accept the warning.

    Note! I haven’t seen the last method mentioned anywhere official, so it might not be supported. Use it with caution and test before using it in production.

    Posted in fido2, Password, passwordless | Tagged , , | Leave a comment

    Always get the English version at docs.microsoft.com

    When you visit https://docs.microsoft.com, it shows pages in the local language you have configured in your browser’s settings. Sometimes the pages are properly translated by humans, sometimes it is machine translated.

    I always want the English versions of the Docs site pages, but I do not want to have English as the default language in my browser since I want Swedish version on other websites.

    I discovered the Firefox plugin called Redirector. It does one very simple task. It looks for pattern matches in the URL and modifies them according to my rules.

    So I installed it and created the following Redirect rule:

    image

    The * is a wildcard, so anything will match. $1 is the value that the first wildcard represented. Note that my rule only matches Swedish (sv-se), you may need to modify your rules to match your language (or all languages).

    Now, whenever I visit a page that starts with https://docs.microsoft.com/sv-se/* it is immediately changed to https://docs.microsoft.com/en-us/*:

    GIF3

    There are similar extensions for Chrome, but I have not tested them yet:

    ModHeader

    Switcheroo Redirector

    Posted in Okategoriserade | Leave a comment