Created
March 8, 2024 11:36
-
-
Save jaloplo/6612a9842202fcf00099f41437086aad to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.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