---
title: Using FIDO2 security keys with PowerShell
description: 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:As you can see, t...
---

[Onevinn blog ](https://www.onevinn.com/blog)

# [Using FIDO2 security keys with PowerShell](https://www.onevinn.com/blog/using-fido2-security-keys-with-powershell)

 Written by [Tom Aafloen](https://www.onevinn.com/blog/author/tom-aafloen) | 21 Oct 2020

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:

<http://mssec.files.wordpress.com/2020/10/ienofido.png>

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:

1. Wait until **PowerShell** moves from **ADAL** to **MSAL**, and sign in prompts are rendered by a modern browser that supports *WebAuthN*.
2. Wait until **each PowerShell Module you need** starts supporting its own implementation of modern authentication to Azure AD.
3. Use **Cloud Shell**, where you can run PowerShell directly in your browser:  
   [http://shell.azure.com/powershell](http://shell.azure.com/powershell)  
   This option works with FIDO2, but a web-based shell has its limitations.
4. 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:

<http://mssec.files.wordpress.com/2020/10/initiate.png>

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

Enter the code in the prompt:

<http://mssec.files.wordpress.com/2020/10/deviceauth.png>

As you can see, we are now signing in **on a remote device or service**. You can sign in using your regular account name and password, but to sign in using a FIDO2 key, click on **Sign-in options**:

<http://mssec.files.wordpress.com/2020/10/sign-in.png>

Now we can use our FIDO2 key to authenticate:

<http://mssec.files.wordpress.com/2020/10/fido2.png>

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

<http://mssec.files.wordpress.com/2020/10/close.png>

#### 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/](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](https://graph.microsoft.com/%26#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  
```

#### Thanks

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

[View full post](https://www.onevinn.com/blog/using-fido2-security-keys-with-powershell)

```json
{
  "@context" : "http://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Tom Aafloen"
  },
  "dateModified" : "2020-10-21T11:52:17.280Z",
  "datePublished" : "2020-10-21T11:52:17Z",
  "headline" : "Using FIDO2 security keys with PowerShell",
  "image" : {
    "@type" : "ImageObject",
    "height" : 60,
    "url" : "/hs/hsstatic/content_shared_assets/static-1.4092/img/default-amp-logo.png",
    "width" : 60
  },
  "mainEntityOfPage" : "https://www.onevinn.com/blog/using-fido2-security-keys-with-powershell",
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "height" : 60,
      "url" : "/hs/hsstatic/content_shared_assets/static-1.4092/img/default-amp-logo.png",
      "width" : 60
    },
    "name" : "Onevinn blog"
  }
}
```