Private/Get-EntraMfaAuthToken.ps1
function Get-EntraMfaAuthToken { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $TenantId, [Parameter(Mandatory = $true)] [PSObject] $Credential ) try { $tokenEndpoint = $Providers.EntraId.TokenEndpoint.Replace('_tenantId_',$TenantId) if ($Credential -is [System.Security.Cryptography.X509Certificates.X509Certificate] -or $Credential -is [string]) { if ($Credential -is [string]) { $cert = Select-Certificate -CertificateThumbprint $Credential if ($cert -isnot [System.Security.Cryptography.X509Certificates.X509Certificate]) { throw "Can't proceed with X509Certificates authentication" } } else { $cert = $Credential } # $currentDateTime = [int](Get-Date).ToUniversalTime().Subtract((Get-Date -Date "1970-01-01")).TotalSeconds $nbf = $currentDateTime $iat = $nbf $exp = $currentDateTime + 60 $jwtHeader = @{ alg = "RS256" typ = "JWT" x5t = [Convert]::ToBase64String($cert.GetCertHash()) } $jwtPayload = @{ aud = $tokenEndpoint iss = $Providers.EntraId.MfaAppId sub = $Providers.EntraId.MfaAppId jti = (New-Guid).Guid nbf = $nbf iat = $iat exp = $exp } $jwtHeaderBase64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes((ConvertTo-Json $jwtHeader -Compress))) $jwtPayloadBase64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes((ConvertTo-Json $jwtPayload -Compress))) $jwtToSign = "$jwtHeaderBase64.$jwtPayloadBase64" $certificatePrivateKey = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert) $signatureBytes = $certificatePrivateKey.SignData([Text.Encoding]::UTF8.GetBytes($jwtToSign), [System.Security.Cryptography.HashAlgorithmName]::SHA256, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1) $jwtSignatureBase64 = [Convert]::ToBase64String($signatureBytes) $clientAssertion = "$jwtToSign.$jwtSignatureBase64" # $body = @{ client_id = $Providers.EntraId.MfaAppId client_assertion = $clientAssertion client_assertion_type = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" scope = "https://adnotifications.windowsazure.com/StrongAuthenticationService.svc/Connector/.default" grant_type = "client_credentials" } } elseif ($Credential -is [System.Security.SecureString]) { $clientSecret = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Credential)) $body = @{ client_id = $Providers.EntraId.MfaAppId client_secret = $clientSecret scope = "https://adnotifications.windowsazure.com/StrongAuthenticationService.svc/Connector/.default" grant_type = "client_credentials" } } else { throw "Invalid -Credential type" } $response = Invoke-RestMethod -Uri $tokenEndpoint -Method Post -Body $body -ContentType "application/x-www-form-urlencoded" -ErrorAction SilentlyContinue if (-not $response.access_token) { throw "Got '$response'" } $response } catch { throw "Failed to get access token - $_" } } |