Skip to content

Instantly share code, notes, and snippets.

@gscales
Created June 7, 2021 01:42
Show Gist options
  • Save gscales/12a4dd21a03c66fa4072b03337ac4fad to your computer and use it in GitHub Desktop.
Save gscales/12a4dd21a03c66fa4072b03337ac4fad to your computer and use it in GitHub Desktop.
function Get-AccessTokenForGraphFromCertificate{
param(
[Parameter(Position = 1, Mandatory = $true)]
[String]
$TenantDomain,
[Parameter(Position = 2, Mandatory = $true)]
[String]
$ClientId,
[Parameter(Position = 3, Mandatory = $false)]
[System.Security.Cryptography.X509Certificates.X509Certificate2]
$Certificate,
[Parameter(Position = 2, Mandatory = $false)]
[String]
$Scope = "https://graph.microsoft.com/.default"
)
Process{
# Create base64 hash of certificate
$CertificateBase64Hash = [System.Convert]::ToBase64String($Certificate.GetCertHash()) -replace '\+','-' -replace '/','_' -replace '='
# Create Token Timestamps
$StartDate = (Get-Date "1970-01-01T00:00:00Z" ).ToUniversalTime()
$TokenExpiration = [math]::Round(((New-TimeSpan -Start $StartDate -End (Get-Date).ToUniversalTime().AddMinutes(2)).TotalSeconds),0)
$NotBefore = [math]::Round(((New-TimeSpan -Start $StartDate -End ((Get-Date).ToUniversalTime())).TotalSeconds),0)
$ClientAssertionheader = @{
alg = "RS256"
typ = "JWT"
x5t = $CertificateBase64Hash
}
$ClientAssertionPayLoad = @{
aud = "https://login.microsoftonline.com/$TenantDomain/oauth2/token"
exp = $TokenExpiration
iss = $ClientId
jti = [guid]::NewGuid()
nbf = $NotBefore
sub = $ClientId
}
$CAEncodedHeader = [System.Convert]::ToBase64String(([System.Text.Encoding]::UTF8.GetBytes(($ClientAssertionheader | ConvertTo-Json)))) -replace '\+','-' -replace '/','_' -replace '='
$CAEncodedPayload = [System.Convert]::ToBase64String(([System.Text.Encoding]::UTF8.GetBytes(($ClientAssertionPayLoad | ConvertTo-Json)))) -replace '\+','-' -replace '/','_' -replace '='
# Get the private key object of your certificate
$PrivateKey = ([System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($Certificate))
$RSAPadding = [Security.Cryptography.RSASignaturePadding]::Pkcs1
$HashAlgorithm = [Security.Cryptography.HashAlgorithmName]::SHA256
# Sign the Assertion
$Signature = [Convert]::ToBase64String(
$PrivateKey.SignData([System.Text.Encoding]::UTF8.GetBytes(($CAEncodedHeader + "." + $CAEncodedPayload)),$HashAlgorithm,$RSAPadding)
) -replace '\+','-' -replace '/','_' -replace '='
# Create the assertion token
$ClientAssertion = $CAEncodedHeader + "." + $CAEncodedPayload + "." + $Signature
# Create a hash with body parameters
$Body = @{
client_id = $ClientId
client_assertion = $ClientAssertion
client_assertion_type = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
scope = $Scope
grant_type = "client_credentials"
}
$AuthUrl = "https://login.microsoftonline.com/$TenantDomain/oauth2/v2.0/token"
return Invoke-RestMethod -Headers $Header -Method POST -Uri $AuthUrl -Body $Body -ContentType 'application/x-www-form-urlencoded'
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment