mirror of
https://github.com/MichaelGrafnetter/webauthn-interop
synced 2026-08-09 12:12:33 +00:00
Add support for Okta (#18)
This commit is contained in:
+1
-1
@@ -21,7 +21,7 @@ The `DSInternals.Win32.WebAuthn.Adapter` library additionally uses classes defin
|
||||
|
||||
## PowerShell Module
|
||||
|
||||
The [DSInternals.Passkeys](https://www.powershellgallery.com/packages/DSInternals.Passkeys) PowerShell module uses the `DSInternals.Win32.WebAuthn` library together with the [Microsoft Graph API](https://learn.microsoft.com/en-us/graph/api/resources/fido2authenticationmethod?view=graph-rest-beta) to provide Microsoft Entra ID administrators the capability of registering Passkeys on behalf of other users:
|
||||
The [DSInternals.Passkeys](https://www.powershellgallery.com/packages/DSInternals.Passkeys) PowerShell module uses the `DSInternals.Win32.WebAuthn` library together with the [Microsoft Graph API](https://learn.microsoft.com/en-us/graph/api/resources/fido2authenticationmethod?view=graph-rest-beta) and the [Okta API](https://developer.okta.com/docs/api/openapi/okta-management/management/tag/UserFactor/#tag/UserFactor/operation/enrollFactor) to provide Microsoft Entra ID and Okta administrators respectively the capability of registering passkeys on behalf of other users:
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -52,6 +52,20 @@ jobs:
|
||||
shell: powershell
|
||||
run: .\Build-PowerShellModule.ps1 -Configuration Release
|
||||
|
||||
- name: Test PowerShell Module
|
||||
env:
|
||||
EntraIdTenantId: ${{ secrets.ENTRAIDTENANTID }}
|
||||
EntraIdClientId: ${{ secrets.ENTRAIDCLIENTID }}
|
||||
EntraIdClientSecret: ${{ secrets.ENTRAIDCLIENTSECRET }}
|
||||
EntraIdUserId: ${{ secrets.ENTRAIDUSERID }}
|
||||
OktaTenantId: ${{ secrets.OKTATENANTID }}
|
||||
OktaClientId: ${{ secrets.OKTACLIENTID }}
|
||||
OktaJsonWebKey: ${{ secrets.OKTAJSONWEBKEY }}
|
||||
OktaUserId: ${{ secrets.OKTAUSERID }}
|
||||
shell: pwsh
|
||||
run: |
|
||||
Invoke-Pester .\Build\bin\PSModule\Release\DSInternals.Passkeys\DSInternals.Passkeys.Tests.ps1 -Passthru
|
||||
|
||||
- name: Upload PowerShell Module as Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
|
||||
@@ -354,3 +354,4 @@ MigrationBackup/
|
||||
# Private Keys and API Keys
|
||||
*.Private.snk
|
||||
*.key
|
||||
.vscode/launch.json
|
||||
|
||||
Vendored
+8
-1
@@ -1,6 +1,13 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "PowerShell Launch Current File",
|
||||
"type": "PowerShell",
|
||||
"request": "launch",
|
||||
"script": "${file}",
|
||||
"cwd": "${cwd}"
|
||||
},
|
||||
{
|
||||
"name": "Debug FIDO2 UI",
|
||||
"type": "clr",
|
||||
@@ -13,4 +20,4 @@
|
||||
"preLaunchTask": "build"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
---
|
||||
external help file: DSInternals.Passkeys-help.xml
|
||||
Module Name: DSInternals.Passkeys
|
||||
online version: https://github.com/MichaelGrafnetter/webauthn-interop/tree/main/Documentation/PowerShell/Connect-Okta.md
|
||||
schema: 2.0.0
|
||||
---
|
||||
|
||||
# Connect-Okta
|
||||
|
||||
## SYNOPSIS
|
||||
Retrieves an access token to interact with Okta APIs.
|
||||
|
||||
## SYNTAX
|
||||
|
||||
### If you are using the authorization code flow
|
||||
```
|
||||
Connect-Okta -Tenant <String> -ClientId <String> [-Scopes <String[]>] [-ProgressAction <ActionPreference>]
|
||||
[<CommonParameters>]
|
||||
```
|
||||
|
||||
### If you are using the client credentials flow
|
||||
```
|
||||
Connect-Okta -Tenant <String> -ClientId <String> [-Scopes <String[]>]
|
||||
-JsonWebKey <ValidateNotNullOrEmptyAttribute> [-ProgressAction <ActionPreference>] [<CommonParameters>]
|
||||
```
|
||||
|
||||
## DESCRIPTION
|
||||
In order to use this module with Okta, you will need to create an application within your Okta tenant. You may use the authorization code flow with PKCE (highly recommended for interactive login), or the client credentials flow (for headless use). If you are unsure which to choose, select the authorization code flow, as it is the most secure option.
|
||||
|
||||
### Setup to use the authorization code flow with PKCE
|
||||
To use the authorization code flow, you will need to create a Single Page App (SPA). In the application area in the Okta admin console, click `Create App Integration`, then select `OIDC - OpenID Connect` for the sign-in method, then `Single-Page Application` for the application type, and click next. Note: This process is nearly identical to [User-based API access setup](https://developer.okta.com/docs/reference/rest/#user-based-api-access-setup) in the Okta developer documentation.
|
||||
<br><br>
|
||||
<img width="559" alt="Create SPA" src="https://github.com/user-attachments/assets/9a85d754-8e3c-4756-80e5-1dca4635f8f4">
|
||||
<br><br>
|
||||
On the next page, give the app integration a meaningful name. Under assignments, select either `Limit access to selected groups` if you already have a group you want to assign this application to, or select `Skip group assignment for now`. You can change this later, but you are required to select an option. Everything else can be left at the defaults. Click save.
|
||||
<br><br>
|
||||
<img width="559" alt="SPA options" src="https://github.com/user-attachments/assets/2c83f1b7-8f50-49c3-bfe2-fb77aec50aa6">
|
||||
<br><br>
|
||||
WARNING: Do NOT, under ANY circumstances, select `Allow everyone in your organization to access`. Use one of the other options. This is your warning. Seriously. Do not do this.
|
||||
<br><br>
|
||||
<img width="559" alt="Do not select allow everyone" src="https://github.com/user-attachments/assets/bb6cebbd-a9a6-4e12-b198-1040163bf962">
|
||||
<br><br>
|
||||
On the next page, ensure that Proof Key for Code Exchange (PKCE) is selected, and note the client ID, you will need this to connect.
|
||||
<br><br>
|
||||
<img width="517" alt="Take note of the Client ID and ensure require PKCE is selected" src="https://github.com/user-attachments/assets/35455c7e-07e8-4112-aefc-e55ba1f56e91">
|
||||
<br><br>
|
||||
On the Assignments tab, assing the application to the appropriate user(s). On the Okta API Scopes tab, scroll down to the okta.users.manage scope and click the `Grant` button to the right of the scope name. This is the minimal permission required to use this library, since the whole point of the library is to register a passkey on behalf of someone else. This scope allows the app to create new users and to manage all users' profile and credentials information. Be very, very careful assigning this app.
|
||||
|
||||
Okta API scopes should look approximately like this:
|
||||
<br><br>
|
||||
<img width="506" alt="Okta API scopes: okta.users.manage" src="https://github.com/user-attachments/assets/434bdeb4-fe12-4578-b1c6-dc5f313936f6">
|
||||
<br><br>
|
||||
Assignments tab should look something like this:
|
||||
<br><br>
|
||||
<img width="506" alt="Okta application assignments" src="https://github.com/user-attachments/assets/c977cb67-05b1-4ccc-98d1-875fcd86a3ca">
|
||||
<br><br>
|
||||
### Setup to use the client credentials flow
|
||||
If you intend to use the client credentials flow, you must set up an API service application as described below. Note: This process is nearly identical to the [Service-based API access setup](https://developer.okta.com/docs/reference/rest/#service-based-api-access-setup) in the Okta developer documentation.
|
||||
<img width="559" alt="" src="https://github.com/user-attachments/assets/2a62bb79-7c93-4af8-9527-c7073ae450d5">
|
||||
<br><br>
|
||||
On the next page, give the app integration a meaningful name. Click save.
|
||||
<br><br>
|
||||
<img width="559" alt="" src="https://github.com/user-attachments/assets/101c98ad-6077-4182-be5d-630c54cfa38b">
|
||||
<br><br>
|
||||
On the next page, note the client ID, you will need this to connect. Switch the client authentication configuration from the default client secret to public key/private key by clicking edit, then selecting the radio button.
|
||||
<br><br>
|
||||
<img width="572" alt="image" src="https://github.com/user-attachments/assets/96aa533d-bf16-4920-8690-be4ebf703d90">
|
||||
<br><br>
|
||||
The public keys configuration section will open. For a simple test configuration, leave the radio button for save keys to Okta selected. You will need to add at least one key here, by clicking the add key button.
|
||||
<br><br>
|
||||
<img width="508" alt="image" src="https://github.com/user-attachments/assets/e5539794-1e79-43e9-ac83-a47dc0bef4e6">
|
||||
<br><br>
|
||||
The add a public key dialog will appear. You have the option to paste in your own public key, or let Okta generate one based on RS256 for you by clicking generate new key.
|
||||
<br><br>
|
||||
<img width="508" alt="image" src="https://github.com/user-attachments/assets/e9c0a690-c40b-418d-b7bb-3f83dbf418be">
|
||||
<br><br>
|
||||
Leave the private key format at the default JSON, and click the copy to clipboard button. Save the contents in a safe place, as this key is a sensitive credential, then click save.
|
||||
<br><br>
|
||||
<img width="539" alt="image" src="https://github.com/user-attachments/assets/10ec207b-859d-483a-9c6b-2d821d2d4f60">
|
||||
<br><br>
|
||||
I typically compress the output to avoid issues later. In the compressed format the key is ready to use as a parameter value to the [-JsonWebKey parameter](https://github.com/MichaelGrafnetter/webauthn-interop/tree/main/Documentation/PowerShell/Connect-Okta.md#-jsonwebkey)
|
||||
<br><br>
|
||||
```powershell
|
||||
PS C:\> $jwk = @'
|
||||
{
|
||||
"kty": "RSA",
|
||||
"e": "AQAB",
|
||||
"kid": "EE3QB0WvhuOwR9DuR6717OERKbDrBemrDKOK4Xvbf8c",
|
||||
"d": "TmljZSB0cnkhICBCdXQgdGhpcyBpc24ndCBhIHJlYWwga2V5Lg",
|
||||
"p": "wqFCdWVuIGludGVudG8hIFBlcm8gZXN0YSBubyBlcyB1bmEgY2xhdmUgcmVhbC4",
|
||||
"q": "TmV0dGVyIFZlcnN1Y2ghIEFiZXIgZGFzIGlzdCBrZWluIGVjaHRlciBTY2hsw7xzc2VsLg",
|
||||
"dp": "QmVsbGUgdGVudGF0aXZlICEgTWFpcyBjZSBuJ2VzdCBwYXMgdW5lIHZyYWllIGNsw6ku",
|
||||
"dq": "5LiN6ZSZ55qE5bCd6K-V77yB5L2G6L-Z5LiN5piv55yf5q2j55qE6ZKl5YyZ44CC",
|
||||
"qi": "7KKL7J2AIOyLnOuPhOuEpOyalCEg7ZWY7KeA66eMIOydtOqxtCDsp4Tsp5wg7Je07Ieg6rCAIOyVhOuLiOyXkOyalC4",
|
||||
"n": "uT64MHF-qH5F-jLAoWxuwI8_YJ2cdkMIjvlyazJnB0xjvtddS14O8cfDHW2lxHWiOor-jarCK282WC1BukjnizCeUl7YoWDWnVNOcQd1hi__nC5cjhgnjVPNgBiRQhctj8e6HWgKfMHTxZ_vaMsqQZJ9QwYy1NzkxchqcI9pZN1zlA2LHdXsXzvJeRxzUg8EjGxaDKuLPHPUfZxf0Wr4Jv-lNVYzwg84XtzOoZ0v9Hb91ZISmVKKtMegXX2ahGRgMeI1pgX8oCG8TCgx7x-SmViJfi9iNfznJWyA_lZiUKu3qJMsFJdgfRp9egCZtUl6P_nnpqe-_-MNmy55WXhc0Q"
|
||||
}
|
||||
'@
|
||||
| ConvertFrom-Json | ConvertTo-Json -Compress
|
||||
```
|
||||
On the Okta API Scopes tab, scroll down to the okta.users.manage scope and click the `Grant` button to the right of the scope name. This is the minimal permission required to use this library, since the whole point of the library is to register a passkey on behalf of someone else. This scope allows the app to create new users and to manage all users' profile and credentials information. Okta API scopes should look approximately like this:
|
||||
<br><br>
|
||||
Okta API scopes: okta.users.manage" src="https://github.com/user-attachments/assets/434bdeb4-fe12-4578-b1c6-dc5f313936f6">
|
||||
<br><br>
|
||||
On the Admin roles tab, you will need to assign an admin role to this app. The `Help Desk Administrator` role seems to work well for this module.
|
||||
<br><br>
|
||||
<img width="506" alt="Admin assignment help desk administrator role" src="https://github.com/user-attachments/assets/8ffb2acb-67cb-4cb4-9aef-6747540a0fdd">
|
||||
<br>
|
||||
## EXAMPLES
|
||||
|
||||
### Example 1
|
||||
```powershell
|
||||
PS C:\> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7
|
||||
```
|
||||
|
||||
Connects to `example.okta.com` tenant using application with client id `0oakmj8hvxvtvCy3P5d7` with the authentication code flow with PKCE
|
||||
|
||||
### Example 2
|
||||
```powershell
|
||||
PS C:\> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7 -Scopes @('okta.users.manage','okta.something.else')
|
||||
```
|
||||
|
||||
Connects to `example.okta.com` tenant using application with client id `0oakmj8hvxvtvCy3P5d7` with the authentication code flow with PKCE, requesting scopes `'okta.users.manage'` and `'okta.something.else'`
|
||||
|
||||
### Example 3
|
||||
```powershell
|
||||
PS C:\> $jwk = '{"kty":"RSA","kid":"EE3QB0WvhuOwR9DuR6717OERKbDrBemrDKOK4Xvbf8c","d":"TmljZSB0cnkhICBCdXQgdGhpcyBpc...'
|
||||
PS C:\> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7 -Scopes @('okta.users.manage','okta.something.else') -JsonWebKey $jwk
|
||||
```
|
||||
|
||||
Connects to `example.okta.com` tenant using application with client id `0oakmj8hvxvtvCy3P5d7` with the client credentials flow using `$jwk` as the the client credential, requesting scopes `'okta.users.manage'` and `'okta.something.else'`
|
||||
|
||||
## PARAMETERS
|
||||
|
||||
### -Tenant
|
||||
The unique identifier of Okta tenant, like `'example.okta.com'`.
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: True
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: False
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -ClientId
|
||||
The client id of the Okta application used to obtain an access token.
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: True
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByValue)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
### -Scopes
|
||||
Scopes to request for the access token. Defaults to `'okta.users.manage'`.
|
||||
|
||||
```yaml
|
||||
Type: String[]
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: False
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -JsonWebKey
|
||||
The JSON Web Key used to authenticate to the Okta application, in order to obtain access token using the client credentials OAuth flow.
|
||||
|
||||
```yaml
|
||||
Parameter Sets: ClientCredentials
|
||||
Aliases: jwk
|
||||
|
||||
Required: True
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByValue)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### CommonParameters
|
||||
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
|
||||
|
||||
## INPUTS
|
||||
|
||||
## OUTPUTS
|
||||
|
||||
## NOTES
|
||||
|
||||
## RELATED LINKS
|
||||
https://developer.okta.com/docs/reference/rest/
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
external help file: DSInternals.Passkeys-help.xml
|
||||
Module Name: DSInternals.Passkeys
|
||||
online version:
|
||||
schema: 2.0.0
|
||||
---
|
||||
|
||||
# Disconnect-Okta
|
||||
|
||||
## SYNOPSIS
|
||||
Revokes Okta access token.
|
||||
|
||||
## SYNTAX
|
||||
|
||||
```
|
||||
Disconnect-Okta [<CommonParameters>]
|
||||
```
|
||||
|
||||
## DESCRIPTION
|
||||
Revokes the Okta access token cached from the call to `Connect-Okta`.
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
### EXAMPLE 1
|
||||
```
|
||||
Disconnect-Okta
|
||||
```
|
||||
|
||||
## PARAMETERS
|
||||
|
||||
### CommonParameters
|
||||
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
|
||||
|
||||
## INPUTS
|
||||
|
||||
## OUTPUTS
|
||||
|
||||
## NOTES
|
||||
|
||||
## RELATED LINKS
|
||||
@@ -8,56 +8,56 @@ schema: 2.0.0
|
||||
# Get-PasskeyRegistrationOptions
|
||||
|
||||
## SYNOPSIS
|
||||
Retrieves creation options required to generate and register a Microsoft Entra ID-compatible passkey.
|
||||
Retrieves creation options required to generate and register a Microsoft Entra ID or Okta compatible passkey.
|
||||
|
||||
## SYNTAX
|
||||
|
||||
```
|
||||
Get-PasskeyRegistrationOptions [-UserId] <String> [[-ChallengeTimeout] <TimeSpan>] [<CommonParameters>]
|
||||
Get-PasskeyRegistrationOptions [-UserId] <String> [[-ChallengeTimeout] <TimeSpan>]
|
||||
[-ProgressAction <ActionPreference>] [<CommonParameters>]
|
||||
```
|
||||
|
||||
## DESCRIPTION
|
||||
{{ Fill in the Description }}
|
||||
|
||||
Retrieves the [credential creation options](https://w3c.github.io/webauthn/#dictionary-makecredentialoptions) required to generate a Microsoft Entra ID or Okta-compatible passkey.
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
### EXAMPLE 1
|
||||
```powershell
|
||||
Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com'
|
||||
### EXAMPLE 1 (Entra ID)
|
||||
```
|
||||
PS \> Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com'
|
||||
```
|
||||
|
||||
### EXAMPLE 2
|
||||
```powershell
|
||||
Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' -ChallengeTimeout (New-TimeSpan -Minutes 10)
|
||||
### EXAMPLE 2 (Entra ID)
|
||||
```
|
||||
PS \> Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' -ChallengeTimeout (New-TimeSpan -Minutes 10)
|
||||
```
|
||||
|
||||
### EXAMPLE 3 (Okta)
|
||||
```
|
||||
PS \> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 00eDuihq64pgP1gVD0x7
|
||||
```
|
||||
|
||||
### EXAMPLE 4 (Okta)
|
||||
```
|
||||
PS \> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 00eDuihq64pgP1gVD0x7 -ChallengeTimeout (New-TimeSpan -Seconds 60)
|
||||
```
|
||||
|
||||
## PARAMETERS
|
||||
|
||||
### -ChallengeTimeout
|
||||
Overrides the timeout of the server-generated challenge returned in the request.
|
||||
The default value is 5 minutes, with the accepted range being between 5 minutes and 30 days.
|
||||
|
||||
```yaml
|
||||
Type: TimeSpan
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: 2
|
||||
Default value: (New-TimeSpan -Minutes 5)
|
||||
Accept pipeline input: False
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -UserId
|
||||
The unique identifier of user.
|
||||
The unique identifier of user.
|
||||
For Entra ID, this is the object id (GUID) or UPN.
|
||||
For Okta, this is the unique identifier of Okta user.
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
Aliases: User
|
||||
|
||||
Required: True
|
||||
Position: 1
|
||||
@@ -66,6 +66,23 @@ Accept pipeline input: False
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -ChallengeTimeout
|
||||
Overrides the timeout of the server-generated challenge returned in the request.
|
||||
For Entra ID, the default value is 5 minutes, with the accepted range being between 5 minutes and 30 days.
|
||||
For Okta, the default value is 300 seconds, with the accepted range being between 1 second and 1 day.
|
||||
|
||||
```yaml
|
||||
Type: TimeSpan
|
||||
Parameter Sets: (All)
|
||||
Aliases: Timeout
|
||||
|
||||
Required: False
|
||||
Position: 2
|
||||
Default value: (New-TimeSpan -Minutes 5)
|
||||
Accept pipeline input: False
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### CommonParameters
|
||||
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
|
||||
|
||||
@@ -73,9 +90,13 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable
|
||||
|
||||
## OUTPUTS
|
||||
|
||||
### DSInternals.Win32.WebAuthn.MicrosoftGraphWebauthnCredentialCreationOptions
|
||||
### DSInternals.Win32.WebAuthn.WebauthnCredentialCreationOption
|
||||
|
||||
## NOTES
|
||||
Self-service operations aren't supported.
|
||||
More info at https://learn.microsoft.com/en-us/graph/api/fido2authenticationmethod-creationoptions
|
||||
Self-service operations aren't supported with Entra ID.
|
||||
|
||||
## RELATED LINKS
|
||||
|
||||
[More info about Entra ID](https://learn.microsoft.com/en-us/graph/api/fido2authenticationmethod-creationoptions)
|
||||
<br>
|
||||
[More info about Okta](https://developer.okta.com/docs/api/openapi/okta-management/management/tag/UserFactor/#tag/UserFactor/operation/enrollFactor)
|
||||
|
||||
@@ -8,41 +8,49 @@ schema: 2.0.0
|
||||
# New-Passkey
|
||||
|
||||
## SYNOPSIS
|
||||
|
||||
Creates a new Microsoft Entra ID-compatible passkey.
|
||||
Creates a new Microsoft Entra ID or Okta-compatible passkey.
|
||||
|
||||
## SYNTAX
|
||||
|
||||
```
|
||||
New-Passkey [-Options] <MicrosoftGraphWebauthnCredentialCreationOptions> [-DisplayName] <String>
|
||||
[<CommonParameters>]
|
||||
New-Passkey [-Options] <WebauthnCredentialCreationOptions> [[-DisplayName] <String>]
|
||||
[-ProgressAction <ActionPreference>] [<CommonParameters>]
|
||||
```
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
{{ Fill in the Description }}
|
||||
Takes the `MicrosoftGraphWebauthnCredentialCreationOptions` or `OktaWebauthnCredentialCreationOptions` object from `Get-PasskeyRegistrationOptions` and uses them to create a credential using the system dialogs.
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
### EXAMPLE 1
|
||||
### EXAMPLE 1 (Entra ID)
|
||||
```
|
||||
PS \> Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' | New-Passkey -DisplayName 'YubiKey 5 Nano' | Register-Passkey -UserId 'AdeleV@contoso.com'
|
||||
```
|
||||
|
||||
```powershell
|
||||
Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' | New-Passkey -DisplayName 'YubiKey 5 Nano' | Register-Passkey -UserId 'AdeleV@contoso.com'
|
||||
Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
### EXAMPLE 2 (Okta)
|
||||
```
|
||||
PS C:\> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7
|
||||
PS \> New-Passkey -Options $options
|
||||
```
|
||||
|
||||
### EXAMPLE 3 (Okta)
|
||||
```
|
||||
PS C:\> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 00eDuihq64pgP1gVD0x7 | New-Passkey
|
||||
```
|
||||
|
||||
## PARAMETERS
|
||||
|
||||
### -DisplayName
|
||||
|
||||
Custom name given to the registered passkey.
|
||||
Custom name given to the Entra ID registered passkey.
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: True
|
||||
Required: False
|
||||
Position: 2
|
||||
Default value: None
|
||||
Accept pipeline input: False
|
||||
@@ -50,11 +58,10 @@ Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -Options
|
||||
|
||||
Options required to generate a Microsoft Entra ID-compatible passkey.
|
||||
Options required to generate a Microsoft Entra ID or Okta compatible passkey.
|
||||
|
||||
```yaml
|
||||
Type: MicrosoftGraphWebauthnCredentialCreationOptions
|
||||
Type: WebauthnCredentialCreationOptions
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
@@ -69,10 +76,13 @@ Accept wildcard characters: False
|
||||
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
|
||||
|
||||
## INPUTS
|
||||
### DSInternals.Win32.WebAuthn.WebauthnCredentialCreationOptions
|
||||
|
||||
## OUTPUTS
|
||||
|
||||
### DSInternals.Win32.WebAuthn.MicrosoftGraphWebauthnAttestationResponse
|
||||
### DSInternals.Win32.WebAuthn.WebauthnAttestationResponse
|
||||
## NOTES
|
||||
|
||||
## RELATED LINKS
|
||||
|
||||
[Microsoft WebAuthn portal](https://learn.microsoft.com/en-us/windows/win32/webauthn/-webauthn-portal)
|
||||
|
||||
@@ -9,13 +9,13 @@ Locale: en-US
|
||||
|
||||
## Description
|
||||
|
||||
This PowerShell module allows administrative registration of passkeys (i.e. FIDO2 security keys and Microsoft Authenticator mobile app) in Microsoft Entra ID (formerly Azure Active Directory).
|
||||
This PowerShell module allows administrative registration of passkeys (i.e. FIDO2 security keys and Microsoft Authenticator mobile app) in Microsoft Entra ID (formerly Azure Active Directory) as well as Okta.
|
||||
|
||||
## DSInternals.Passkeys Cmdlets
|
||||
|
||||
### [Register-Passkey](Register-Passkey.md)
|
||||
|
||||
Registers a new passkey in Microsoft Entra ID.
|
||||
Registers a new passkey in Microsoft Entra ID or Okta.
|
||||
|
||||
```powershell
|
||||
Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
@@ -23,10 +23,16 @@ Register-Passkey -UserId 'AdeleV@contoso.com' -DisplayName 'YubiKey 5 Nano'
|
||||
Disconnect-MgGraph
|
||||
```
|
||||
|
||||
```powershell
|
||||
Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7
|
||||
Register-Passkey -UserId 00ub61wm1aqmawzRC5d7'
|
||||
Disconnect-Okta
|
||||
```
|
||||
|
||||
### [Get-PasskeyRegistrationOptions](Get-PasskeyRegistrationOptions.md)
|
||||
|
||||
Retrieves creation options required to generate and register a Microsoft Entra ID-compatible passkey.
|
||||
Retrieves creation options required to generate and register a Microsoft Entra ID or Okta-compatible passkey.
|
||||
|
||||
### [New-Passkey](New-Passkey.md)
|
||||
|
||||
Creates a new Microsoft Entra ID-compatible passkey.
|
||||
Creates a new Microsoft Entra ID or Okta-compatible passkey.
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
---
|
||||
external help file: DSInternals.Passkeys-help.xml
|
||||
Module Name: DSInternals.Passkeys
|
||||
online version: https://github.com/MichaelGrafnetter/webauthn-interop/tree/main/Documentation/PowerShell/Register-Passkey.md
|
||||
online version: https://github.com/MichaelGrafnetter/webauthn-interop/tree/main/Documentation/PowerShell/New-Passkey.md
|
||||
schema: 2.0.0
|
||||
---
|
||||
|
||||
# Register-Passkey
|
||||
|
||||
## SYNOPSIS
|
||||
|
||||
Registers a new passkey in Microsoft Entra ID.
|
||||
Registers a newly created passkey with Microsoft Entra ID or Okta.
|
||||
|
||||
## SYNTAX
|
||||
|
||||
@@ -20,95 +19,104 @@ Register-Passkey -UserId <String> -DisplayName <String> [-ChallengeTimeout <Time
|
||||
|
||||
### Existing
|
||||
```
|
||||
Register-Passkey -UserId <String> -Passkey <MicrosoftGraphWebauthnAttestationResponse> [<CommonParameters>]
|
||||
Register-Passkey -UserId <String> -Passkey <WebauthnAttestationResponse> [<CommonParameters>]
|
||||
```
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
{{ Fill in the Description }}
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
### EXAMPLE 1
|
||||
|
||||
```powershell
|
||||
Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
Register-Passkey -UserId 'AdeleV@contoso.com' -DisplayName 'YubiKey 5 Nano'
|
||||
### EXAMPLE 1 (Entra ID)
|
||||
```
|
||||
PS \> Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
PS \> Register-Passkey -UserId 'AdeleV@contoso.com' -DisplayName 'YubiKey 5 Nano'
|
||||
```
|
||||
|
||||
### EXAMPLE 2
|
||||
|
||||
```powershell
|
||||
Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
Register-Passkey -UserId 'AdeleV@contoso.com' -DisplayName 'YubiKey 5 Nano' -ChallengeTimeout (New-TimeSpan -Minutes 10)
|
||||
### EXAMPLE 2 (Entra ID)
|
||||
```
|
||||
PS \> Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
PS \> Register-Passkey -UserId 'AdeleV@contoso.com' -DisplayName 'YubiKey 5 Nano' -ChallengeTimeout (New-TimeSpan -Minutes 10)
|
||||
```
|
||||
|
||||
### EXAMPLE 3
|
||||
### EXAMPLE 3 (Entra ID)
|
||||
```
|
||||
PS \> Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' | New-Passkey -DisplayName 'YubiKey 5 Nano' | Register-Passkey -UserId 'AdeleV@contoso.com'
|
||||
```
|
||||
|
||||
```powershell
|
||||
Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' | New-Passkey -DisplayName 'YubiKey 5 Nano' | Register-Passkey -UserId 'AdeleV@contoso.com'
|
||||
### EXAMPLE 4 (Okta)
|
||||
```
|
||||
PS \> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7
|
||||
PS \> Register-Passkey -UserId 00eDuihq64pgP1gVD0x7
|
||||
```
|
||||
|
||||
### EXAMPLE 5 (Okta)
|
||||
```
|
||||
PS \> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 00eDuihq64pgP1gVD0x7 | New-Passkey | Register-Passkey
|
||||
```
|
||||
|
||||
## PARAMETERS
|
||||
|
||||
### -ChallengeTimeout
|
||||
Overrides the timeout of the server-generated challenge returned in the request.
|
||||
The default value is 5 minutes, with the accepted range being between 5 minutes and 30 days.
|
||||
|
||||
```yaml
|
||||
Type: TimeSpan
|
||||
Parameter Sets: New
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: (New-TimeSpan -Minutes 5)
|
||||
Accept pipeline input: False
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -DisplayName
|
||||
Custom name given to the registered passkey.
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: New
|
||||
Aliases:
|
||||
|
||||
Required: True
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: False
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -Passkey
|
||||
The passkey to be registered.
|
||||
|
||||
```yaml
|
||||
Type: MicrosoftGraphWebauthnAttestationResponse
|
||||
Parameter Sets: Existing
|
||||
Aliases:
|
||||
|
||||
Required: True
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByValue)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -UserId
|
||||
The unique identifier of user.
|
||||
The unique identifier of user.
|
||||
For Entra ID, this is the object id (GUID) or UPN.
|
||||
For Okta, this is the unique identifier of Okta user.
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (All)
|
||||
Aliases: User
|
||||
|
||||
Required: True
|
||||
Position: 1
|
||||
Default value: None
|
||||
Accept pipeline input: False
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
### -Passkey
|
||||
The passkey to be registered.
|
||||
|
||||
```yaml
|
||||
Type: DSInternals.Win32.WebAuthn.WebauthnAttestationResponse
|
||||
Parameter Sets: (Existing)
|
||||
Aliases:
|
||||
|
||||
Required: True
|
||||
Position: Named
|
||||
Position: 2
|
||||
Default value: None
|
||||
Accept pipeline input: True
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -DisplayName
|
||||
Custom name given to the Entra ID registered passkey.
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (EntraIDNew)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: 2
|
||||
Default value: None
|
||||
Accept pipeline input: False
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -ChallengeTimeout
|
||||
Overrides the timeout of the server-generated challenge returned in the request.
|
||||
For Entra ID, the default value is 5 minutes, with the accepted range being between 5 minutes and 30 days.
|
||||
For Okta, the default value is 300 seconds, with the accepted range being between 1 second and 1 day.
|
||||
|
||||
```yaml
|
||||
Type: TimeSpan
|
||||
Parameter Sets: (EntraIDNew, OktaNew)
|
||||
Aliases: Timeout
|
||||
|
||||
Required: False
|
||||
Position: 3
|
||||
Default value: (New-TimeSpan -Minutes 5)
|
||||
Accept pipeline input: False
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
@@ -117,11 +125,17 @@ Accept wildcard characters: False
|
||||
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
|
||||
|
||||
## INPUTS
|
||||
### DSInternals.Win32.WebAuthn.WebauthnAttestationResponse
|
||||
|
||||
## OUTPUTS
|
||||
|
||||
### Microsoft.Graph.PowerShell.Models.MicrosoftGraphFido2AuthenticationMethod
|
||||
### DSInternals.Win32.WebAuthn.Okta.OktaFido2AuthenticationMethod
|
||||
|
||||
## NOTES
|
||||
More info at https://learn.microsoft.com/en-us/graph/api/authentication-post-fido2methods
|
||||
|
||||
## RELATED LINKS
|
||||
|
||||
[More info for Entra ID](https://learn.microsoft.com/en-us/graph/api/authentication-post-fido2methods)
|
||||
<br>
|
||||
[More info for Okta](https://developer.okta.com/docs/api/openapi/okta-management/management/tag/UserFactor/#tag/UserFactor/operation/activateFactor)
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
BeforeAll {
|
||||
Add-Type -Path "./build/bin/DSInternals.Win32.WebAuthn.Tests/release/DSInternals.Win32.WebAuthn.Tests.dll" -ErrorAction Stop
|
||||
Import-Module .\Build\bin\PSModule\Release\DSInternals.Passkeys\DSInternals.Passkeys.psm1 -Force
|
||||
}
|
||||
|
||||
Describe 'EntraID Tests' {
|
||||
BeforeAll {
|
||||
$SecureClientSecret = ConvertTo-SecureString -String $env:EntraIdClientSecret -AsPlainText -Force
|
||||
$ClientSecretCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $env:EntraIdClientId, $SecureClientSecret
|
||||
Connect-MgGraph -TenantId $env:EntraIdTenantId -ClientSecretCredential $ClientSecretCredential
|
||||
}
|
||||
|
||||
It "Registers passkeys to Entra ID for each credential parameter option" {
|
||||
$options = Get-PasskeyRegistrationOptions -UserId $env:EntraIdUserId
|
||||
$options | Should -BeOfType [DSInternals.Win32.WebAuthn.EntraID.MicrosoftGraphWebauthnCredentialCreationOptions]
|
||||
$options.ChallengeTimeout | Should -BeGreaterThan (Get-Date)
|
||||
$options.PublicKeyOptions.RelyingParty.Id | Should -Be "login.microsoft.com"
|
||||
$options.PublicKeyOptions.PublicKeyCredentialParameters.Count | Should -Be 2
|
||||
|
||||
$factory0 = [DSInternals.Win32.WebAuthn.Tests.PasskeyFactory]::new()
|
||||
$factory0 | Should -BeOfType [DSInternals.Win32.WebAuthn.Tests.PasskeyFactory]
|
||||
$passkey0 = $factory0.MakePasskey($options, 0)
|
||||
$passkey0 | Should -BeOfType [DSInternals.Win32.WebAuthn.EntraID.MicrosoftGraphWebauthnAttestationResponse]
|
||||
$passkey0.DisplayName | Should -BeLike 'DSInternals.Passkeys*'
|
||||
|
||||
$factory1 = [DSInternals.Win32.WebAuthn.Tests.PasskeyFactory]::new()
|
||||
$factory1 | Should -BeOfType [DSInternals.Win32.WebAuthn.Tests.PasskeyFactory]
|
||||
$passkey1 = $factory1.MakePasskey($options, 1)
|
||||
$passkey1 | Should -BeOfType [DSInternals.Win32.WebAuthn.EntraID.MicrosoftGraphWebauthnAttestationResponse]
|
||||
$passkey1.DisplayName | Should -BeLike 'DSInternals.Passkeys*'
|
||||
|
||||
$result0 = Register-Passkey -Passkey $passkey0 -UserId $env:EntraIdUserId
|
||||
$result0 | Should -Not -BeNullOrEmpty
|
||||
$result0 | Should -BeOfType [Microsoft.Graph.PowerShell.Models.MicrosoftGraphFido2AuthenticationMethod]
|
||||
$result0.AaGuid | Should -Be "4453496e-7465-726e-616c-730000000000"
|
||||
$result0.CreatedDateTime | Should -BeLessThan $options.ChallengeTimeout
|
||||
$result0.AttestationCertificates.Count | Should -Be 1
|
||||
$credentialId0 = $result0.Id
|
||||
|
||||
$result1 = Register-Passkey -Passkey $passkey1 -UserId $env:EntraIdUserId
|
||||
$result1 | Should -Not -BeNullOrEmpty
|
||||
$result1 | Should -BeOfType [Microsoft.Graph.PowerShell.Models.MicrosoftGraphFido2AuthenticationMethod]
|
||||
$result1.AaGuid | Should -Be "4453496e-7465-726e-616c-730000000000"
|
||||
$result1.CreatedDateTime | Should -BeLessThan $options.ChallengeTimeout
|
||||
$result1.AttestationCertificates.Count | Should -Be 1
|
||||
$credentialId1 = $result1.Id
|
||||
|
||||
$result0.AttestationCertificates[0] | Should -Not -Be $result1.AttestationCertificates[0]
|
||||
$result0.Id | Should -Not -Be $result1.Id
|
||||
|
||||
[string] $credentialDeletionUrl0 = '/beta/users/{0}/authentication/fido2Methods/{1}' -f [uri]::EscapeDataString($env:EntraIdUserId), $credentialId0
|
||||
$response0 = Invoke-MgGraphRequest -Method Delete -Uri $credentialDeletionUrl0
|
||||
$response0 | Should -BeNullOrEmpty
|
||||
|
||||
[string] $credentialDeletionUrl1 = '/beta/users/{0}/authentication/fido2Methods/{1}' -f [uri]::EscapeDataString($env:EntraIdUserId), $credentialId1
|
||||
$response1 = Invoke-MgGraphRequest -Method Delete -Uri $credentialDeletionUrl1
|
||||
$response1 | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
Disconnect-MgGraph
|
||||
}
|
||||
}
|
||||
|
||||
Describe "Okta Tests" {
|
||||
BeforeAll {
|
||||
Connect-Okta -Tenant $env:OktaTenantId -ClientId $env:OKtaClientId -Scopes @('okta.users.manage') -JsonWebKey $env:OktaJsonWebKey
|
||||
}
|
||||
|
||||
It "Registers passkeys to Okta for each credential parameter option" {
|
||||
$options0 = Get-PasskeyRegistrationOptions -UserId $env:OktaUserId
|
||||
$options0 | Should -BeOfType [DSInternals.Win32.WebAuthn.Okta.OktaWebauthnCredentialCreationOptions]
|
||||
$options0.PublicKeyOptions.RelyingParty.Id | Should -Be $env:OktaTenantId
|
||||
$options0.PublicKeyOptions.PublicKeyCredentialParameters.Count | Should -Be 2
|
||||
|
||||
$factory0 = [DSInternals.Win32.WebAuthn.Tests.PasskeyFactory]::new()
|
||||
$factory0 | Should -BeOfType [DSInternals.Win32.WebAuthn.Tests.PasskeyFactory]
|
||||
|
||||
$passkey0 = $factory0.MakePasskey($options0, 0)
|
||||
$passkey0 | Should -BeOfType [DSInternals.Win32.WebAuthn.Okta.OktaWebauthnAttestationResponse]
|
||||
$passkey0 | Should -Not -BeNullOrEmpty
|
||||
$factorId0 = $passkey0.FactorId
|
||||
|
||||
$result0 = Register-Passkey -Passkey $passkey0 -UserId $env:OktaUserId
|
||||
$result0 | Should -Not -BeNullOrEmpty
|
||||
$result0 | Should -BeOfType [DSInternals.Win32.WebAuthn.Okta.OktaFido2AuthenticationMethod]
|
||||
$result0.Id | Should -Be $factorId0
|
||||
$result0.FactorType | Should -Be "webauthn"
|
||||
$result0.Provider | Should -Be "FIDO"
|
||||
$result0.VendorName | Should -Be "FIDO"
|
||||
$result0.Status | Should -Be "ACTIVE"
|
||||
$result0.Created | Should -BeLessThan (Get-Date -AsUTC)
|
||||
$result0.Profile.CredentialId | Should -Not -BeNullOrEmpty
|
||||
$result0.Profile.CredentialId | Should -Be ([Convert]::ToBase64String($passkey0.PublicKeyCred.Id)).Replace('+', '-').Replace('/', '_').Replace('=', '')
|
||||
|
||||
$OktaUserId = $env:OktaUserId
|
||||
[string] $credentialDeletionPath0 = "/api/v1/users/${OktaUserId}/factors/${factorId0}"
|
||||
$response0 = Invoke-OktaWebRequest -Method ([Microsoft.PowerShell.Commands.WebRequestMethod]::Delete) -Path $credentialDeletionPath0
|
||||
$response0.StatusCode | Should -Be 204
|
||||
$response0.RawContentLength | Should -Be 0
|
||||
|
||||
$options1 = Get-PasskeyRegistrationOptions -UserId $env:OktaUserId
|
||||
$options1 | Should -BeOfType [DSInternals.Win32.WebAuthn.Okta.OktaWebauthnCredentialCreationOptions]
|
||||
$options1.PublicKeyOptions.RelyingParty.Id | Should -Be $env:OktaTenantId
|
||||
$options1.PublicKeyOptions.PublicKeyCredentialParameters.Count | Should -Be 2
|
||||
|
||||
$factory1 = [DSInternals.Win32.WebAuthn.Tests.PasskeyFactory]::new()
|
||||
$factory1 | Should -BeOfType [DSInternals.Win32.WebAuthn.Tests.PasskeyFactory]
|
||||
|
||||
$passkey1 = $factory1.MakePasskey($options1, 1)
|
||||
$passkey1 | Should -BeOfType [DSInternals.Win32.WebAuthn.Okta.OktaWebauthnAttestationResponse]
|
||||
$passkey1 | Should -Not -BeNullOrEmpty
|
||||
$factorId1 = $passkey1.FactorId
|
||||
|
||||
$result1 = Register-Passkey -Passkey $passkey1 -UserId $env:OktaUserId
|
||||
$result1 | Should -Not -BeNullOrEmpty
|
||||
$result1 | Should -BeOfType [DSInternals.Win32.WebAuthn.Okta.OktaFido2AuthenticationMethod]
|
||||
$result1.Id | Should -Be $factorId1
|
||||
$result1.FactorType | Should -Be "webauthn"
|
||||
$result1.Provider | Should -Be "FIDO"
|
||||
$result1.VendorName | Should -Be "FIDO"
|
||||
$result1.Status | Should -Be "ACTIVE"
|
||||
$result1.Created | Should -BeLessThan (Get-Date -AsUTC)
|
||||
$result1.Profile.CredentialId | Should -Not -BeNullOrEmpty
|
||||
$result1.Profile.CredentialId | Should -Be ([Convert]::ToBase64String($passkey1.PublicKeyCred.Id)).Replace('+', '-').Replace('/', '_').Replace('=', '')
|
||||
|
||||
[string] $credentialDeletionPath1 = "/api/v1/users/${OktaUserId}/factors/${factorId1}"
|
||||
$response1 = Invoke-OktaWebRequest -Method ([Microsoft.PowerShell.Commands.WebRequestMethod]::Delete) -Path $credentialDeletionPath1
|
||||
$response1.StatusCode | Should -Be 204
|
||||
$response1.RawContentLength | Should -Be 0
|
||||
|
||||
$result0.Profile.CredentialId | Should -Not -Be $result1.Profile.CredentialId
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
Disconnect-Okta
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@ RequiredModules = @('Microsoft.Graph.Authentication','Microsoft.Graph.Identity.S
|
||||
# NestedModules = @()
|
||||
|
||||
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
|
||||
FunctionsToExport = @('Get-PasskeyRegistrationOptions', 'New-Passkey', 'Register-Passkey')
|
||||
FunctionsToExport = @('Get-PasskeyRegistrationOptions', 'New-Passkey', 'Register-Passkey','Connect-Okta','Disconnect-Okta')
|
||||
|
||||
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
|
||||
CmdletsToExport = @()
|
||||
@@ -96,7 +96,7 @@ PrivateData = @{
|
||||
PSData = @{
|
||||
|
||||
# Tags applied to this module. These help with module discovery in online galleries.
|
||||
Tags = @('Windows', 'PSEdition_Desktop', 'PSEdition_Core', 'PSModule', 'FIDO2', 'Passkeys', 'EntraID', 'AzureAD', 'Azure', 'WebAuthn', 'CTAP', 'Security','2FA','MFA','Authentication','Identity','Passwordless')
|
||||
Tags = @('Windows', 'PSEdition_Desktop', 'PSEdition_Core', 'PSModule', 'FIDO2', 'Passkeys', 'EntraID', 'AzureAD', 'Azure', 'WebAuthn', 'CTAP', 'Security','2FA','MFA','Authentication','Identity','Passwordless','Okta')
|
||||
|
||||
# A URL to the license for this module.
|
||||
LicenseUri = 'https://github.com/MichaelGrafnetter/webauthn-interop/blob/main/LICENSE'
|
||||
|
||||
@@ -2,25 +2,196 @@
|
||||
if ($PSVersionTable.PSVersion.Major -ge 6) {
|
||||
# PowerShell Core
|
||||
Add-Type -Path "$PSScriptRoot/net6.0/DSInternals.Win32.WebAuthn.dll" -ErrorAction Stop
|
||||
Add-Type -Path "$PSScriptRoot/net6.0/Microsoft.Identity.Client.dll" -ErrorAction Stop
|
||||
Add-Type -Path "$PSScriptRoot/net6.0/System.IdentityModel.Tokens.Jwt.dll" -ErrorAction Stop
|
||||
}
|
||||
else {
|
||||
# PowerShell Desktop
|
||||
Add-Type -Path "$PSScriptRoot/net48/DSInternals.Win32.WebAuthn.dll" -ErrorAction Stop
|
||||
Add-Type -Path "$PSScriptRoot/net48/Microsoft.Identity.Client.dll" -ErrorAction Stop
|
||||
Add-Type -Path "$PSScriptRoot/net48/System.IdentityModel.Tokens.Jwt.dll" -ErrorAction Stop
|
||||
}
|
||||
|
||||
# Needed for [Microsoft.Graph.PowerShell.Models.MicrosoftGraphFido2AuthenticationMethod] type
|
||||
Import-Module -Name Microsoft.Graph.Identity.SignIns -ErrorAction Stop
|
||||
|
||||
New-Variable -Name OktaToken -Value $null -Scope Script
|
||||
New-Variable -Name OktaRevocationInfo -Value $null -Scope Script
|
||||
|
||||
function Get-EntraIDPasskeyRegistrationOptions
|
||||
{
|
||||
[OutputType([DSInternals.Win32.WebAuthn.EntraID.MicrosoftGraphWebauthnCredentialCreationOptions])]
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateScript({
|
||||
return $_ -match "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" -or $true -eq [guid]::TryParse($_, $([ref][guid]::Empty))
|
||||
})]
|
||||
[Alias('User')]
|
||||
[string] $UserId,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateScript({
|
||||
if ($_ -is [TimeSpan]) {
|
||||
$min = New-TimeSpan -Minutes 5
|
||||
$max = New-TimeSpan -Minutes 43200
|
||||
return $_ -ge $min -and $_ -le $max
|
||||
}
|
||||
else {
|
||||
throw "Parameter must be a TimeSpan object."
|
||||
}
|
||||
})]
|
||||
[Alias('Timeout')]
|
||||
[TimeSpan] $ChallengeTimeout = (New-TimeSpan -Minutes 5)
|
||||
)
|
||||
try {
|
||||
Write-Debug "UserId ${UserId} TokenLifetimeSeconds ${ChallengeTimeout}"
|
||||
# Generate the user-specific URL, e.g., https://graph.microsoft.com/beta/users/af4cf208-16e0-429d-b574-2a09c5f30dea/authentication/fido2Methods/creationOptions
|
||||
[string] $credentialOptionsUrl = '/beta/users/{0}/authentication/fido2Methods/creationOptions' -f [uri]::EscapeDataString($UserId)
|
||||
|
||||
Write-Debug ('Credential options url: ' + $credentialOptionsUrl)
|
||||
|
||||
[string] $response = Invoke-MgGraphRequest -Method GET `
|
||||
-Uri $credentialOptionsUrl `
|
||||
-Body @{ challengeTimeoutInMinutes = $ChallengeTimeout.TotalMinutes } `
|
||||
-OutputType Json
|
||||
|
||||
Write-Debug ('Credential options response: ' + $response)
|
||||
|
||||
# Parse JSON response
|
||||
return [DSInternals.Win32.WebAuthn.EntraID.MicrosoftGraphWebauthnCredentialCreationOptions]::Create($response)
|
||||
}
|
||||
catch {
|
||||
throw $_
|
||||
}
|
||||
}
|
||||
|
||||
function Invoke-OktaWebRequest
|
||||
{
|
||||
param(
|
||||
$Path,
|
||||
$Query,
|
||||
$Method = [Microsoft.PowerShell.Commands.WebRequestMethod]::Post,
|
||||
$Body,
|
||||
$ContentType = "application/json"
|
||||
)
|
||||
|
||||
Write-Debug "Path ${Path}"
|
||||
Write-Debug "Query ${Query}"
|
||||
Write-Debug "Method ${Method}"
|
||||
Write-Debug ('Body ' + ($Body | ConvertTo-Json))
|
||||
Write-Debug "Content type ${ContentType}"
|
||||
|
||||
$tokenType = $Script:OktaToken.TokenType
|
||||
$token = $Script:OktaToken.AccessToken
|
||||
$headers = @{
|
||||
"Accept" = "application/json"
|
||||
"Authorization" = "${tokenType} ${token}"
|
||||
}
|
||||
|
||||
$tenant = ([System.UriBuilder]($Script:OktaToken.AuthenticationResultMetadata.TokenEndpoint)).Host
|
||||
Write-Debug "Tenant ${Tenant}"
|
||||
|
||||
$uriBuilder = New-Object System.UriBuilder
|
||||
$uriBuilder.Scheme = "https"
|
||||
$uriBuilder.Host = $tenant
|
||||
$uriBuilder.Path = $Path
|
||||
$uriBuilder.Query = $Query
|
||||
|
||||
$uri = $uriBuilder.ToString()
|
||||
Write-Debug "Uri ${uri}"
|
||||
|
||||
return Invoke-WebRequest -Uri $uri `
|
||||
-Method $Method `
|
||||
-Headers $headers `
|
||||
-ContentType $ContentType `
|
||||
-Body $Body
|
||||
}
|
||||
|
||||
function Get-OktaPasskeyRegistrationOptions
|
||||
{
|
||||
[OutputType([DSInternals.Win32.WebAuthn.Okta.OktaWebauthnCredentialCreationOptions])]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidatePattern("^[A-Za-z0-9_-]{20}$")]
|
||||
[Alias('User')]
|
||||
[string] $UserId,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateScript({
|
||||
if ($_ -is [TimeSpan]) {
|
||||
$min = New-TimeSpan -Seconds 1
|
||||
$max = New-TimeSpan -Seconds 86400
|
||||
return $_ -ge $min -and $_ -le $max
|
||||
}
|
||||
else {
|
||||
throw "Parameter must be a TimeSpan object."
|
||||
}
|
||||
})]
|
||||
[Alias('Timeout')]
|
||||
[TimeSpan] $ChallengeTimeout = (New-TimeSpan -Minutes 5)
|
||||
)
|
||||
begin {
|
||||
if ($null -eq $Script:OktaToken)
|
||||
{
|
||||
throw 'Not connected to Okta, call Connnect-Okta to get started.'
|
||||
}
|
||||
}
|
||||
process {
|
||||
try
|
||||
{
|
||||
Write-Debug "In Get-OktaPasskeyRegistrationOptions with ${UserId} and ${ChallengeTimeout}"
|
||||
|
||||
$TokenLifetimeSeconds = $ChallengeTimeout.TotalSeconds
|
||||
|
||||
Write-Debug "TokenLifetimeSeconds ${TokenLifetimeSeconds}"
|
||||
|
||||
[string] $credentialOptionsPath = "/api/v1/users/${UserId}/factors"
|
||||
[string] $credentialOptionsQuery = "tokenLifetimeSeconds=${TokenLifetimeSeconds}&activate=true"
|
||||
Write-Debug ('Credential options path: ' + $credentialOptionsPath)
|
||||
Write-Debug ('Credential options query: ' + $credentialOptionsQuery)
|
||||
|
||||
$body = @{
|
||||
factorType = "webauthn"
|
||||
provider = "FIDO"
|
||||
} | ConvertTo-Json -Compress
|
||||
|
||||
Write-Debug ('Credential options payload: ' + $body)
|
||||
|
||||
[string] $response = Invoke-OktaWebRequest -Path $credentialOptionsPath `
|
||||
-Query $credentialOptionsQuery `
|
||||
-Body $body
|
||||
|
||||
Write-Debug ('Credential options response: ' + $response)
|
||||
|
||||
# Parse JSON response
|
||||
$options = [DSInternals.Win32.WebAuthn.Okta.OktaWebauthnCredentialCreationOptions]::Create($response)
|
||||
|
||||
# Okta appears to omit relying party id in the options, but it is required for credential creation
|
||||
# So set default to the tenant we are talking to, which is probably what the user wants anyway
|
||||
if ($null -eq $options.Embedded.PublicKeyOptions.RelyingParty.Id)
|
||||
{
|
||||
Write-Debug ('Setting relying party id to ' + ([System.UriBuilder]($Script:OktaToken.AuthenticationResultMetadata.TokenEndpoint)).Host)
|
||||
$options.Embedded.PublicKeyOptions.RelyingParty.Id = ([System.UriBuilder]($Script:OktaToken.AuthenticationResultMetadata.TokenEndpoint)).Host
|
||||
}
|
||||
Write-Debug ('Credential options: ' + ($options | Out-String))
|
||||
return $options
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw $_
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieves creation options required to generate and register a Microsoft Entra ID-compatible passkey.
|
||||
Retrieves creation options required to generate and register a Microsoft Entra ID or Okta compatible passkey.
|
||||
|
||||
.PARAMETER UserId
|
||||
The unique identifier of user.
|
||||
The unique identifier of user. For Entra ID, this is the object id (guid) or UPN. For Okta, this is the unique identifier of Okta user.
|
||||
|
||||
.PARAMETER ChallengeTimeout
|
||||
Overrides the timeout of the server-generated challenge returned in the request.
|
||||
The default value is 5 minutes, with the accepted range being between 5 minutes and 30 days.
|
||||
Overrides the timeout of the server-generated challenge returned in the request. For Entra ID, the default value is 5 minutes, with the accepted range being between 5 minutes and 30 days. For Okta, the default value is 300 second, with the accepted range being between 1 second and 1 day.
|
||||
|
||||
.EXAMPLE
|
||||
PS \> Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
@@ -30,58 +201,205 @@ PS \> Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com'
|
||||
PS \> Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' -ChallengeTimeout (New-TimeSpan -Minutes 10)
|
||||
|
||||
.EXAMPLE
|
||||
PS \> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 00eDuihq64pgP1gVD0x7
|
||||
|
||||
.EXAMPLE
|
||||
PS \> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 00eDuihq64pgP1gVD0x7 -ChallengeTimeout (New-TimeSpan -Seconds 60)
|
||||
|
||||
.NOTES
|
||||
Self-service operations aren't supported.
|
||||
More info at https://learn.microsoft.com/en-us/graph/api/fido2authenticationmethod-creationoptions
|
||||
Self-service operations aren't supported for Entra ID.
|
||||
More info about Entra ID at https://learn.microsoft.com/en-us/graph/api/fido2authenticationmethod-creationoptions
|
||||
More info about Okta at https://developer.okta.com/docs/api/openapi/okta-management/management/tag/UserFactor/#tag/UserFactor/operation/enrollFactor
|
||||
|
||||
#>
|
||||
function Get-PasskeyRegistrationOptions
|
||||
{
|
||||
[CmdletBinding()]
|
||||
[OutputType([DSInternals.Win32.WebAuthn.MicrosoftGraphWebauthnCredentialCreationOptions])]
|
||||
[OutputType([DSInternals.Win32.WebAuthn.WebauthnCredentialCreationOptions])]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Alias('User')]
|
||||
[ValidateScript({
|
||||
if ($_ -match "^[A-Za-z0-9_-]{20}$" -or $true -eq [guid]::TryParse($_, $([ref][guid]::Empty)) -or $_ -match "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$")
|
||||
{return $true}
|
||||
return $false
|
||||
})]
|
||||
[string] $UserId,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[Alias('Timeout')]
|
||||
[timespan] $ChallengeTimeout = (New-TimeSpan -Minutes 5)
|
||||
)
|
||||
try {
|
||||
# Generate the user-specific URL, e.g., https://graph.microsoft.com/beta/users/af4cf208-16e0-429d-b574-2a09c5f30dea/authentication/fido2Methods/creationOptions
|
||||
[string] $credentialOptionsUrl = '/beta/users/{0}/authentication/fido2Methods/creationOptions' -f [uri]::EscapeDataString($UserId)
|
||||
|
||||
[string] $response = Invoke-MgGraphRequest -Method GET `
|
||||
-Uri $credentialOptionsUrl `
|
||||
-Body @{ challengeTimeoutInMinutes = $ChallengeTimeout.TotalMinutes } `
|
||||
-OutputType Json
|
||||
|
||||
# Parse JSON response
|
||||
return [DSInternals.Win32.WebAuthn.MicrosoftGraphWebauthnCredentialCreationOptions]::Create($response)
|
||||
begin {
|
||||
Write-Debug "In Get-PasskeyRegistrationOptions with ${UserId} and ${ChallengeTimeout}"
|
||||
$IsEntraID = ($UserId -match "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" -or $true -eq [guid]::TryParse($UserId, $([ref][guid]::Empty)))
|
||||
Write-Debug "IsEntraID: ${IsEntraId}"
|
||||
if ($IsEntraID)
|
||||
{
|
||||
$min = New-TimeSpan -Minutes 5
|
||||
$max = New-TimeSpan -Minutes 43200
|
||||
if ($ChallengeTimeout -gt $max -or $ChallengeTimeout -lt $min) {
|
||||
Write-Error "Cannot validate argument on parameter 'ChallengeTimeout' which must be a valid TimeSpan between 5 and 43200 minutes for $_." -ErrorAction Stop
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$min = New-TimeSpan -Seconds 1
|
||||
$max = New-TimeSpan -Seconds 86400
|
||||
if ($ChallengeTimeout -gt $max -or $ChallengeTimeout -lt $min) {
|
||||
Write-Error "Cannot validate argument on parameter 'ChallengeTimeout' which must be a valid TimeSpan between 1 and 86400 seconds for $_." -ErrorAction Stop
|
||||
}
|
||||
if ($UserId -notmatch "^[A-Za-z0-9_-]{20}$") {
|
||||
Write-Error "Cannot validate argument on parameter 'UserID' which must the unique idenitier for the user for Okta." -ErrorAction Stop
|
||||
}
|
||||
if ($null -eq $Script:OktaToken) {
|
||||
throw 'Not connected to Okta, call Connnect-Okta to get started.'
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
# TODO: PS Error Record ($PSCmdlet.ThrowTerminatingError())
|
||||
throw
|
||||
process {
|
||||
$Options = $null
|
||||
try {
|
||||
if ($IsEntraID) {
|
||||
Write-Debug "Calling Get-EntraIDPasskeyRegistrationOptions with ${UserId} and ${ChallengeTimeout}"
|
||||
$Options = Get-EntraIDPasskeyRegistrationOptions -UserId $UserId -ChallengeTimeout $ChallengeTimeout
|
||||
}
|
||||
else {
|
||||
Write-Debug "Calling Get-OktaPasskeyRegistrationOptions with ${UserId} and ${ChallengeTimeout}"
|
||||
$Options = Get-OktaPasskeyRegistrationOptions -UserId $UserId -ChallengeTimeout $ChallengeTimeout
|
||||
}
|
||||
return $Options
|
||||
}
|
||||
catch {
|
||||
$errorRecord = New-Object Management.Automation.ErrorRecord(
|
||||
$_.Exception,
|
||||
$_.Exception.Message,
|
||||
[Management.Automation.ErrorCategory]::InvalidArgument,
|
||||
$Options
|
||||
)
|
||||
|
||||
$PSCmdlet.ThrowTerminatingError($errorRecord)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Register-EntraIDPasskey
|
||||
{
|
||||
[OutputType([Microsoft.Graph.PowerShell.Models.MicrosoftGraphFido2AuthenticationMethod])]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateScript({
|
||||
return $_ -match "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" -or $true -eq [guid]::TryParse($_, $([ref][guid]::Empty))
|
||||
})]
|
||||
[Alias('User')]
|
||||
[string] $UserId,
|
||||
|
||||
[ValidateScript({
|
||||
if ([string]::IsNullOrEmpty($_.DisplayName))
|
||||
{
|
||||
throw "Passkey 'DisplayName' field may not be null or empty."
|
||||
}
|
||||
return $true
|
||||
})]
|
||||
[DSInternals.Win32.WebAuthn.EntraID.MicrosoftGraphWebauthnAttestationResponse]
|
||||
$Passkey
|
||||
)
|
||||
try
|
||||
{
|
||||
# Generate the user-specific URL, e.g., https://graph.microsoft.com/beta/users/af4cf208-16e0-429d-b574-2a09c5f30dea/authentication/fido2Methods
|
||||
[string] $registrationUrl = '/beta/users/{0}/authentication/fido2Methods' -f [uri]::EscapeDataString($UserId)
|
||||
|
||||
Write-Debug ('Registration URL: ' + $registrationUrl)
|
||||
|
||||
[string] $response = Invoke-MgGraphRequest `
|
||||
-Method POST `
|
||||
-Uri $registrationUrl `
|
||||
-OutputType Json `
|
||||
-ContentType 'application/json' `
|
||||
-Body $Passkey.ToString()
|
||||
|
||||
Write-Debug ('Registration response: ' + $response)
|
||||
|
||||
return [Microsoft.Graph.PowerShell.Models.MicrosoftGraphFido2AuthenticationMethod]::FromJsonString($response)
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw $_
|
||||
}
|
||||
}
|
||||
|
||||
function Register-OktaPasskey
|
||||
{
|
||||
[CmdletBinding(DefaultParameterSetName = 'New')]
|
||||
[OutputType([DSInternals.Win32.WebAuthn.Okta.OktaFido2AuthenticationMethod])]
|
||||
param (
|
||||
[Parameter(Mandatory = $true, ParameterSetName = 'Existing')]
|
||||
[Parameter(Mandatory = $true, ParameterSetName = 'New')]
|
||||
[Alias('User')]
|
||||
[string] $UserId,
|
||||
|
||||
[Parameter(Mandatory = $true, ParameterSetName = 'Existing', ValueFromPipeline = $true)]
|
||||
[DSInternals.Win32.WebAuthn.Okta.OktaWebauthnAttestationResponse]
|
||||
$Passkey,
|
||||
|
||||
[Parameter(Mandatory = $false, ParameterSetName = 'New')]
|
||||
[ValidateScript({
|
||||
if ($_ -is [TimeSpan]) {
|
||||
$min = New-TimeSpan -Seconds 1
|
||||
$max = New-TimeSpan -Seconds 86400
|
||||
return $_ -ge $min -and $_ -le $max
|
||||
}
|
||||
else {
|
||||
throw "Parameter must be a TimeSpan object."
|
||||
}
|
||||
})]
|
||||
[Alias('Timeout')]
|
||||
[timespan] $ChallengeTimeout = (New-TimeSpan -Minutes 5)
|
||||
)
|
||||
try
|
||||
{
|
||||
if ($null -eq $Script:OktaToken)
|
||||
{
|
||||
throw 'Not connected to Okta, call Connnect-Okta to get started.'
|
||||
}
|
||||
|
||||
$userId = $Passkey.UserId
|
||||
$factorId = $Passkey.FactorId
|
||||
[string] $registrationPath = "/api/v1/users/${userId}/factors/${factorId}/lifecycle/activate"
|
||||
|
||||
Write-Debug ('Registration path: ' + $registrationPath)
|
||||
|
||||
[string] $response = Invoke-OktaWebRequest -Path $registrationPath `
|
||||
-Body $Passkey.ToString()
|
||||
|
||||
Write-Debug ('Registration response: ' + $response)
|
||||
|
||||
return [DSInternals.Win32.WebAuthn.Okta.OktaFido2AuthenticationMethod]::FromJsonString($response)
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw $_
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Registers a new passkey in Microsoft Entra ID.
|
||||
Registers a new passkey in Microsoft Entra ID, or Okta.
|
||||
|
||||
.PARAMETER UserId
|
||||
The unique identifier of user.
|
||||
The unique identifier of user. For Entra ID, this is the object id (guid) or UPN. For Okta, this is the unique identifier of Okta user.
|
||||
|
||||
.PARAMETER ChallengeTimeout
|
||||
Overrides the timeout of the server-generated challenge returned in the request. For Entra ID, the default value is 5 minutes, with the accepted range being between 5 minutes and 30 days. For Okta, the default value is 300 second, with the accepted range being between 1 second and 1 day.
|
||||
|
||||
.PARAMETER Passkey
|
||||
The passkey to be registered.
|
||||
|
||||
.PARAMETER DisplayName
|
||||
Custom name given to the registered passkey.
|
||||
|
||||
.PARAMETER ChallengeTimeout
|
||||
Overrides the timeout of the server-generated challenge returned in the request.
|
||||
The default value is 5 minutes, with the accepted range being between 5 minutes and 30 days.
|
||||
Custom name given to the Entra ID registered passkey.
|
||||
|
||||
.EXAMPLE
|
||||
PS \> Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
@@ -95,54 +413,74 @@ PS \> Register-Passkey -UserId 'AdeleV@contoso.com' -DisplayName 'YubiKey 5 Nano
|
||||
PS \> Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' | New-Passkey -DisplayName 'YubiKey 5 Nano' | Register-Passkey -UserId 'AdeleV@contoso.com'
|
||||
|
||||
.EXAMPLE
|
||||
PS \> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7
|
||||
PS \> Register-Passkey -UserId 00eDuihq64pgP1gVD0x7
|
||||
|
||||
.EXAMPLE
|
||||
PS \> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 00eDuihq64pgP1gVD0x7 | New-Passkey | Register-Passkey
|
||||
|
||||
.NOTES
|
||||
More info at https://learn.microsoft.com/en-us/graph/api/authentication-post-fido2methods
|
||||
More info for Entra ID at https://learn.microsoft.com/en-us/graph/api/authentication-post-fido2methods
|
||||
More info for Okta at https://developer.okta.com/docs/api/openapi/okta-management/management/tag/UserFactor/#tag/UserFactor/operation/activateFactor
|
||||
|
||||
#>
|
||||
function Register-Passkey
|
||||
{
|
||||
[CmdletBinding(DefaultParameterSetName = 'New')]
|
||||
[OutputType([Microsoft.Graph.PowerShell.Models.MicrosoftGraphFido2AuthenticationMethod])]
|
||||
[OutputType([DSInternals.Win32.WebAuthn.Okta.OktaFido2AuthenticationMethod], ParameterSetName = 'OktaNew')]
|
||||
[OutputType([Microsoft.Graph.PowerShell.Models.MicrosoftGraphFido2AuthenticationMethod], ParameterSetName = 'EntraIDNew')]
|
||||
param(
|
||||
[Parameter(Mandatory = $true, ParameterSetName = 'EntraIDNew')]
|
||||
[Parameter(Mandatory = $true, ParameterSetName = 'Existing')]
|
||||
[Parameter(Mandatory = $true, ParameterSetName = 'New')]
|
||||
[Parameter(Mandatory = $true, ParameterSetName = 'OktaNew')]
|
||||
[Alias('User')]
|
||||
[string] $UserId,
|
||||
|
||||
[Parameter(Mandatory = $true, ParameterSetName = 'Existing', ValueFromPipeline = $true)]
|
||||
[DSInternals.Win32.WebAuthn.MicrosoftGraphWebauthnAttestationResponse]
|
||||
[DSInternals.Win32.WebAuthn.WebauthnAttestationResponse]
|
||||
$Passkey,
|
||||
|
||||
[Parameter(Mandatory = $true, ParameterSetName = 'New')]
|
||||
[Parameter(Mandatory = $true, ParameterSetName = 'EntraIDNew')]
|
||||
[string] $DisplayName,
|
||||
|
||||
[Parameter(Mandatory = $false, ParameterSetName = 'New')]
|
||||
[Parameter(Mandatory = $false, ParameterSetName = 'EntraIDNew')]
|
||||
[Parameter(Mandatory = $false, ParameterSetName = 'OktaNew')]
|
||||
[Alias('Timeout')]
|
||||
[timespan] $ChallengeTimeout = (New-TimeSpan -Minutes 5)
|
||||
)
|
||||
process
|
||||
{
|
||||
# TODO: Write-Error
|
||||
|
||||
begin {
|
||||
if ($null -ne $Passkey -and $Passkey.GetType() -eq ([DSInternals.Win32.WebAuthn.EntraID.MicrosoftGraphWebauthnAttestationResponse]) -and [string]::IsNullOrEmpty($Passkey.displayName)) {
|
||||
throw "Parameter 'DisplayName' may not be null or empty."
|
||||
}
|
||||
}
|
||||
|
||||
process {
|
||||
switch ($PSCmdlet.ParameterSetName) {
|
||||
'Existing' {
|
||||
# Generate the user-specific URL, e.g., https://graph.microsoft.com/beta/users/af4cf208-16e0-429d-b574-2a09c5f30dea/authentication/fido2Methods
|
||||
[string] $registrationUrl = '/beta/users/{0}/authentication/fido2Methods' -f [uri]::EscapeDataString($UserId)
|
||||
switch ($Passkey.GetType())
|
||||
{
|
||||
([DSInternals.Win32.WebAuthn.EntraID.MicrosoftGraphWebauthnAttestationResponse])
|
||||
{
|
||||
return Register-EntraIDPasskey -UserId $UserId -Passkey $Passkey
|
||||
}
|
||||
|
||||
[string] $response = Invoke-MgGraphRequest `
|
||||
-Method POST `
|
||||
-Uri $registrationUrl `
|
||||
-OutputType Json `
|
||||
-ContentType 'application/json' `
|
||||
-Body $Passkey.ToString()
|
||||
|
||||
return [Microsoft.Graph.PowerShell.Models.MicrosoftGraphFido2AuthenticationMethod]::FromJsonString($response)
|
||||
([DSInternals.Win32.WebAuthn.Okta.OktaWebauthnAttestationResponse])
|
||||
{
|
||||
if ($null -eq $Script:OktaToken) {
|
||||
throw 'Not connected to Okta, call Connnect-Okta to get started.'
|
||||
}
|
||||
return Register-OktaPasskey -UserId $UserId -Passkey $Passkey
|
||||
}
|
||||
}
|
||||
}
|
||||
'New' {
|
||||
[DSInternals.Win32.WebAuthn.MicrosoftGraphWebauthnCredentialCreationOptions] $registrationOptions =
|
||||
Get-PasskeyRegistrationOptions -UserId $UserId -ChallengeTimeout $ChallengeTimeout
|
||||
default {
|
||||
[DSInternals.Win32.WebAuthn.WebauthnCredentialCreationOptions] $registrationOptions =
|
||||
Get-PasskeyRegistrationOptions -UserId $UserId -ChallengeTimeout $ChallengeTimeout
|
||||
|
||||
[DSInternals.Win32.WebAuthn.MicrosoftGraphWebauthnAttestationResponse] $passkey =
|
||||
New-Passkey -Options $registrationOptions -DisplayName $DisplayName
|
||||
[DSInternals.Win32.WebAuthn.WebauthnAttestationResponse] $passkey =
|
||||
New-Passkey -Options $registrationOptions -DisplayName $DisplayName
|
||||
|
||||
# Recursive call with the 'Existing' parameter set
|
||||
return Register-Passkey -UserId $UserId -Passkey $passkey
|
||||
@@ -153,47 +491,267 @@ function Register-Passkey
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Creates a new Microsoft Entra ID-compatible passkey.
|
||||
Creates a new Microsoft Entra ID or Okta compatible passkey.
|
||||
|
||||
.PARAMETER Options
|
||||
Options required to generate a Microsoft Entra ID-compatible passkey.
|
||||
Options required to generate a Microsoft Entra ID or Okta compatible passkey.
|
||||
|
||||
.PARAMETER DisplayName
|
||||
Custom name given to the registered passkey.
|
||||
Custom name given to the Entra ID registered passkey.
|
||||
|
||||
.EXAMPLE
|
||||
PS \> Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' | New-Passkey -DisplayName 'YubiKey 5 Nano' | Register-Passkey -UserId 'AdeleV@contoso.com'
|
||||
|
||||
.EXAMPLE
|
||||
PS \> New-Passkey -Options $options
|
||||
|
||||
.EXAMPLE
|
||||
PS \> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 00eDuihq64pgP1gVD0x7 | New-Passkey
|
||||
|
||||
.INPUTS
|
||||
DSInternals.Win32.WebAuthn.WebauthnCredentialCreationOptions
|
||||
|
||||
#>
|
||||
function New-Passkey
|
||||
{
|
||||
[OutputType([DSInternals.Win32.WebAuthn.WebauthnAttestationResponse])]
|
||||
[CmdletBinding()]
|
||||
[OutputType([DSInternals.Win32.WebAuthn.MicrosoftGraphWebauthnAttestationResponse])]
|
||||
param(
|
||||
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
|
||||
[DSInternals.Win32.WebAuthn.MicrosoftGraphWebauthnCredentialCreationOptions]
|
||||
[DSInternals.Win32.WebAuthn.WebauthnCredentialCreationOptions]
|
||||
$Options,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateLength(1, 30)]
|
||||
[string] $DisplayName
|
||||
)
|
||||
|
||||
process
|
||||
{
|
||||
try {
|
||||
[DSInternals.Win32.WebAuthn.WebAuthnApi] $api = [DSInternals.Win32.WebAuthn.WebAuthnApi]::new()
|
||||
[DSInternals.Win32.WebAuthn.PublicKeyCredential] $credential = $api.AuthenticatorMakeCredential($Options.PublicKeyOptions)
|
||||
return [DSInternals.Win32.WebAuthn.MicrosoftGraphWebauthnAttestationResponse]::new($credential, $DisplayName)
|
||||
try {
|
||||
[DSInternals.Win32.WebAuthn.WebAuthnApi] $api = [DSInternals.Win32.WebAuthn.WebAuthnApi]::new()
|
||||
[DSInternals.Win32.WebAuthn.PublicKeyCredential] $credential = $api.AuthenticatorMakeCredential($Options.PublicKeyOptions)
|
||||
|
||||
switch ($Options.GetType())
|
||||
{
|
||||
([DSInternals.Win32.WebAuthn.EntraID.MicrosoftGraphWebauthnCredentialCreationOptions])
|
||||
{
|
||||
if ([string]::IsNullOrEmpty($DisplayName)) {
|
||||
throw "Parameter 'DisplayName' may not be null or empty."
|
||||
}
|
||||
return [DSInternals.Win32.WebAuthn.EntraID.MicrosoftGraphWebauthnAttestationResponse]::new($credential, $DisplayName)
|
||||
}
|
||||
([DSInternals.Win32.WebAuthn.Okta.OktaWebauthnCredentialCreationOptions])
|
||||
{
|
||||
return [DSInternals.Win32.WebAuthn.Okta.OktaWebauthnAttestationResponse]::new($credential, $Options.PublicKeyOptions.User.Id, $Options.Id)
|
||||
}
|
||||
}
|
||||
catch {
|
||||
# TODO: PS Error Record (Write-Error)
|
||||
throw
|
||||
}
|
||||
catch {
|
||||
$errorRecord = New-Object Management.Automation.ErrorRecord(
|
||||
$_,
|
||||
$_.Message,
|
||||
[Management.Automation.ErrorCategory]::InvalidArgument,
|
||||
$Options
|
||||
)
|
||||
$PSCmdlet.ThrowTerminatingError($errorRecord)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieves the Microsoft Graph endpoint URL.
|
||||
|
||||
.NOTES
|
||||
Dynamic URL retrieval is used to support Azure environments, like Azure Public, Azure Government, or Azure China.
|
||||
|
||||
#>
|
||||
function Get-MgGraphEndpoint
|
||||
{
|
||||
[CmdletBinding()]
|
||||
[OutputType([string])]
|
||||
param()
|
||||
|
||||
try {
|
||||
[Microsoft.Graph.PowerShell.Authentication.AuthContext] $context = Get-MgContext -ErrorAction Stop
|
||||
|
||||
if($null -ne $context) {
|
||||
return (Get-MgEnvironment -Name $context.Environment -ErrorAction Stop).GraphEndpoint
|
||||
}
|
||||
}
|
||||
catch {
|
||||
$errorRecord = New-Object Management.Automation.ErrorRecord(
|
||||
(New-Object Exception('Not connected to Microsoft Graph.')),
|
||||
'Not connected to Microsoft Graph.',
|
||||
[Management.Automation.ErrorCategory]::ConnectionError,
|
||||
$context
|
||||
)
|
||||
|
||||
$PSCmdlet.ThrowTerminatingError($errorRecord)
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieves an access token to interact with Okta APIs.
|
||||
|
||||
.PARAMETER Tenant
|
||||
The unique identifier of Okta tenant, like 'example.okta.com'.
|
||||
|
||||
.PARAMETER ClientId
|
||||
The client id of the Okta application used to obtain an access token.
|
||||
|
||||
.PARAMETER Scopes
|
||||
Scopes to request for the access token. Defaults to 'okta.users.manage'.
|
||||
|
||||
.PARAMETER JsonWebKey
|
||||
The JSON Web Key used to authenticate to the Okta application, in order to obtain access token using the client credentials OAuth flow.
|
||||
|
||||
.EXAMPLE
|
||||
PS \> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7
|
||||
|
||||
.EXAMPLE
|
||||
PS \> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7 -Scopes @('okta.users.manage','okta.something.else')
|
||||
|
||||
.EXAMPLE
|
||||
PS \> $jwk = '{"kty":"RSA","kid":"EE3QB0WvhuOwR9DuR6717OERKbDrBemrDKOK4Xvbf8c","d":"TmljZSB0cnkhICBCdXQgdGhpcyBpc...'
|
||||
PS \> Connect-Okta -Tenant example.okta.com -ClientId 0oakmj8hvxvtvCy3P5d7 -Scopes @('okta.users.manage','okta.something.else') -JsonWebKey $jwk
|
||||
|
||||
#>
|
||||
|
||||
function Connect-Okta
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory = $true, ParameterSetName = 'ClientCredentials')]
|
||||
[Parameter(Mandatory = $true, ParameterSetName = 'AuthorizationCode')]
|
||||
[ValidatePattern('^[a-zA-Z0-9-]+\.okta(?:-emea|preview|\.mil)?\.com$')]
|
||||
[string] $Tenant,
|
||||
|
||||
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'ClientCredentials')]
|
||||
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'AuthorizationCode')]
|
||||
[ValidatePattern('^[A-Za-z0-9_-]{20}$')]
|
||||
[string]
|
||||
$ClientId,
|
||||
|
||||
[Parameter(Mandatory = $false, ParameterSetName = 'ClientCredentials')]
|
||||
[Parameter(Mandatory = $false, ParameterSetName = 'AuthorizationCode')]
|
||||
[string[]] $Scopes = @('okta.users.manage'),
|
||||
|
||||
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'ClientCredentials')]
|
||||
[Alias('jwk')]
|
||||
[string]
|
||||
$JsonWebKey
|
||||
)
|
||||
|
||||
try {
|
||||
$Script:OktaRevocationInfo = [PSCustomObject] @{
|
||||
ClientId = $ClientId
|
||||
RevocationToken = $null
|
||||
}
|
||||
switch ($PSCmdlet.ParameterSetName){
|
||||
'AuthorizationCode'
|
||||
{
|
||||
Write-Debug "No JWK found, assuming public client intended"
|
||||
$publicClientApp = [Microsoft.Identity.Client.PublicClientApplicationBuilder]::Create($ClientId).
|
||||
WithExperimentalFeatures().
|
||||
WithOidcAuthority("https://${tenant}/").
|
||||
WithRedirectUri("http://localhost:8080/login/callback").
|
||||
Build()
|
||||
|
||||
$Script:OktaToken = $publicClientApp.AcquireTokenInteractive($Scopes).ExecuteAsync().GetAwaiter().GetResult()
|
||||
if ($null -ne $Script:OktaToken)
|
||||
{
|
||||
Write-Host 'Okta access token successfully retrieved.'
|
||||
}
|
||||
}
|
||||
'ClientCredentials'
|
||||
{
|
||||
Write-Debug "JWK found, assuming confidential client intended"
|
||||
$jwk = [Microsoft.IdentityModel.Tokens.JsonWebKey]::new($JsonWebKey)
|
||||
$signingCredentials = [Microsoft.IdentityModel.Tokens.SigningCredentials]::new($jwk,'RS256')
|
||||
$issuer = $ClientId
|
||||
$audience = "https://${tenant}/oauth2/v1/token"
|
||||
$subject = [System.Security.Claims.ClaimsIdentity]::new()
|
||||
$subject.Claims.Add([System.Security.Claims.Claim]::new('sub',$ClientId))
|
||||
$notBefore = (Get-Date)
|
||||
$expires = (Get-Date).AddMinutes(60)
|
||||
$issuedAt = $notBefore
|
||||
|
||||
$tokenHandler = [System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler]::new()
|
||||
$securityToken = $tokenHandler.CreateJwtSecurityToken($issuer, $audience, $subject, $notBefore, $expires, $issuedAt, $signingCredentials)
|
||||
$revocationToken = $tokenHandler.CreateJwtSecurityToken($issuer, "https://${tenant}/oauth2/v1/revoke", $subject, $notBefore, $expires, $issuedAt, $signingCredentials)
|
||||
$assertion = $tokenHandler.WriteToken($securityToken)
|
||||
$Script:OktaRevocationInfo.RevocationToken = $tokenHandler.WriteToken($revocationToken)
|
||||
$confidentialClientApp = [Microsoft.Identity.Client.ConfidentialClientApplicationBuilder]::Create($ClientId).
|
||||
WithClientAssertion($assertion).
|
||||
WithOidcAuthority("https://${tenant}").
|
||||
Build()
|
||||
|
||||
$Script:OktaToken = $confidentialClientApp.AcquireTokenForClient($Scopes).ExecuteAsync().GetAwaiter().GetResult()
|
||||
if ($null -ne $Script:OktaToken -and $null -ne $Script:OktaRevocationInfo.RevocationToken)
|
||||
{
|
||||
Write-Host 'Okta access and revocation tokens successfully retrieved.'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
throw
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Revokes Okta access token.
|
||||
|
||||
.EXAMPLE
|
||||
PS \> Disconnect-Okta
|
||||
|
||||
.DESCRIPTION
|
||||
Revokes the Okta access token cached from the call to `Connect-Okta`.
|
||||
|
||||
.LINK
|
||||
https://developer.okta.com/docs/guides/revoke-tokens/main/
|
||||
|
||||
#>
|
||||
function Disconnect-Okta
|
||||
{
|
||||
if ($null -ne $Script:OktaToken)
|
||||
{
|
||||
[string] $revocationPath = "/oauth2/v1/revoke"
|
||||
|
||||
Write-Debug ('Revocation path: ' + $revocationPath)
|
||||
|
||||
$body = @{
|
||||
client_id = $Script:OktaRevocationInfo.ClientId
|
||||
token = $Script:OktaToken.AccessToken
|
||||
token_type_hint = "access_token"
|
||||
}
|
||||
|
||||
if ($null -ne $Script:OktaRevocationInfo.RevocationToken)
|
||||
{
|
||||
$body.Add('client_assertion_type',"urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
|
||||
$body.Add('client_assertion',$Script:OktaRevocationInfo.RevocationToken)
|
||||
}
|
||||
|
||||
Write-Debug ('Revocation payload: ' + ($body | ConvertTo-Json))
|
||||
|
||||
[string] $response = Invoke-OktaWebRequest -Uri $revocationPath `
|
||||
-ContentType "application/x-www-form-urlencoded" `
|
||||
-Body $body
|
||||
|
||||
$Script:OktaToken = $null
|
||||
$Script:OktaRevocationInfo.RevocationToken = $null
|
||||
|
||||
if ($response.Length -eq 0 -and $null -eq $Script:OktaToken)
|
||||
{
|
||||
Write-Host 'Okta access token successfully revoked.'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
New-Alias -Name Register-MgUserAuthenticationFido2Method -Value Register-Passkey
|
||||
|
||||
Export-ModuleMember -Function 'Get-PasskeyRegistrationOptions','New-Passkey','Register-Passkey' `
|
||||
Export-ModuleMember -Function 'Get-PasskeyRegistrationOptions','New-Passkey','Register-Passkey','Connect-Okta','Disconnect-Okta','Invoke-OktaWebRequest' `
|
||||
-Alias 'Register-MgUserAuthenticationFido2Method'
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
<helpItems schema="maml" xmlns="http://msh">
|
||||
<command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10" xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10" xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10" xmlns:MSHelp="http://msdn.microsoft.com/mshelp">
|
||||
<command:details>
|
||||
<command:name>Get-PasskeyRegistrationOptions</command:name>
|
||||
<command:verb>Get</command:verb>
|
||||
<command:noun>PasskeyRegistrationOptions</command:noun>
|
||||
<command:name>Connect-Okta</command:name>
|
||||
<command:verb>Connect</command:verb>
|
||||
<command:noun>Okta</command:noun>
|
||||
<maml:description>
|
||||
<maml:para>Retrieves creation options required to generate and register a Microsoft Entra ID-compatible passkey.</maml:para>
|
||||
<maml:para>{{ Fill in the Synopsis }}</maml:para>
|
||||
</maml:description>
|
||||
</command:details>
|
||||
<maml:description>
|
||||
@@ -14,11 +14,11 @@
|
||||
</maml:description>
|
||||
<command:syntax>
|
||||
<command:syntaxItem>
|
||||
<maml:name>Get-PasskeyRegistrationOptions</maml:name>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="1" aliases="none">
|
||||
<maml:name>UserId</maml:name>
|
||||
<maml:name>Connect-Okta</maml:name>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByValue)" position="named" aliases="none">
|
||||
<maml:name>ClientId</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>The unique identifier of user.</maml:para>
|
||||
<maml:para>{{ Fill ClientId Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">String</command:parameterValue>
|
||||
<dev:type>
|
||||
@@ -27,10 +27,167 @@
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="none">
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByValue)" position="named" aliases="jwk">
|
||||
<maml:name>JsonWebKey</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>{{ Fill JsonWebKey Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">ValidateNotNullOrEmptyAttribute</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>ValidateNotNullOrEmptyAttribute</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="proga">
|
||||
<maml:name>ProgressAction</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>{{ Fill ProgressAction Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">ActionPreference</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>ActionPreference</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
|
||||
<maml:name>Scopes</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>{{ Fill Scopes Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">String[]</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>String[]</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
|
||||
<maml:name>Tenant</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>{{ Fill Tenant Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">String</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>String</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
</command:syntaxItem>
|
||||
</command:syntax>
|
||||
<command:parameters>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByValue)" position="named" aliases="none">
|
||||
<maml:name>ClientId</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>{{ Fill ClientId Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">String</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>String</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByValue)" position="named" aliases="jwk">
|
||||
<maml:name>JsonWebKey</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>{{ Fill JsonWebKey Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">ValidateNotNullOrEmptyAttribute</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>ValidateNotNullOrEmptyAttribute</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="proga">
|
||||
<maml:name>ProgressAction</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>{{ Fill ProgressAction Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">ActionPreference</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>ActionPreference</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
|
||||
<maml:name>Scopes</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>{{ Fill Scopes Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">String[]</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>String[]</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
|
||||
<maml:name>Tenant</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>{{ Fill Tenant Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">String</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>String</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
</command:parameters>
|
||||
<command:inputTypes />
|
||||
<command:returnValues />
|
||||
<maml:alertSet>
|
||||
<maml:alert>
|
||||
<maml:para></maml:para>
|
||||
</maml:alert>
|
||||
</maml:alertSet>
|
||||
<command:examples>
|
||||
<command:example>
|
||||
<maml:title>-------------------------- Example 1 --------------------------</maml:title>
|
||||
<dev:code>PS C:\> {{ Add example code here }}</dev:code>
|
||||
<dev:remarks>
|
||||
<maml:para>{{ Add example description here }}</maml:para>
|
||||
</dev:remarks>
|
||||
</command:example>
|
||||
</command:examples>
|
||||
<command:relatedLinks />
|
||||
</command:command>
|
||||
<command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10" xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10" xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10" xmlns:MSHelp="http://msdn.microsoft.com/mshelp">
|
||||
<command:details>
|
||||
<command:name>Get-PasskeyRegistrationOptions</command:name>
|
||||
<command:verb>Get</command:verb>
|
||||
<command:noun>PasskeyRegistrationOptions</command:noun>
|
||||
<maml:description>
|
||||
<maml:para>Retrieves creation options required to generate and register a Microsoft Entra ID or Okta compatible passkey.</maml:para>
|
||||
</maml:description>
|
||||
</command:details>
|
||||
<maml:description>
|
||||
<maml:para></maml:para>
|
||||
</maml:description>
|
||||
<command:syntax>
|
||||
<command:syntaxItem>
|
||||
<maml:name>Get-PasskeyRegistrationOptions</maml:name>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="1" aliases="User">
|
||||
<maml:name>UserId</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>The unique identifier of user. For Entra ID, this is the object id (GUID) or UPN. For Okta, this is the unique identifier of Okta user.</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">String</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>String</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="Timeout">
|
||||
<maml:name>ChallengeTimeout</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>Overrides the timeout of the server-generated challenge returned in the request. The default value is 5 minutes, with the accepted range being between 5 minutes and 30 days.</maml:para>
|
||||
<maml:para>Overrides the timeout of the server-generated challenge returned in the request. For Entra ID, the default value is 5 minutes, with the accepted range being between 5 minutes and 30 days. For Okta, the default value is 300 seconds, with the accepted range being between 1 second and 1 day.</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">TimeSpan</command:parameterValue>
|
||||
<dev:type>
|
||||
@@ -39,13 +196,25 @@
|
||||
</dev:type>
|
||||
<dev:defaultValue>(New-TimeSpan -Minutes 5)</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="proga">
|
||||
<maml:name>ProgressAction</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>{{ Fill ProgressAction Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">ActionPreference</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>ActionPreference</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
</command:syntaxItem>
|
||||
</command:syntax>
|
||||
<command:parameters>
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="none">
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="Timeout">
|
||||
<maml:name>ChallengeTimeout</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>Overrides the timeout of the server-generated challenge returned in the request. The default value is 5 minutes, with the accepted range being between 5 minutes and 30 days.</maml:para>
|
||||
<maml:para>Overrides the timeout of the server-generated challenge returned in the request. For Entra ID, the default value is 5 minutes, with the accepted range being between 5 minutes and 30 days. For Okta, the default value is 300 seconds, with the accepted range being between 1 second and 1 day.</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">TimeSpan</command:parameterValue>
|
||||
<dev:type>
|
||||
@@ -54,10 +223,22 @@
|
||||
</dev:type>
|
||||
<dev:defaultValue>(New-TimeSpan -Minutes 5)</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="1" aliases="none">
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="proga">
|
||||
<maml:name>ProgressAction</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>{{ Fill ProgressAction Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">ActionPreference</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>ActionPreference</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="1" aliases="User">
|
||||
<maml:name>UserId</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>The unique identifier of user.</maml:para>
|
||||
<maml:para>The unique identifier of user. For Entra ID, this is the object id (GUID) or UPN. For Okta, this is the unique identifier of Okta user.</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">String</command:parameterValue>
|
||||
<dev:type>
|
||||
@@ -71,7 +252,7 @@
|
||||
<command:returnValues>
|
||||
<command:returnValue>
|
||||
<dev:type>
|
||||
<maml:name>DSInternals.Win32.WebAuthn.MicrosoftGraphWebauthnCredentialCreationOptions</maml:name>
|
||||
<maml:name>DSInternals.Win32.WebAuthn.WebauthnCredentialCreationOptions</maml:name>
|
||||
</dev:type>
|
||||
<maml:description>
|
||||
<maml:para></maml:para>
|
||||
@@ -80,22 +261,36 @@
|
||||
</command:returnValues>
|
||||
<maml:alertSet>
|
||||
<maml:alert>
|
||||
<maml:para>Self-service operations aren't supported. More info at https://learn.microsoft.com/en-us/graph/api/fido2authenticationmethod-creationoptions</maml:para>
|
||||
<maml:para>Self-service operations aren't supported. For the Okta token, you should not use SSWS but instead use a bearer token.</maml:para>
|
||||
</maml:alert>
|
||||
</maml:alertSet>
|
||||
<command:examples>
|
||||
<command:example>
|
||||
<maml:title>-------------------------- EXAMPLE 1 --------------------------</maml:title>
|
||||
<dev:code>Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com'</dev:code>
|
||||
<maml:title>--------------------- EXAMPLE 1 (Entra ID) ---------------------</maml:title>
|
||||
<dev:code>PS \> Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com'</dev:code>
|
||||
<dev:remarks>
|
||||
<maml:para></maml:para>
|
||||
</dev:remarks>
|
||||
</command:example>
|
||||
<command:example>
|
||||
<maml:title>-------------------------- EXAMPLE 2 --------------------------</maml:title>
|
||||
<dev:code>Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' -ChallengeTimeout (New-TimeSpan -Minutes 10)</dev:code>
|
||||
<maml:title>--------------------- EXAMPLE 2 (Entra ID) ---------------------</maml:title>
|
||||
<dev:code>PS \> Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' -ChallengeTimeout (New-TimeSpan -Minutes 10)</dev:code>
|
||||
<dev:remarks>
|
||||
<maml:para></maml:para>
|
||||
</dev:remarks>
|
||||
</command:example>
|
||||
<command:example>
|
||||
<maml:title>----------------------- EXAMPLE 3 (Okta) -----------------------</maml:title>
|
||||
<dev:code>PS \> Get-PasskeyRegistrationOptions -UserId 00eDuihq64pgP1gVD0x7 -Tenant example.okta.com -Token your_okta_token</dev:code>
|
||||
<dev:remarks>
|
||||
<maml:para></maml:para>
|
||||
</dev:remarks>
|
||||
</command:example>
|
||||
<command:example>
|
||||
<maml:title>----------------------- EXAMPLE 4 (Okta) -----------------------</maml:title>
|
||||
<dev:code>PS \> Get-PasskeyRegistrationOptions -UserId 00eDuihq64pgP1gVD0x7 -ChallengeTimeout (New-TimeSpan -Seconds 60) -Tenant example.okta.com -Token your_okta_token</dev:code>
|
||||
<dev:remarks>
|
||||
<maml:para></maml:para>
|
||||
</dev:remarks>
|
||||
@@ -106,6 +301,14 @@ Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' -ChallengeTimeout (N
|
||||
<maml:linkText>Online Version:</maml:linkText>
|
||||
<maml:uri>https://github.com/MichaelGrafnetter/webauthn-interop/tree/main/Documentation/PowerShell/Get-PasskeyRegistrationOptions.md</maml:uri>
|
||||
</maml:navigationLink>
|
||||
<maml:navigationLink>
|
||||
<maml:linkText>More info about Entra ID</maml:linkText>
|
||||
<maml:uri>https://learn.microsoft.com/en-us/graph/api/fido2authenticationmethod-creationoptions</maml:uri>
|
||||
</maml:navigationLink>
|
||||
<maml:navigationLink>
|
||||
<maml:linkText>More info about Okta</maml:linkText>
|
||||
<maml:uri>https://developer.okta.com/docs/api/openapi/okta-management/management/tag/UserFactor/#tag/UserFactor/operation/enrollFactor</maml:uri>
|
||||
</maml:navigationLink>
|
||||
</command:relatedLinks>
|
||||
</command:command>
|
||||
<command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10" xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10" xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10" xmlns:MSHelp="http://msdn.microsoft.com/mshelp">
|
||||
@@ -114,11 +317,11 @@ Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' -ChallengeTimeout (N
|
||||
<command:verb>New</command:verb>
|
||||
<command:noun>Passkey</command:noun>
|
||||
<maml:description>
|
||||
<maml:para>Creates a new Microsoft Entra ID-compatible passkey.</maml:para>
|
||||
<maml:para>Creates a new Microsoft Entra ID or Okta compatible passkey.</maml:para>
|
||||
</maml:description>
|
||||
</command:details>
|
||||
<maml:description>
|
||||
<maml:para>{{ Fill in the Description }}</maml:para>
|
||||
<maml:para>Takes the MicrosoftGraphWebauthnCredentialCreationOptions or OktaWebauthnCredentialCreationOptions object from Get-PasskeyRegistrationOptions and uses them to create a credential using the system dialogs.</maml:para>
|
||||
</maml:description>
|
||||
<command:syntax>
|
||||
<command:syntaxItem>
|
||||
@@ -126,19 +329,19 @@ Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' -ChallengeTimeout (N
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByValue)" position="1" aliases="none">
|
||||
<maml:name>Options</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>Options required to generate a Microsoft Entra ID-compatible passkey.</maml:para>
|
||||
<maml:para>Options required to generate a Microsoft Entra ID or Okta compatible passkey.</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">MicrosoftGraphWebauthnCredentialCreationOptions</command:parameterValue>
|
||||
<command:parameterValue required="true" variableLength="false">WebauthnCredentialCreationOptions</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>MicrosoftGraphWebauthnCredentialCreationOptions</maml:name>
|
||||
<maml:name>WebauthnCredentialCreationOptions</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="none">
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="none">
|
||||
<maml:name>DisplayName</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>Custom name given to the registered passkey.</maml:para>
|
||||
<maml:para>Custom name given to the Entra ID registered passkey.</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">String</command:parameterValue>
|
||||
<dev:type>
|
||||
@@ -147,13 +350,25 @@ Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' -ChallengeTimeout (N
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="proga">
|
||||
<maml:name>ProgressAction</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>{{ Fill ProgressAction Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">ActionPreference</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>ActionPreference</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
</command:syntaxItem>
|
||||
</command:syntax>
|
||||
<command:parameters>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="none">
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="none">
|
||||
<maml:name>DisplayName</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>Custom name given to the registered passkey.</maml:para>
|
||||
<maml:para>Custom name given to the Entra ID registered passkey.</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">String</command:parameterValue>
|
||||
<dev:type>
|
||||
@@ -165,11 +380,23 @@ Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' -ChallengeTimeout (N
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByValue)" position="1" aliases="none">
|
||||
<maml:name>Options</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>Options required to generate a Microsoft Entra ID-compatible passkey.</maml:para>
|
||||
<maml:para>Options required to generate a Microsoft Entra ID or Okta compatible passkey.</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">MicrosoftGraphWebauthnCredentialCreationOptions</command:parameterValue>
|
||||
<command:parameterValue required="true" variableLength="false">WebauthnCredentialCreationOptions</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>MicrosoftGraphWebauthnCredentialCreationOptions</maml:name>
|
||||
<maml:name>WebauthnCredentialCreationOptions</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="proga">
|
||||
<maml:name>ProgressAction</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>{{ Fill ProgressAction Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">ActionPreference</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>ActionPreference</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
@@ -179,7 +406,7 @@ Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' -ChallengeTimeout (N
|
||||
<command:returnValues>
|
||||
<command:returnValue>
|
||||
<dev:type>
|
||||
<maml:name>DSInternals.Win32.WebAuthn.MicrosoftGraphWebauthnAttestationResponse</maml:name>
|
||||
<maml:name>DSInternals.Win32.WebAuthn.WebauthnAttestationResponse</maml:name>
|
||||
</dev:type>
|
||||
<maml:description>
|
||||
<maml:para></maml:para>
|
||||
@@ -193,9 +420,23 @@ Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' -ChallengeTimeout (N
|
||||
</maml:alertSet>
|
||||
<command:examples>
|
||||
<command:example>
|
||||
<maml:title>-------------------------- EXAMPLE 1 --------------------------</maml:title>
|
||||
<dev:code>Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' | New-Passkey -DisplayName 'YubiKey 5 Nano' | Register-Passkey -UserId 'AdeleV@contoso.com'
|
||||
Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'</dev:code>
|
||||
<maml:title>--------------------- EXAMPLE 1 (Entra ID) ---------------------</maml:title>
|
||||
<dev:code>PS \> Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' | New-Passkey -DisplayName 'YubiKey 5 Nano' | Register-Passkey -UserId 'AdeleV@contoso.com'</dev:code>
|
||||
<dev:remarks>
|
||||
<maml:para></maml:para>
|
||||
</dev:remarks>
|
||||
</command:example>
|
||||
<command:example>
|
||||
<maml:title>----------------------- EXAMPLE 2 (Okta) -----------------------</maml:title>
|
||||
<dev:code>PS \> New-Passkey -Options $options</dev:code>
|
||||
<dev:remarks>
|
||||
<maml:para></maml:para>
|
||||
</dev:remarks>
|
||||
</command:example>
|
||||
<command:example>
|
||||
<maml:title>----------------------- EXAMPLE 3 (Okta) -----------------------</maml:title>
|
||||
<dev:code>PS \> Get-PasskeyRegistrationOptions -UserId 00eDuihq64pgP1gVD0x7 -Tenant example.okta.com -Token your_okta_token | New-Passkey</dev:code>
|
||||
<dev:remarks>
|
||||
<maml:para></maml:para>
|
||||
</dev:remarks>
|
||||
@@ -206,39 +447,43 @@ Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'</dev:code>
|
||||
<maml:linkText>Online Version:</maml:linkText>
|
||||
<maml:uri>https://github.com/MichaelGrafnetter/webauthn-interop/tree/main/Documentation/PowerShell/New-Passkey.md</maml:uri>
|
||||
</maml:navigationLink>
|
||||
<maml:navigationLink>
|
||||
<maml:linkText>Microsoft WebAuthn portal</maml:linkText>
|
||||
<maml:uri>https://learn.microsoft.com/en-us/windows/win32/webauthn/-webauthn-portal</maml:uri>
|
||||
</maml:navigationLink>
|
||||
</command:relatedLinks>
|
||||
</command:command>
|
||||
<command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10" xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10" xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10" xmlns:MSHelp="http://msdn.microsoft.com/mshelp">
|
||||
<command:details>
|
||||
<command:name>Register-Passkey</command:name>
|
||||
<command:verb>Register</command:verb>
|
||||
<command:name>New-Passkey</command:name>
|
||||
<command:verb>New</command:verb>
|
||||
<command:noun>Passkey</command:noun>
|
||||
<maml:description>
|
||||
<maml:para>Registers a new passkey in Microsoft Entra ID.</maml:para>
|
||||
<maml:para>Creates a new Microsoft Entra ID or Okta compatible passkey.</maml:para>
|
||||
</maml:description>
|
||||
</command:details>
|
||||
<maml:description>
|
||||
<maml:para>{{ Fill in the Description }}</maml:para>
|
||||
<maml:para>Takes the MicrosoftGraphWebauthnCredentialCreationOptions or OktaWebauthnCredentialCreationOptions object from Get-PasskeyRegistrationOptions and uses them to create a credential using the system dialogs.</maml:para>
|
||||
</maml:description>
|
||||
<command:syntax>
|
||||
<command:syntaxItem>
|
||||
<maml:name>Register-Passkey</maml:name>
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
|
||||
<maml:name>ChallengeTimeout</maml:name>
|
||||
<maml:name>New-Passkey</maml:name>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByValue)" position="1" aliases="none">
|
||||
<maml:name>Options</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>Overrides the timeout of the server-generated challenge returned in the request. The default value is 5 minutes, with the accepted range being between 5 minutes and 30 days.</maml:para>
|
||||
<maml:para>Options required to generate a Microsoft Entra ID or Okta compatible passkey.</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">TimeSpan</command:parameterValue>
|
||||
<command:parameterValue required="true" variableLength="false">WebauthnCredentialCreationOptions</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>TimeSpan</maml:name>
|
||||
<maml:name>WebauthnCredentialCreationOptions</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>(New-TimeSpan -Minutes 5)</dev:defaultValue>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="none">
|
||||
<maml:name>DisplayName</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>Custom name given to the registered passkey.</maml:para>
|
||||
<maml:para>Custom name given to the Entra ID registered passkey.</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">String</command:parameterValue>
|
||||
<dev:type>
|
||||
@@ -247,41 +492,14 @@ Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'</dev:code>
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
|
||||
<maml:name>UserId</maml:name>
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="proga">
|
||||
<maml:name>ProgressAction</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>The unique identifier of user.</maml:para>
|
||||
<maml:para>{{ Fill ProgressAction Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">String</command:parameterValue>
|
||||
<command:parameterValue required="true" variableLength="false">ActionPreference</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>String</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
</command:syntaxItem>
|
||||
<command:syntaxItem>
|
||||
<maml:name>Register-Passkey</maml:name>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByValue)" position="named" aliases="none">
|
||||
<maml:name>Passkey</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>The passkey to be registered.</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">MicrosoftGraphWebauthnAttestationResponse</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>MicrosoftGraphWebauthnAttestationResponse</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
|
||||
<maml:name>UserId</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>The unique identifier of user.</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">String</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>String</maml:name>
|
||||
<maml:name>ActionPreference</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
@@ -289,22 +507,10 @@ Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'</dev:code>
|
||||
</command:syntaxItem>
|
||||
</command:syntax>
|
||||
<command:parameters>
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
|
||||
<maml:name>ChallengeTimeout</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>Overrides the timeout of the server-generated challenge returned in the request. The default value is 5 minutes, with the accepted range being between 5 minutes and 30 days.</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">TimeSpan</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>TimeSpan</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>(New-TimeSpan -Minutes 5)</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="none">
|
||||
<maml:name>DisplayName</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>Custom name given to the registered passkey.</maml:para>
|
||||
<maml:para>Custom name given to the Entra ID registered passkey.</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">String</command:parameterValue>
|
||||
<dev:type>
|
||||
@@ -313,26 +519,26 @@ Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'</dev:code>
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByValue)" position="named" aliases="none">
|
||||
<maml:name>Passkey</maml:name>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByValue)" position="1" aliases="none">
|
||||
<maml:name>Options</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>The passkey to be registered.</maml:para>
|
||||
<maml:para>Options required to generate a Microsoft Entra ID or Okta compatible passkey.</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">MicrosoftGraphWebauthnAttestationResponse</command:parameterValue>
|
||||
<command:parameterValue required="true" variableLength="false">WebauthnCredentialCreationOptions</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>MicrosoftGraphWebauthnAttestationResponse</maml:name>
|
||||
<maml:name>WebauthnCredentialCreationOptions</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
</command:parameter>
|
||||
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
|
||||
<maml:name>UserId</maml:name>
|
||||
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="proga">
|
||||
<maml:name>ProgressAction</maml:name>
|
||||
<maml:description>
|
||||
<maml:para>The unique identifier of user.</maml:para>
|
||||
<maml:para>{{ Fill ProgressAction Description }}</maml:para>
|
||||
</maml:description>
|
||||
<command:parameterValue required="true" variableLength="false">String</command:parameterValue>
|
||||
<command:parameterValue required="true" variableLength="false">ActionPreference</command:parameterValue>
|
||||
<dev:type>
|
||||
<maml:name>String</maml:name>
|
||||
<maml:name>ActionPreference</maml:name>
|
||||
<maml:uri />
|
||||
</dev:type>
|
||||
<dev:defaultValue>None</dev:defaultValue>
|
||||
@@ -342,7 +548,7 @@ Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'</dev:code>
|
||||
<command:returnValues>
|
||||
<command:returnValue>
|
||||
<dev:type>
|
||||
<maml:name>Microsoft.Graph.PowerShell.Models.MicrosoftGraphFido2AuthenticationMethod</maml:name>
|
||||
<maml:name>DSInternals.Win32.WebAuthn.WebauthnAttestationResponse</maml:name>
|
||||
</dev:type>
|
||||
<maml:description>
|
||||
<maml:para></maml:para>
|
||||
@@ -351,30 +557,28 @@ Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'</dev:code>
|
||||
</command:returnValues>
|
||||
<maml:alertSet>
|
||||
<maml:alert>
|
||||
<maml:para>More info at https://learn.microsoft.com/en-us/graph/api/authentication-post-fido2methods</maml:para>
|
||||
<maml:para></maml:para>
|
||||
</maml:alert>
|
||||
</maml:alertSet>
|
||||
<command:examples>
|
||||
<command:example>
|
||||
<maml:title>-------------------------- EXAMPLE 1 --------------------------</maml:title>
|
||||
<dev:code>Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
Register-Passkey -UserId 'AdeleV@contoso.com' -DisplayName 'YubiKey 5 Nano'</dev:code>
|
||||
<maml:title>--------------------- EXAMPLE 1 (Entra ID) ---------------------</maml:title>
|
||||
<dev:code>PS \> Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
PS \> Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' | New-Passkey -DisplayName 'YubiKey 5 Nano' | Register-Passkey -UserId 'AdeleV@contoso.com'</dev:code>
|
||||
<dev:remarks>
|
||||
<maml:para></maml:para>
|
||||
</dev:remarks>
|
||||
</command:example>
|
||||
<command:example>
|
||||
<maml:title>-------------------------- EXAMPLE 2 --------------------------</maml:title>
|
||||
<dev:code>Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
Register-Passkey -UserId 'AdeleV@contoso.com' -DisplayName 'YubiKey 5 Nano' -ChallengeTimeout (New-TimeSpan -Minutes 10)</dev:code>
|
||||
<maml:title>----------------------- EXAMPLE 2 (Okta) -----------------------</maml:title>
|
||||
<dev:code>PS \> New-Passkey -Options $options</dev:code>
|
||||
<dev:remarks>
|
||||
<maml:para></maml:para>
|
||||
</dev:remarks>
|
||||
</command:example>
|
||||
<command:example>
|
||||
<maml:title>-------------------------- EXAMPLE 3 --------------------------</maml:title>
|
||||
<dev:code>Connect-MgGraph -Scopes 'UserAuthenticationMethod.ReadWrite.All'
|
||||
Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' | New-Passkey -DisplayName 'YubiKey 5 Nano' | Register-Passkey -UserId 'AdeleV@contoso.com'</dev:code>
|
||||
<maml:title>----------------------- EXAMPLE 3 (Okta) -----------------------</maml:title>
|
||||
<dev:code>PS \> Get-PasskeyRegistrationOptions -UserId 00eDuihq64pgP1gVD0x7 -Tenant example.okta.com -Token your_okta_token | New-Passkey</dev:code>
|
||||
<dev:remarks>
|
||||
<maml:para></maml:para>
|
||||
</dev:remarks>
|
||||
@@ -383,7 +587,11 @@ Get-PasskeyRegistrationOptions -UserId 'AdeleV@contoso.com' | New-Passkey -Displ
|
||||
<command:relatedLinks>
|
||||
<maml:navigationLink>
|
||||
<maml:linkText>Online Version:</maml:linkText>
|
||||
<maml:uri>https://github.com/MichaelGrafnetter/webauthn-interop/tree/main/Documentation/PowerShell/Register-Passkey.md</maml:uri>
|
||||
<maml:uri>https://github.com/MichaelGrafnetter/webauthn-interop/tree/main/Documentation/PowerShell/New-Passkey.md</maml:uri>
|
||||
</maml:navigationLink>
|
||||
<maml:navigationLink>
|
||||
<maml:linkText>Microsoft WebAuthn portal</maml:linkText>
|
||||
<maml:uri>https://learn.microsoft.com/en-us/windows/win32/webauthn/-webauthn-portal</maml:uri>
|
||||
</maml:navigationLink>
|
||||
</command:relatedLinks>
|
||||
</command:command>
|
||||
|
||||
@@ -66,16 +66,24 @@
|
||||
"System.Diagnostics.DiagnosticSource": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Bcl.AsyncInterfaces": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.CodeCoverage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "17.10.0",
|
||||
"contentHash": "yC7oSlnR54XO5kOuHlVOKtxomNNN1BWXX8lK1G2jaPXT9sUok7kCOoA4Pgs0qyFaCtMrNsprztYMeoEGqCm4uA=="
|
||||
},
|
||||
"Microsoft.CSharp": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "kaj6Wb4qoMuH3HySFJhxwQfe8R/sJsNJnANrvv8WdFPMoNbKY5htfNscv+LHCu5ipz+49m2e+WQXpLXr9XYemQ=="
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
@@ -135,27 +143,44 @@
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.17.0",
|
||||
"contentHash": "I3cSVE185qF3a222/iQIdmBFhrhZBtz7wZ1RUUbMuHC1un79XCI7vggbWdmbqIttFcUoeziemadO6t+3FLjcSA==",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Tokens": "6.17.0"
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.17.0",
|
||||
"contentHash": "Ix6/CMLDoo939NDf1ARDuGK6YERY7pAX9WYbfwb4gZqx7r52unMFIykJk+zlEBX7jjtbDz/0uzikQFvheV9KsQ=="
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.17.0",
|
||||
"contentHash": "mhOe+d9BQg5U45TkTCyXAFOjl7RvwaFj6v9qo8b+WFolkuGsfjSFfQ+WI9D3ho9sD/fK75gvL4JptmjLzyUPkw==",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.CSharp": "4.5.0",
|
||||
"Microsoft.IdentityModel.Logging": "6.17.0",
|
||||
"System.Security.Cryptography.Cng": "4.5.0"
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Testing.Extensions.Telemetry": {
|
||||
@@ -251,8 +276,8 @@
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
@@ -269,11 +294,11 @@
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.17.0",
|
||||
"contentHash": "G3rY4WLr54Mo+97+AEq0ANpiKvW7E8Qu5bKWfVMa7rkyJtvrOxUqp/OLqrGw/6JDbD5GlxnAtFKukGteUuB0rQ==",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "6.17.0",
|
||||
"Microsoft.IdentityModel.Tokens": "6.17.0"
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Reflection.Metadata": {
|
||||
@@ -310,7 +335,9 @@
|
||||
"dsinternals.win32.webauthn": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Identity.Client": "[4.66.1, )",
|
||||
"PeterO.Cbor": "[4.5.3, )",
|
||||
"System.IdentityModel.Tokens.Jwt": "[8.2.0, )",
|
||||
"System.Security.Cryptography.Cng": "[5.0.0, )",
|
||||
"System.Text.Json": "[8.0.5, )"
|
||||
}
|
||||
@@ -318,7 +345,7 @@
|
||||
"dsinternals.win32.webauthn.adapter": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"DSInternals.Win32.WebAuthn": "[1.0.3, )",
|
||||
"DSInternals.Win32.WebAuthn": "[1.0.4, )",
|
||||
"Fido2.Models": "[3.0.1, )",
|
||||
"PeterO.Cbor": "[4.5.3, )",
|
||||
"System.Security.Cryptography.Cng": "[5.0.0, )"
|
||||
|
||||
@@ -35,6 +35,62 @@
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.CSharp": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "kaj6Wb4qoMuH3HySFJhxwQfe8R/sJsNJnANrvv8WdFPMoNbKY5htfNscv+LHCu5ipz+49m2e+WQXpLXr9XYemQ=="
|
||||
},
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.CSharp": "4.5.0",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0",
|
||||
"System.Security.Cryptography.Cng": "4.5.0",
|
||||
"System.Text.Json": "8.0.5"
|
||||
}
|
||||
},
|
||||
"Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "12.0.3",
|
||||
@@ -55,11 +111,29 @@
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.4",
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Formats.Asn1": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "MTvUIktmemNB+El0Fgw9egyqT9AYSIk6DTJeoDSpc3GIHxHCMo8COqkWT1mptX5tZ1SlQ6HJZ0OsSvMth1c12w=="
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.5",
|
||||
@@ -101,7 +175,9 @@
|
||||
"dsinternals.win32.webauthn": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Identity.Client": "[4.66.1, )",
|
||||
"PeterO.Cbor": "[4.5.3, )",
|
||||
"System.IdentityModel.Tokens.Jwt": "[8.2.0, )",
|
||||
"System.Security.Cryptography.Cng": "[5.0.0, )",
|
||||
"System.Text.Json": "[8.0.5, )"
|
||||
}
|
||||
@@ -135,6 +211,57 @@
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "8.0.0",
|
||||
"System.ValueTuple": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0",
|
||||
"System.Memory": "4.5.5",
|
||||
"System.Text.Json": "8.0.5"
|
||||
}
|
||||
},
|
||||
"Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "12.0.3",
|
||||
@@ -155,6 +282,24 @@
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.4",
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.5",
|
||||
@@ -215,7 +360,9 @@
|
||||
"dsinternals.win32.webauthn": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Identity.Client": "[4.66.1, )",
|
||||
"PeterO.Cbor": "[4.5.3, )",
|
||||
"System.IdentityModel.Tokens.Jwt": "[8.2.0, )",
|
||||
"System.Text.Json": "[8.0.5, )"
|
||||
}
|
||||
}
|
||||
@@ -248,6 +395,57 @@
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "8.0.0",
|
||||
"System.ValueTuple": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0",
|
||||
"System.Memory": "4.5.5",
|
||||
"System.Text.Json": "8.0.5"
|
||||
}
|
||||
},
|
||||
"Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "12.0.3",
|
||||
@@ -268,6 +466,24 @@
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.4",
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.5",
|
||||
@@ -328,7 +544,9 @@
|
||||
"dsinternals.win32.webauthn": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Identity.Client": "[4.66.1, )",
|
||||
"PeterO.Cbor": "[4.5.3, )",
|
||||
"System.IdentityModel.Tokens.Jwt": "[8.2.0, )",
|
||||
"System.Text.Json": "[8.0.5, )"
|
||||
}
|
||||
}
|
||||
@@ -367,6 +585,62 @@
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.CSharp": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "kaj6Wb4qoMuH3HySFJhxwQfe8R/sJsNJnANrvv8WdFPMoNbKY5htfNscv+LHCu5ipz+49m2e+WQXpLXr9XYemQ=="
|
||||
},
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.CSharp": "4.5.0",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0",
|
||||
"System.Security.Cryptography.Cng": "4.5.0",
|
||||
"System.Text.Json": "8.0.5"
|
||||
}
|
||||
},
|
||||
"Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "12.0.3",
|
||||
@@ -387,11 +661,28 @@
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Formats.Asn1": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "MTvUIktmemNB+El0Fgw9egyqT9AYSIk6DTJeoDSpc3GIHxHCMo8COqkWT1mptX5tZ1SlQ6HJZ0OsSvMth1c12w=="
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.5",
|
||||
@@ -433,7 +724,9 @@
|
||||
"dsinternals.win32.webauthn": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Identity.Client": "[4.66.1, )",
|
||||
"PeterO.Cbor": "[4.5.3, )",
|
||||
"System.IdentityModel.Tokens.Jwt": "[8.2.0, )",
|
||||
"System.Security.Cryptography.Cng": "[5.0.0, )",
|
||||
"System.Text.Json": "[8.0.5, )"
|
||||
}
|
||||
@@ -465,6 +758,59 @@
|
||||
"System.Formats.Asn1": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Bcl.AsyncInterfaces": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0"
|
||||
}
|
||||
},
|
||||
"PeterO.Numbers": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.8.2",
|
||||
@@ -475,11 +821,28 @@
|
||||
"resolved": "1.0.0",
|
||||
"contentHash": "fpRTBsYACMp7NvTECauYRomubWTC3vUNw4hMXdIedP8ctBGK6tea9HOJwE+qVzis6MZYkL3LIs8qeY3rc6Jdlw=="
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Formats.Asn1": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "MTvUIktmemNB+El0Fgw9egyqT9AYSIk6DTJeoDSpc3GIHxHCMo8COqkWT1mptX5tZ1SlQ6HJZ0OsSvMth1c12w=="
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
@@ -505,7 +868,9 @@
|
||||
"dsinternals.win32.webauthn": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Identity.Client": "[4.66.1, )",
|
||||
"PeterO.Cbor": "[4.5.3, )",
|
||||
"System.IdentityModel.Tokens.Jwt": "[8.2.0, )",
|
||||
"System.Security.Cryptography.Cng": "[5.0.0, )",
|
||||
"System.Text.Json": "[8.0.5, )"
|
||||
}
|
||||
@@ -537,6 +902,59 @@
|
||||
"System.Formats.Asn1": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Bcl.AsyncInterfaces": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0"
|
||||
}
|
||||
},
|
||||
"PeterO.Numbers": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.8.2",
|
||||
@@ -547,11 +965,33 @@
|
||||
"resolved": "1.0.0",
|
||||
"contentHash": "fpRTBsYACMp7NvTECauYRomubWTC3vUNw4hMXdIedP8ctBGK6tea9HOJwE+qVzis6MZYkL3LIs8qeY3rc6Jdlw=="
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Formats.Asn1": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "MTvUIktmemNB+El0Fgw9egyqT9AYSIk6DTJeoDSpc3GIHxHCMo8COqkWT1mptX5tZ1SlQ6HJZ0OsSvMth1c12w=="
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
|
||||
},
|
||||
"System.Text.Encodings.Web": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
@@ -568,7 +1008,9 @@
|
||||
"dsinternals.win32.webauthn": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Identity.Client": "[4.66.1, )",
|
||||
"PeterO.Cbor": "[4.5.3, )",
|
||||
"System.IdentityModel.Tokens.Jwt": "[8.2.0, )",
|
||||
"System.Security.Cryptography.Cng": "[5.0.0, )",
|
||||
"System.Text.Json": "[8.0.5, )"
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Fido2.Models" Version="3.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.5.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.5.1" />
|
||||
|
||||
+1
@@ -1,4 +1,5 @@
|
||||
using System.Text.Json;
|
||||
using DSInternals.Win32.WebAuthn.EntraID;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace DSInternals.Win32.WebAuthn.Tests
|
||||
|
||||
@@ -1,13 +1,304 @@
|
||||
using System.Text.Json;
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Buffers.Binary;
|
||||
using System.Formats.Asn1;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using DSInternals.Win32.WebAuthn.EntraID;
|
||||
using DSInternals.Win32.WebAuthn.FIDO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using PeterO.Cbor;
|
||||
using DSInternals.Win32.WebAuthn.Okta;
|
||||
|
||||
namespace DSInternals.Win32.WebAuthn.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public class PasskeyFactory
|
||||
{
|
||||
internal WebauthnCredentialCreationOptions _options;
|
||||
internal CBORObject _attestationObject => CBORObject.NewMap().
|
||||
Add("fmt", "packed").
|
||||
Add("authData", _authData).
|
||||
Add("attStmt", CBORObject.NewMap().
|
||||
Add("alg", _alg).
|
||||
Add("sig", _sig).
|
||||
Add("x5c", _x5c)
|
||||
);
|
||||
|
||||
internal COSE.Algorithm _alg;
|
||||
internal COSE.KeyType _kty
|
||||
{
|
||||
get
|
||||
{
|
||||
return _alg switch
|
||||
{
|
||||
COSE.Algorithm.RS1 or COSE.Algorithm.RS256 or COSE.Algorithm.RS384 or COSE.Algorithm.RS512 or COSE.Algorithm.PS256 or COSE.Algorithm.PS384 or COSE.Algorithm.PS512 => COSE.KeyType.RSA,
|
||||
COSE.Algorithm.ES256 or COSE.Algorithm.ES384 or COSE.Algorithm.ES512 => COSE.KeyType.EC2,
|
||||
COSE.Algorithm.EdDSA => COSE.KeyType.OKP,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(_alg)),
|
||||
};
|
||||
}
|
||||
}
|
||||
internal COSE.EllipticCurve _crv
|
||||
{
|
||||
get
|
||||
{
|
||||
return _alg switch
|
||||
{
|
||||
COSE.Algorithm.ES256 => COSE.EllipticCurve.P256,
|
||||
COSE.Algorithm.ES384 => COSE.EllipticCurve.P384,
|
||||
COSE.Algorithm.ES512 => COSE.EllipticCurve.P521,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(_alg)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal RSASignaturePadding _padding
|
||||
{
|
||||
get
|
||||
{
|
||||
return _alg switch
|
||||
{
|
||||
COSE.Algorithm.RS1 or COSE.Algorithm.RS256 or COSE.Algorithm.RS384 or COSE.Algorithm.RS512 => RSASignaturePadding.Pkcs1,
|
||||
COSE.Algorithm.PS256 or COSE.Algorithm.PS384 or COSE.Algorithm.PS512 => RSASignaturePadding.Pss,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(_alg)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal CredentialPublicKey _credentialPublicKey;
|
||||
|
||||
internal string _rp => _options.PublicKeyOptions.RelyingParty.Id;
|
||||
internal string _origin => new UriBuilder("https", _options.PublicKeyOptions.RelyingParty.Id).ToString();
|
||||
internal byte[] _challenge => _options.PublicKeyOptions.Challenge;
|
||||
internal CertificateRequest _certReq;
|
||||
internal static X500DistinguishedName _rootDN = new X500DistinguishedName("CN=Testing, O=DSInternals, OU=Passkeys, C=US");
|
||||
internal static byte[] _asnEncodedAaguid = [0x04, 0x10, 0x44, 0x53, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x61, 0x6C, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00,];
|
||||
internal byte[] _sig;
|
||||
internal CBORObject _x5c
|
||||
{
|
||||
get
|
||||
{
|
||||
_certReq.CertificateExtensions.Add(new X509BasicConstraintsExtension(true, true, 2, false));
|
||||
_certReq.CertificateExtensions.Add(new X509Extension(new Oid("1.3.6.1.4.1.45724.1.1.4"), _asnEncodedAaguid, true));
|
||||
using X509Certificate2 root = _certReq.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(2));
|
||||
return CBORObject.NewArray().Add(root.RawData);
|
||||
}
|
||||
}
|
||||
|
||||
internal byte[] _rpIdHash => SHA256.HashData(Encoding.UTF8.GetBytes(_rp));
|
||||
internal byte[] _clientDataJson
|
||||
{
|
||||
get
|
||||
{
|
||||
return JsonSerializer.SerializeToUtf8Bytes(new CollectedClientData()
|
||||
{
|
||||
Type = "webauthn.create",
|
||||
Challenge = _challenge,
|
||||
Origin = _origin
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
internal byte[] _clientDataHash => SHA256.HashData(_clientDataJson);
|
||||
|
||||
internal byte[] _attToBeSigned {
|
||||
get
|
||||
{
|
||||
byte[] toBeSigned = new byte[_authData.Length + _clientDataHash.Length];
|
||||
_authData.CopyTo(toBeSigned, 0);
|
||||
_clientDataHash.CopyTo(toBeSigned, _authData.Length);
|
||||
return toBeSigned;
|
||||
}
|
||||
}
|
||||
|
||||
internal static byte[] HashData(HashAlgorithmName hashName, ReadOnlySpan<byte> data)
|
||||
{
|
||||
return hashName.Name switch
|
||||
{
|
||||
"SHA1" => SHA1.HashData(data),
|
||||
"SHA256" or "HS256" or "RS256" or "ES256" or "PS256" => SHA256.HashData(data),
|
||||
"SHA384" or "HS384" or "RS384" or "ES384" or "PS384" => SHA384.HashData(data),
|
||||
"SHA512" or "HS512" or "RS512" or "ES512" or "PS512" => SHA512.HashData(data),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(hashName)),
|
||||
};
|
||||
}
|
||||
|
||||
internal byte[] _attToBeSignedHash(HashAlgorithmName alg)
|
||||
{
|
||||
return HashData(alg, _attToBeSigned);
|
||||
}
|
||||
|
||||
internal byte[] _credentialID;
|
||||
internal const AuthenticatorFlags _flags = AuthenticatorFlags.AttestationData | AuthenticatorFlags.ExtensionData | AuthenticatorFlags.UserPresent | AuthenticatorFlags.UserVerified;
|
||||
internal ushort _signCount;
|
||||
internal static byte[] _aaguid = [0x44, 0x53, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x61, 0x6C, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00,];
|
||||
|
||||
internal byte[] _authData
|
||||
{
|
||||
get
|
||||
{
|
||||
var writer = new ArrayBufferWriter<byte>(512);
|
||||
writer.Write(_rpIdHash);
|
||||
writer.Write(stackalloc byte[1] { (byte)_flags });
|
||||
var buffer = writer.GetSpan(4);
|
||||
BinaryPrimitives.WriteUInt32BigEndian(buffer, _signCount);
|
||||
writer.Advance(4);
|
||||
writer.Write(_acd);
|
||||
CBORObject exts = CBORObject.NewMap().Add("testing", true);
|
||||
writer.Write(exts.EncodeToBytes());
|
||||
return writer.WrittenSpan.ToArray();
|
||||
}
|
||||
}
|
||||
internal byte[] _acd
|
||||
{
|
||||
get
|
||||
{
|
||||
var writer = new ArrayBufferWriter<byte>(16 + 2 + _credentialID.Length + _credentialPublicKey.GetBytes().Length);
|
||||
|
||||
writer.Write(_aaguid);
|
||||
|
||||
// Write the length of credential ID, as big endian bytes of a 16-bit unsigned integer
|
||||
var credentialIDLen = (ushort)_credentialID.Length;
|
||||
var credentialIDLenBytes = BitConverter.GetBytes(credentialIDLen);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
Array.Reverse(credentialIDLenBytes);
|
||||
}
|
||||
|
||||
writer.Write(credentialIDLenBytes);
|
||||
// Write CredentialID bytes
|
||||
writer.Write(_credentialID);
|
||||
|
||||
// Write credential public key bytes
|
||||
writer.Write(_credentialPublicKey.GetBytes());
|
||||
return writer.WrittenSpan.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
internal static HashAlgorithmName HashAlgFromCOSEAlg(COSE.Algorithm alg)
|
||||
{
|
||||
return alg switch
|
||||
{
|
||||
COSE.Algorithm.RS1 => HashAlgorithmName.SHA1,
|
||||
COSE.Algorithm.ES256 => HashAlgorithmName.SHA256,
|
||||
COSE.Algorithm.ES384 => HashAlgorithmName.SHA384,
|
||||
COSE.Algorithm.ES512 => HashAlgorithmName.SHA512,
|
||||
COSE.Algorithm.PS256 => HashAlgorithmName.SHA256,
|
||||
COSE.Algorithm.PS384 => HashAlgorithmName.SHA384,
|
||||
COSE.Algorithm.PS512 => HashAlgorithmName.SHA512,
|
||||
COSE.Algorithm.RS256 => HashAlgorithmName.SHA256,
|
||||
COSE.Algorithm.RS384 => HashAlgorithmName.SHA384,
|
||||
COSE.Algorithm.RS512 => HashAlgorithmName.SHA512,
|
||||
(COSE.Algorithm)4 => HashAlgorithmName.SHA1,
|
||||
(COSE.Algorithm)11 => HashAlgorithmName.SHA256,
|
||||
(COSE.Algorithm)12 => HashAlgorithmName.SHA384,
|
||||
(COSE.Algorithm)13 => HashAlgorithmName.SHA512,
|
||||
COSE.Algorithm.EdDSA => HashAlgorithmName.SHA512,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(alg)),
|
||||
};
|
||||
}
|
||||
|
||||
internal void MakeCredentialPublicKey()
|
||||
{
|
||||
var cpk = CBORObject.NewMap().
|
||||
Add(COSE.KeyCommonParameter.KeyType, _kty).
|
||||
Add(COSE.KeyCommonParameter.Alg, _alg);
|
||||
|
||||
switch (_kty)
|
||||
{
|
||||
case COSE.KeyType.EC2:
|
||||
ECCurve curve = _crv switch
|
||||
{
|
||||
COSE.EllipticCurve.P256 => ECCurve.NamedCurves.nistP256,
|
||||
COSE.EllipticCurve.P384 => ECCurve.NamedCurves.nistP384,
|
||||
COSE.EllipticCurve.P521 => ECCurve.NamedCurves.nistP521,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(_crv)),
|
||||
};
|
||||
|
||||
var ecdsa = ECDsa.Create(curve);
|
||||
_certReq = new CertificateRequest(_rootDN, ecdsa, HashAlgorithmName.SHA256);
|
||||
var ecparams = ecdsa.ExportParameters(true);
|
||||
|
||||
cpk.Add(COSE.KeyTypeParameter.X, ecparams.Q.X);
|
||||
cpk.Add(COSE.KeyTypeParameter.Y, ecparams.Q.Y);
|
||||
cpk.Add((int)COSE.KeyTypeParameter.Crv, (int)_crv);
|
||||
_credentialPublicKey = new CredentialPublicKey(cpk);
|
||||
var sig = ecdsa.SignData(_attToBeSigned, HashAlgFromCOSEAlg(_alg));
|
||||
var coefficientSize = (int)Math.Ceiling((decimal)ecdsa.KeySize / 8);
|
||||
var r = sig[0..coefficientSize];
|
||||
var s = sig[(sig.Length - coefficientSize)..sig.Length];
|
||||
|
||||
var asnwriter = new AsnWriter(AsnEncodingRules.BER);
|
||||
ReadOnlySpan<byte> zero = new byte[1] { 0 };
|
||||
using (asnwriter.PushSequence())
|
||||
{
|
||||
asnwriter.WriteIntegerUnsigned(r);
|
||||
asnwriter.WriteIntegerUnsigned(s);
|
||||
}
|
||||
_sig = asnwriter.Encode();
|
||||
break;
|
||||
case COSE.KeyType.RSA:
|
||||
var rsa = RSA.Create();
|
||||
|
||||
var padding = _alg switch // https://www.iana.org/assignments/cose/cose.xhtml#algorithms
|
||||
{
|
||||
COSE.Algorithm.RS1 or COSE.Algorithm.RS256 or COSE.Algorithm.RS384 or COSE.Algorithm.RS512 => RSASignaturePadding.Pkcs1,
|
||||
COSE.Algorithm.PS256 or COSE.Algorithm.PS384 or COSE.Algorithm.PS512 => RSASignaturePadding.Pss,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(_alg)),
|
||||
};
|
||||
_certReq = new CertificateRequest(_rootDN, rsa, HashAlgorithmName.SHA256, padding);
|
||||
var rsaparams = rsa.ExportParameters(true);
|
||||
cpk.Add(COSE.KeyTypeParameter.N, rsaparams.Modulus);
|
||||
cpk.Add(COSE.KeyTypeParameter.E, rsaparams.Exponent);
|
||||
_credentialPublicKey = new CredentialPublicKey(cpk);
|
||||
_sig = rsa.SignData(_attToBeSigned, HashAlgFromCOSEAlg(_alg), _padding);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(_kty), _kty, "Invalid COSE key type");
|
||||
}
|
||||
}
|
||||
|
||||
public WebauthnAttestationResponse MakePasskey(WebauthnCredentialCreationOptions options, int algIndex = 0)
|
||||
{
|
||||
WebauthnAttestationResponse response;
|
||||
_credentialID = RandomNumberGenerator.GetBytes(32);
|
||||
_options = options;
|
||||
_alg = _options.PublicKeyOptions.PublicKeyCredentialParameters[algIndex].Algorithm;
|
||||
MakeCredentialPublicKey();
|
||||
|
||||
PublicKeyCredential pkc = new()
|
||||
{
|
||||
AuthenticatorResponse = new AuthenticatorAttestationResponse()
|
||||
{
|
||||
AttestationObject = _attestationObject.EncodeToBytes(),
|
||||
ClientDataJson = _clientDataJson
|
||||
},
|
||||
ClientExtensionResults = new()
|
||||
{
|
||||
HmacSecret = true
|
||||
},
|
||||
Id = _credentialID
|
||||
};
|
||||
|
||||
response = options.GetType().Name switch
|
||||
{
|
||||
nameof(MicrosoftGraphWebauthnCredentialCreationOptions) => new MicrosoftGraphWebauthnAttestationResponse(pkc, $"DSInternals.Passkeys {_alg}"),
|
||||
nameof(OktaWebauthnCredentialCreationOptions) => new OktaWebauthnAttestationResponse(pkc, options.PublicKeyOptions.User.Id, (options as OktaWebauthnCredentialCreationOptions).Id),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(options)),
|
||||
};
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class PublicKeyCredentialCreationOptionsTester
|
||||
{
|
||||
[TestMethod]
|
||||
public void PublicKeyCredentialCreationOptions_Deserialize()
|
||||
public void EntraIdPublicKeyCredentialCreationOptions_Deserialize()
|
||||
{
|
||||
var options = JsonSerializer.Deserialize<PublicKeyCredentialCreationOptions>(@"{
|
||||
""rp"": {
|
||||
@@ -97,5 +388,61 @@ namespace DSInternals.Win32.WebAuthn.Tests
|
||||
Assert.AreEqual(COSE.Algorithm.RS256, options.PublicKeyCredentialParameters[1].Algorithm);
|
||||
Assert.AreEqual(COSE.Algorithm.EdDSA, options.PublicKeyCredentialParameters[2].Algorithm);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OktaPublicKeyCredentialCreationOptions_Deserialize()
|
||||
{
|
||||
var options = JsonSerializer.Deserialize<PublicKeyCredentialCreationOptions>(@"{
|
||||
""rp"": {
|
||||
""name"": ""Okta Tenant Name -- Environment"",
|
||||
""id"": ""example.okta.com""
|
||||
},
|
||||
""user"": {
|
||||
""displayName"": ""Okta Doe"",
|
||||
""name"": ""okta@contoso.com"",
|
||||
""id"": ""00eDuihq64pgP1gVD0x7""
|
||||
},
|
||||
""pubKeyCredParams"": [
|
||||
{
|
||||
""type"": ""public-key"",
|
||||
""alg"": -7
|
||||
},
|
||||
{
|
||||
""type"": ""public-key"",
|
||||
""alg"": -257
|
||||
}
|
||||
],
|
||||
""challenge"": ""AVun-poGmJKZOAT0r-KBSs-94BPqMf3j"",
|
||||
""attestation"": ""direct"",
|
||||
""authenticatorSelection"": {
|
||||
""userVerification"": ""required"",
|
||||
""requireResidentKey"": false
|
||||
},
|
||||
""u2fParams"": {
|
||||
""appid"": ""https://example.okta.com""
|
||||
},
|
||||
""excludeCredentials"": [
|
||||
{
|
||||
""type"": ""public-key"",
|
||||
""id"": ""VX_AlCL9qUx2ox_Ekth4NYngvwpUswaBqcfb4XsHglI""
|
||||
},
|
||||
{
|
||||
""type"": ""public-key"",
|
||||
""id"": ""kFPT5CL3-I30e22QQ0WYo4C9EFCTcbWM0-G-wTBslVNzKzf-FsJ1CBVrgN2k5RJH2dTFJxyzgI06XxIbrcbpAA""
|
||||
}
|
||||
]
|
||||
}");
|
||||
|
||||
Assert.AreEqual("example.okta.com", options.RelyingParty.Id);
|
||||
Assert.AreEqual("okta@contoso.com", options.User.Name);
|
||||
Assert.AreEqual(AttestationConveyancePreference.Direct, options.Attestation);
|
||||
Assert.IsNotNull(options.ExcludeCredentials);
|
||||
Assert.IsFalse(options.AuthenticatorSelection.RequireResidentKey);
|
||||
Assert.AreEqual(AuthenticatorAttachment.Any, options.AuthenticatorSelection.AuthenticatorAttachment);
|
||||
Assert.AreEqual(UserVerificationRequirement.Required, options.AuthenticatorSelection.UserVerificationRequirement);
|
||||
Assert.AreEqual(2, options.PublicKeyCredentialParameters.Count);
|
||||
Assert.AreEqual(COSE.Algorithm.ES256, options.PublicKeyCredentialParameters[0].Algorithm);
|
||||
Assert.AreEqual(COSE.Algorithm.RS256, options.PublicKeyCredentialParameters[1].Algorithm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,12 @@
|
||||
"resolved": "6.0.2",
|
||||
"contentHash": "bJShQ6uWRTQ100ZeyiMqcFlhP7WJ+bCuabUs885dJiBEzMsJMSFr7BOyeCw4rgvQokteGi5rKQTlkhfQPUXg2A=="
|
||||
},
|
||||
"Fido2.Models": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.0.1, )",
|
||||
"resolved": "3.0.1",
|
||||
"contentHash": "mgjcuGETuYSCUEaZG+jQeeuuEMkDLc4GDJHBvKDdOz6oSOWp5adPdWP4btZx7Pi+9fu4szN3JIjJmby67MaILw=="
|
||||
},
|
||||
"Microsoft.NET.Test.Sdk": {
|
||||
"type": "Direct",
|
||||
"requested": "[17.10.0, )",
|
||||
@@ -51,11 +57,64 @@
|
||||
"System.Diagnostics.DiagnosticSource": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Bcl.AsyncInterfaces": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.CodeCoverage": {
|
||||
"type": "Transitive",
|
||||
"resolved": "17.10.0",
|
||||
"contentHash": "yC7oSlnR54XO5kOuHlVOKtxomNNN1BWXX8lK1G2jaPXT9sUok7kCOoA4Pgs0qyFaCtMrNsprztYMeoEGqCm4uA=="
|
||||
},
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Testing.Extensions.Telemetry": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.3.2",
|
||||
@@ -141,19 +200,36 @@
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "tCQTzPsGZh/A9LhhA6zrqCRV4hOHsK90/G7q3Khxmn6tnB1PuNU0cRaKANP2AWcF9bn0zsuOoZOSrHuJk6oNBA=="
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Formats.Asn1": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "MTvUIktmemNB+El0Fgw9egyqT9AYSIk6DTJeoDSpc3GIHxHCMo8COqkWT1mptX5tZ1SlQ6HJZ0OsSvMth1c12w=="
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Reflection.Metadata": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.6.0",
|
||||
"contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ=="
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
|
||||
},
|
||||
"System.Security.Cryptography.Cng": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
@@ -170,7 +246,9 @@
|
||||
"dsinternals.win32.webauthn": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Identity.Client": "[4.66.1, )",
|
||||
"PeterO.Cbor": "[4.5.3, )",
|
||||
"System.IdentityModel.Tokens.Jwt": "[8.2.0, )",
|
||||
"System.Security.Cryptography.Cng": "[5.0.0, )",
|
||||
"System.Text.Json": "[8.0.5, )"
|
||||
}
|
||||
|
||||
@@ -43,12 +43,14 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Identity.Client" Version="4.66.1" />
|
||||
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.106">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<!-- TODO: Replace with System.Formats.Cbor -->
|
||||
<PackageReference Include="PeterO.Cbor" Version="4.5.3" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.2.0" />
|
||||
<!-- Note: Classes from this namespace are part of .NET Framework -->
|
||||
<PackageReference Include="System.Security.Cryptography.Cng" Version="5.0.0" Condition="'$(TargetFramework)' != 'net472' AND '$(TargetFramework)' != 'net48'" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.5" />
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace DSInternals.Win32.WebAuthn
|
||||
namespace DSInternals.Win32.WebAuthn.EntraID
|
||||
{
|
||||
public class MicrosoftGraphWebauthnAttestationResponse
|
||||
public class MicrosoftGraphWebauthnAttestationResponse : WebauthnAttestationResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// The display name of the key as given by the user.
|
||||
@@ -15,11 +15,11 @@ namespace DSInternals.Win32.WebAuthn
|
||||
/// Contains the WebAuthn public key credential information being registered.
|
||||
/// </summary>
|
||||
[JsonPropertyName("publicKeyCredential")]
|
||||
public PublicKeyCredential PublicKeyCredential { get; set; }
|
||||
public override PublicKeyCredential PublicKeyCred { get; set; }
|
||||
|
||||
public MicrosoftGraphWebauthnAttestationResponse(PublicKeyCredential publicKeyCredential, string displayName)
|
||||
{
|
||||
PublicKeyCredential = publicKeyCredential;
|
||||
PublicKeyCred = publicKeyCredential;
|
||||
DisplayName = displayName;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -2,13 +2,13 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace DSInternals.Win32.WebAuthn
|
||||
namespace DSInternals.Win32.WebAuthn.EntraID
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <remarks>OData Object: https://graph.microsoft.com/beta/$metadata#microsoft.graph.webauthnCredentialCreationOptions</remarks>
|
||||
public class MicrosoftGraphWebauthnCredentialCreationOptions
|
||||
public class MicrosoftGraphWebauthnCredentialCreationOptions : WebauthnCredentialCreationOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines when the challenge in the creation options is no longer valid.
|
||||
@@ -20,7 +20,7 @@ namespace DSInternals.Win32.WebAuthn
|
||||
/// Defines public key options for the creation of a new WebAuthn public key credential.
|
||||
/// </summary>
|
||||
[JsonPropertyName("publicKey")]
|
||||
public PublicKeyCredentialCreationOptions PublicKeyOptions { get; set; }
|
||||
public override PublicKeyCredentialCreationOptions PublicKeyOptions { get; set; }
|
||||
|
||||
public static MicrosoftGraphWebauthnCredentialCreationOptions Create(string json)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
|
||||
namespace DSInternals.Win32.WebAuthn.Okta
|
||||
{
|
||||
public class OktaProfile
|
||||
{
|
||||
[JsonConstructor]
|
||||
public OktaProfile(
|
||||
string credentialId,
|
||||
object appId,
|
||||
object version,
|
||||
string authenticatorName,
|
||||
object presetPinAvailable,
|
||||
object fulfillmentProvider
|
||||
)
|
||||
{
|
||||
this.CredentialId = credentialId;
|
||||
this.AppId = appId;
|
||||
this.Version = version;
|
||||
this.AuthenticatorName = authenticatorName;
|
||||
this.PresetPinAvailable = presetPinAvailable;
|
||||
this.FulfillmentProvider = fulfillmentProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ID for the Factor credential
|
||||
/// </summary>
|
||||
[JsonPropertyName("credentialId")]
|
||||
public string CredentialId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// U2F appId string
|
||||
/// </summary>
|
||||
[JsonPropertyName("appId")]
|
||||
public object AppId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Undocumented
|
||||
/// </summary>
|
||||
[JsonPropertyName("version")]
|
||||
public object Version { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Human-readable name of the authenticator
|
||||
/// </summary>
|
||||
[JsonPropertyName("authenticatorName")]
|
||||
public string AuthenticatorName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Undocumented
|
||||
/// </summary>
|
||||
[JsonPropertyName("presetPinAvailable")]
|
||||
public object PresetPinAvailable { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Undocumented
|
||||
/// </summary>
|
||||
[JsonPropertyName("fulfillmentProvider")]
|
||||
public object FulfillmentProvider { get; }
|
||||
}
|
||||
|
||||
public class OktaFido2AuthenticationMethod
|
||||
{
|
||||
[JsonConstructor]
|
||||
public OktaFido2AuthenticationMethod(
|
||||
string id,
|
||||
string factorType,
|
||||
string provider,
|
||||
string vendorName,
|
||||
string status,
|
||||
DateTime? created,
|
||||
DateTime? lastUpdated,
|
||||
OktaProfile profile
|
||||
)
|
||||
{
|
||||
this.Id = id;
|
||||
this.FactorType = factorType;
|
||||
this.Provider = provider;
|
||||
this.VendorName = vendorName;
|
||||
this.Status = status;
|
||||
this.Created = created;
|
||||
this.LastUpdated = lastUpdated;
|
||||
this.Profile = profile;
|
||||
}
|
||||
|
||||
public static OktaFido2AuthenticationMethod FromJsonString(string json)
|
||||
{
|
||||
if (string.IsNullOrEmpty(json))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(json));
|
||||
}
|
||||
|
||||
return JsonSerializer.Deserialize<OktaFido2AuthenticationMethod>(json);
|
||||
}
|
||||
/// <summary>
|
||||
/// ID of the Factor
|
||||
/// </summary>
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Type of Factor
|
||||
/// </summary>
|
||||
[JsonPropertyName("factorType")]
|
||||
public string FactorType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Provider for the Factor
|
||||
/// </summary>
|
||||
[JsonPropertyName("provider")]
|
||||
public string Provider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the Factor vendor. This is usually the same as the provider except for On-Prem MFA where it depends on administrator settings.
|
||||
/// </summary>
|
||||
[JsonPropertyName("vendorName")]
|
||||
public string VendorName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Status of the Factor
|
||||
/// </summary>
|
||||
[JsonPropertyName("status")]
|
||||
public string Status { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Timestamp when the Factor was enrolled
|
||||
/// </summary>
|
||||
[JsonPropertyName("created")]
|
||||
public DateTime? Created { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Timestamp when the Factor was last updated
|
||||
/// </summary>
|
||||
[JsonPropertyName("lastUpdated")]
|
||||
public DateTime? LastUpdated { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Specific attributes related to the Factor
|
||||
/// </summary>
|
||||
[JsonPropertyName("profile")]
|
||||
public OktaProfile Profile { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace DSInternals.Win32.WebAuthn.Okta
|
||||
{
|
||||
public class OktaWebauthnAttestationResponse : WebauthnAttestationResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the WebAuthn public key credential information being registered.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public override PublicKeyCredential PublicKeyCred { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ID of an existing Okta user.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public string UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ID of an existing user Factor.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public string FactorId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ID of an existing user Factor.
|
||||
/// </summary>
|
||||
[JsonPropertyName("attestation")]
|
||||
[JsonConverter(typeof(Base64UrlConverter))]
|
||||
public byte[] Attestation => PublicKeyCred.AuthenticatorResponse.AttestationObject;
|
||||
|
||||
/// <summary>
|
||||
/// ID of an existing user Factor.
|
||||
/// </summary>
|
||||
[JsonPropertyName("clientData")]
|
||||
[JsonConverter(typeof(Base64UrlConverter))]
|
||||
public byte[] ClientData => PublicKeyCred.AuthenticatorResponse.ClientDataJson;
|
||||
|
||||
public OktaWebauthnAttestationResponse(PublicKeyCredential publicKeyCredential, byte[] userId, string factorId)
|
||||
{
|
||||
PublicKeyCred = publicKeyCredential;
|
||||
UserId = Base64UrlConverter.ToBase64UrlString(userId);
|
||||
FactorId = factorId;
|
||||
}
|
||||
|
||||
override public string ToString()
|
||||
{
|
||||
return JsonSerializer.Serialize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace DSInternals.Win32.WebAuthn.Okta
|
||||
{
|
||||
public class Embedded
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines public key options for the creation of a new WebAuthn public key credential.
|
||||
/// </summary>
|
||||
[JsonPropertyName("activation")]
|
||||
public PublicKeyCredentialCreationOptions PublicKeyOptions { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class OktaWebauthnCredentialCreationOptions : WebauthnCredentialCreationOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The factor id of the Okta factor being registered.
|
||||
/// </summary>
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A wrapper around the PublicKeyCredentialCreationOptions
|
||||
/// </summary>
|
||||
[JsonPropertyName("_embedded")]
|
||||
public Embedded Embedded { get; set; }
|
||||
|
||||
public override PublicKeyCredentialCreationOptions PublicKeyOptions { get => Embedded.PublicKeyOptions; set { }}
|
||||
|
||||
public static OktaWebauthnCredentialCreationOptions Create(string json)
|
||||
{
|
||||
if(string.IsNullOrEmpty(json))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(json));
|
||||
}
|
||||
|
||||
return JsonSerializer.Deserialize<OktaWebauthnCredentialCreationOptions>(json);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace DSInternals.Win32.WebAuthn
|
||||
{
|
||||
public abstract class WebauthnAttestationResponse
|
||||
{
|
||||
[JsonIgnore()]
|
||||
public abstract PublicKeyCredential PublicKeyCred { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace DSInternals.Win32.WebAuthn
|
||||
{
|
||||
public abstract class WebauthnCredentialCreationOptions
|
||||
{
|
||||
public abstract PublicKeyCredentialCreationOptions PublicKeyOptions { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,16 @@
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
".NETCoreApp,Version=v3.1": {
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Direct",
|
||||
"requested": "[4.66.1, )",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.CsWin32": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.3.106, )",
|
||||
@@ -23,6 +33,16 @@
|
||||
"PeterO.URIUtility": "1.0.0"
|
||||
}
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.2.0, )",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Security.Cryptography.Cng": {
|
||||
"type": "Direct",
|
||||
"requested": "[5.0.0, )",
|
||||
@@ -51,6 +71,53 @@
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.CSharp": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "kaj6Wb4qoMuH3HySFJhxwQfe8R/sJsNJnANrvv8WdFPMoNbKY5htfNscv+LHCu5ipz+49m2e+WQXpLXr9XYemQ=="
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.CSharp": "4.5.0",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0",
|
||||
"System.Security.Cryptography.Cng": "4.5.0",
|
||||
"System.Text.Json": "8.0.5"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.SDK.Win32Docs": {
|
||||
"type": "Transitive",
|
||||
"resolved": "0.1.42-alpha",
|
||||
@@ -84,6 +151,15 @@
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.4",
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Formats.Asn1": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
@@ -116,6 +192,16 @@
|
||||
}
|
||||
},
|
||||
".NETFramework,Version=v4.7.2": {
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Direct",
|
||||
"requested": "[4.66.1, )",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.CsWin32": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.3.106, )",
|
||||
@@ -137,6 +223,16 @@
|
||||
"PeterO.URIUtility": "1.0.0"
|
||||
}
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.2.0, )",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Text.Json": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.5, )",
|
||||
@@ -160,6 +256,48 @@
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "8.0.0",
|
||||
"System.ValueTuple": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0",
|
||||
"System.Memory": "4.5.5",
|
||||
"System.Text.Json": "8.0.5"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.SDK.Win32Docs": {
|
||||
"type": "Transitive",
|
||||
"resolved": "0.1.42-alpha",
|
||||
@@ -193,6 +331,15 @@
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.4",
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.5",
|
||||
@@ -238,6 +385,16 @@
|
||||
}
|
||||
},
|
||||
".NETFramework,Version=v4.8": {
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Direct",
|
||||
"requested": "[4.66.1, )",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.CsWin32": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.3.106, )",
|
||||
@@ -259,6 +416,16 @@
|
||||
"PeterO.URIUtility": "1.0.0"
|
||||
}
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.2.0, )",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Text.Json": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.5, )",
|
||||
@@ -282,6 +449,48 @@
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "8.0.0",
|
||||
"System.ValueTuple": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0",
|
||||
"System.Memory": "4.5.5",
|
||||
"System.Text.Json": "8.0.5"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.SDK.Win32Docs": {
|
||||
"type": "Transitive",
|
||||
"resolved": "0.1.42-alpha",
|
||||
@@ -315,6 +524,15 @@
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.4",
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.5",
|
||||
@@ -360,6 +578,16 @@
|
||||
}
|
||||
},
|
||||
".NETCoreApp,Version=v5.0": {
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Direct",
|
||||
"requested": "[4.66.1, )",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.CsWin32": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.3.106, )",
|
||||
@@ -381,6 +609,16 @@
|
||||
"PeterO.URIUtility": "1.0.0"
|
||||
}
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.2.0, )",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Security.Cryptography.Cng": {
|
||||
"type": "Direct",
|
||||
"requested": "[5.0.0, )",
|
||||
@@ -409,6 +647,53 @@
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.CSharp": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "kaj6Wb4qoMuH3HySFJhxwQfe8R/sJsNJnANrvv8WdFPMoNbKY5htfNscv+LHCu5ipz+49m2e+WQXpLXr9XYemQ=="
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.CSharp": "4.5.0",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0",
|
||||
"System.Security.Cryptography.Cng": "4.5.0",
|
||||
"System.Text.Json": "8.0.5"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.SDK.Win32Docs": {
|
||||
"type": "Transitive",
|
||||
"resolved": "0.1.42-alpha",
|
||||
@@ -442,6 +727,14 @@
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Formats.Asn1": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
@@ -474,6 +767,16 @@
|
||||
}
|
||||
},
|
||||
"net6.0": {
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Direct",
|
||||
"requested": "[4.66.1, )",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.CsWin32": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.3.106, )",
|
||||
@@ -495,6 +798,16 @@
|
||||
"PeterO.URIUtility": "1.0.0"
|
||||
}
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.2.0, )",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Security.Cryptography.Cng": {
|
||||
"type": "Direct",
|
||||
"requested": "[5.0.0, )",
|
||||
@@ -514,6 +827,50 @@
|
||||
"System.Text.Encodings.Web": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Bcl.AsyncInterfaces": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.SDK.Win32Docs": {
|
||||
"type": "Transitive",
|
||||
"resolved": "0.1.42-alpha",
|
||||
@@ -542,6 +899,14 @@
|
||||
"resolved": "1.0.0",
|
||||
"contentHash": "fpRTBsYACMp7NvTECauYRomubWTC3vUNw4hMXdIedP8ctBGK6tea9HOJwE+qVzis6MZYkL3LIs8qeY3rc6Jdlw=="
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Formats.Asn1": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
@@ -562,6 +927,16 @@
|
||||
}
|
||||
},
|
||||
"net7.0": {
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Direct",
|
||||
"requested": "[4.66.1, )",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.CsWin32": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.3.106, )",
|
||||
@@ -583,6 +958,16 @@
|
||||
"PeterO.URIUtility": "1.0.0"
|
||||
}
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.2.0, )",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Security.Cryptography.Cng": {
|
||||
"type": "Direct",
|
||||
"requested": "[5.0.0, )",
|
||||
@@ -601,6 +986,50 @@
|
||||
"System.Text.Encodings.Web": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Bcl.AsyncInterfaces": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.SDK.Win32Docs": {
|
||||
"type": "Transitive",
|
||||
"resolved": "0.1.42-alpha",
|
||||
@@ -629,11 +1058,24 @@
|
||||
"resolved": "1.0.0",
|
||||
"contentHash": "fpRTBsYACMp7NvTECauYRomubWTC3vUNw4hMXdIedP8ctBGK6tea9HOJwE+qVzis6MZYkL3LIs8qeY3rc6Jdlw=="
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Formats.Asn1": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "MTvUIktmemNB+El0Fgw9egyqT9AYSIk6DTJeoDSpc3GIHxHCMo8COqkWT1mptX5tZ1SlQ6HJZ0OsSvMth1c12w=="
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
|
||||
},
|
||||
"System.Text.Encodings.Web": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
@@ -641,6 +1083,16 @@
|
||||
}
|
||||
},
|
||||
"net8.0": {
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Direct",
|
||||
"requested": "[4.66.1, )",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.CsWin32": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.3.106, )",
|
||||
@@ -662,6 +1114,16 @@
|
||||
"PeterO.URIUtility": "1.0.0"
|
||||
}
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.2.0, )",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Security.Cryptography.Cng": {
|
||||
"type": "Direct",
|
||||
"requested": "[5.0.0, )",
|
||||
@@ -677,6 +1139,42 @@
|
||||
"resolved": "8.0.5",
|
||||
"contentHash": "0f1B50Ss7rqxXiaBJyzUu9bWFOO2/zSlifZ/UNMdiIpDYe4cY4LQQicP4nirK1OS31I43rn062UIJ1Q9bpmHpg=="
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA=="
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.SDK.Win32Docs": {
|
||||
"type": "Transitive",
|
||||
"resolved": "0.1.42-alpha",
|
||||
@@ -705,10 +1203,23 @@
|
||||
"resolved": "1.0.0",
|
||||
"contentHash": "fpRTBsYACMp7NvTECauYRomubWTC3vUNw4hMXdIedP8ctBGK6tea9HOJwE+qVzis6MZYkL3LIs8qeY3rc6Jdlw=="
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Formats.Asn1": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "MTvUIktmemNB+El0Fgw9egyqT9AYSIk6DTJeoDSpc3GIHxHCMo8COqkWT1mptX5tZ1SlQ6HJZ0OsSvMth1c12w=="
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,57 @@
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Bcl.TimeProvider": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "C7kWHJnMRY7EvJev2S8+yJHZ1y7A4ZlLbA4NE+O23BDIAN5mHeqND1m+SKv1ChRS5YlCDW7yAMUe7lttRsJaAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "8.0.0",
|
||||
"System.ValueTuple": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Identity.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.66.1",
|
||||
"contentHash": "mE+m3pZ7zSKocSubKXxwZcUrCzLflC86IdLxrVjS8tialy0b1L+aECBqRBC/ykcPlB4y7skg49TaTiA+O2UfDw==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "27ClfnelIu92kLGOaz0vjdXR1Jv7hAdLffxxNgR8T0+IMWmxeVyO3cU8oohmuTrWUFOfd2tsSGaRNewnuClIZw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.JsonWebTokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/DAx+9HeqfkH/PccwHx7cUtQe9fYM6AxEmTla8WXUT+w+mapKLnigWmdKtF55hNvxiSnmGhSSCcG7XrvkpGKFA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "mZsjOZlbmCZfM71y8Fyo+D5UJ1RZFvmKXkxTfE2llQ0/CrfEeWmbpoew51w++EWs+G8B/peZqR1DQtbX3bB6Fg==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.Abstractions": "8.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.IdentityModel.Tokens": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "/I+6D3SwW8hQh5wznGzQCrS4L5y5Re/0AEKKfXXAduWzz4WKqJzY8RmjwZ6W66bIFUhPrqOy6zsLKPik4Ppnbw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.TimeProvider": "8.0.1",
|
||||
"Microsoft.IdentityModel.Logging": "8.2.0",
|
||||
"System.Memory": "4.5.5",
|
||||
"System.Text.Json": "8.0.5"
|
||||
}
|
||||
},
|
||||
"Microsoft.Windows.SDK.Contracts": {
|
||||
"type": "Transitive",
|
||||
"resolved": "10.0.18362.2005",
|
||||
@@ -84,6 +135,24 @@
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.4",
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.IdentityModel.Tokens.Jwt": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.2.0",
|
||||
"contentHash": "M61kEnR2ljMFL2vLHmHrodCqPO/zKsYsaRu3jdagYOP/y0ZdFoFoATyfwR0bJ5quBsWEPL5y8QU7CJiEh2kq+Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.IdentityModel.JsonWebTokens": "8.2.0",
|
||||
"Microsoft.IdentityModel.Tokens": "8.2.0"
|
||||
}
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.5",
|
||||
@@ -174,7 +243,9 @@
|
||||
"dsinternals.win32.webauthn": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Identity.Client": "[4.66.1, )",
|
||||
"PeterO.Cbor": "[4.5.3, )",
|
||||
"System.IdentityModel.Tokens.Jwt": "[8.2.0, )",
|
||||
"System.Text.Json": "[8.0.5, )"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user