Skip to content

Instantly share code, notes, and snippets.

@jaloplo
Created March 8, 2024 11:36
Show Gist options
  • Save jaloplo/6612a9842202fcf00099f41437086aad to your computer and use it in GitHub Desktop.
Save jaloplo/6612a9842202fcf00099f41437086aad to your computer and use it in GitHub Desktop.
<#
.SYNOPSIS
This script generates a JWT token and accesses a token from a consumer tenant for registering a container type.
.DESCRIPTION
This script is used to generate a JWT token using a private key certificate and then use that token to access an access token from a consumer tenant.
It then registers the container type in the consumer tenant using the obtained access token.
.PARAMETER ClientId
Specifies the Entra ID application client Id.
.PARAMETER ContainerTypeId
Specifies the SharePoint Embedded Container Type Id to register.
.PARAMETER PemCertificationFilePath
Specifies the path to the PEM certification file.
.PARAMETER ConsumerTenantId
Specifies the ID of the consumer tenant.
.PARAMETER ConsumerTenantUrl
Specifies the URL of the consumer tenant.
.PARAMETER Thumbprint
Specifies the thumbprint of the certificate taken from the Entra ID application.
.EXAMPLE
.\Register-SPOContainerType.ps1 -ClientId "af04a077-dca1-43ad-84b3-795873cc59cc" -ContainerTypeId "e8064be0-3041-4fb4-a258-3945dc82149f" -PemCertificationFilePath "C:\path\to\certificate.pem" -ConsumerTenantId "cd02c8bc-f2b3-4ada-944f-20cc722793af" -ConsumerTenantUrl "https://consumer.sharepoint.com" -Thumbprint "cb150c86842d40eba1ee757d5060d1be"
#>
param(
[Parameter(Mandatory=$true)]
[String] $ClientId,
[Parameter(Mandatory=$true)]
[String] $ContainerTypeId,
[Parameter(Mandatory=$true)]
[String] $PemCertificationFilePath,
[Parameter(Mandatory=$true)]
[String] $ConsumerTenantId,
[Parameter(Mandatory=$true)]
[String] $ConsumerTenantUrl,
[Parameter(Mandatory=$true)]
[String] $Thumbprint
)
<#
Here's a list of the steps performed by the script:
1. Build the JWT token to retrieve the consumer tenant access token
1. Transform the thumbprint provided to base64 format
2. Build the JWT header
3. Build the JWT payload
4. Build the JWT signature
5. Combine the JWT header, payload, and signature to create the JWT token.
6. Get the access token from the consumer tenant.
2. Register the container type in the consumer tenant.
#>
Try {
# Transformation of the thumbprint from hex to base64
Write-Host "Transforming the thumbprint provided to base64 format..."
$HexThumbprint = $Thumbprint
$RawThumbprint = [System.Convert]::FromHexString($HexThumbprint)
$Base64Thumbprint = [System.Convert]::ToBase64String($RawThumbprint)
$SafeThumbprintt = $Base64Thumbprint -replace '\+', '-' -replace '/','_' -replace '='
# JWT Header
Write-Host "Building the JWT header..."
$AlgorithmClaim = "RS256"
$TokenTypeClaim = "JWT"
$X5TClaim = $SafeThumbprintt
$Header = @{
alg = $AlgorithmClaim
typ = $TokenTypeClaim
x5t = $X5TClaim
} | ConvertTo-Json -Compress
$Base64Header = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Header))
$SafeHeader = $Base64Header -replace '\+', '-' -replace '/','_' -replace '='
# JWT Payload
Write-Host "Building the JWT payload..."
$Now = [DateTime]::UtcNow
$Expiration = [DateTime]::UtcNow.AddMinutes(5)
$AudienceClaim = "https://login.microsoftonline.com/$ConsumerTenantId/oauth2/v2.0/token"
$ExpirationTimeClaim = [Math]::Round($Expiration.Subtract([DateTime]::UnixEpoch).TotalSeconds)
$IssuerClaim = $ClientId
$JWTIdClaim = [Guid]::NewGuid()
$NotBeforeClaim = [Math]::Round($Now.Subtract([DateTime]::UnixEpoch).TotalSeconds)
$SubjectClaim = $ClientId
$IssuedAtClaim = [Math]::Round($Now.Subtract([DateTime]::UnixEpoch).TotalSeconds)
$Payload = @{
aud = $AudienceClaim
exp = $ExpirationTimeClaim
iss = $IssuerClaim
jti = $JWTIdClaim
nbf = $NotBeforeClaim
sub = $SubjectClaim
iat = $IssuedAtClaim
} | ConvertTo-Json -Compress
$Base64Payload = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Payload))
$SafePayload = $Base64Payload -replace '\+', '-' -replace '/','_' -replace '='
# JWT Signature
Write-Host "Building the JWT signature..."
$UnsignedToken = "$SafeHeader.$SafePayload"
$RsaProvider = New-Object System.Security.Cryptography.RSACryptoServiceProvider
$PemKey = Get-Content -Path $PemCertificationFilePath -Raw
$RsaProvider.ImportFromPem($PemKey)
$Hash = [System.Security.Cryptography.HashAlgorithmName]::SHA256
$Padding = [System.Security.Cryptography.RSASignaturePadding]::Pkcs1
$Signature = $RsaProvider.SignData([Text.Encoding]::UTF8.GetBytes($UnsignedToken), $Hash, $Padding)
$Base64Signature = [Convert]::ToBase64String($signature)
$SafeSignature = $Base64Signature -replace '\+', '-' -replace '/','_' -replace '='
# Combine the JWT and signature
Write-Host "Combined the JWT header, payload, and signature to create the JWT token."
$SignedToken= "$UnsignedToken.$SafeSignature"
# Getting the Access Token
Write-Host "Getting the access token from the consumer tenant..."
$Body = @{
"client_assertion_type" = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
"client_assertion" = $SignedToken
"client_id" = $ClientId
"scope" = "$ConsumerTenantUrl/.default"
"grant_type" = "client_credentials"
}
$AccessTokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$ConsumerTenantId/oauth2/v2.0/token" `
-Method Post `
-ContentType "application/x-www-form-urlencoded" `
-Body $Body `
-UseBasicParsing
$AccessToken = $AccessTokenResponse.access_token
$SecureAccessToken = $AccessToken | ConvertTo-SecureString -AsPlainText -Force
# Registering the Consumer Tenant
Write-Host "Registering the container type in the consumer tenant..."
$Body = @{
value = @(
@{
"appId" = $ClientId
"delegated" = @("full")
"appOnly" = @("full")
}
)
}
$RegistrationResponse = Invoke-RestMethod -Uri "$ConsumerTenantUrl/_api/v2.1/storageContainerTypes/$ContainerTypeId/applicationPermissions" `
-Method Put `
-Authentication Bearer `
-Token $SecureAccessToken `
-ContentType "application/json" `
-Body ($Body | ConvertTo-Json -Depth 3)
Write-Host "Registration completed."
$RegistrationResponse
}
Catch {
Write-Host "Error occurred: $_"
Exit 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment