
Maîtriser l'acquisition d'Access Token : Client Credentials Flow
Comment utiliser le flux Client Credentials pour obtenir un access token
Cet article fait partie d’une série. Dans celui-ci, nous mettons en avant l’utilisation d’un certificat. Consultez les autres articles sur les autres flux d’autorisation :
Maîtriser l’acquisition d’Access Token : le flux Authorization Code
Maîtriser l’acquisition d’Access Token : Utiliser un refresh token
Maîtriser l’acquisition d’Access Token : Client Credentials Flow
Bien qu’utiliser le flux Client Credentials avec un client secret soit l’une de mes méthodes préférées pour obtenir un access token, l’utilisation d’un certificat est l’une des plus sécurisées. C’est identique à l’utilisation d’un client secret, sauf que vous spécifiez client_assertion et client_assertion_type dans le body de la requête au lieu de client_secret.
Tandis que le paramètre client_assertion_type a toujours la même valeur, cette forme d’authentification repose sur le paramètre client_assertion. Il s’agit d’un JWT (JSON Web Token) composé des trois parties suivantes, séparées par un point :
La sécurité de cette forme d’authentification réside dans le fait que vous pouvez indiquer dans le payload pendant combien de temps et jusqu’à quand exactement le JWT peut rester valide. Et le fait que la signature est signée numériquement avec la clé privée de votre certificat. Ainsi, l’inscription d’application peut vérifier l’authenticité avant d’accorder un access token, puisque ce même certificat est configuré dans l’inscription d’application Entra.
Pour obtenir un access token avec ce flux d’autorisation, nous devons faire 3 choses :
Commençons par créer le certificat. Nous pouvons le faire en utilisant PowerShell. Ce certificat est ajouté à l’emplacement des certificats de l’ordinateur. Ensuite, nous l’exporterons afin de pouvoir le télécharger dans notre inscription d’application Entra. Avec ce morceau de code PowerShell, nous pouvons créer et exporter le certificat. Notez que j’utilise l’emplacement C: pour exporter mon certificat, mais vous pouvez choisir un emplacement de votre choix.
$certname = "MySyperAwesomeCertificate"
$cert = New-SelfSignedCertificate -Subject "CN=$certname" -CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -KeySpec Signature -KeyLength 2048 -KeyAlgorithm RSA -HashAlgorithm SHA256
Export-Certificate -Cert $cert -FilePath "C:\$certname.cer"
Si tout se passe bien, vous devriez voir quelque chose comme ceci :

Maintenant que nous avons notre certificat, nous pouvons le télécharger dans notre inscription d’application Entra dans la section Certificates & secrets :

Ensuite, un panneau s’ouvre sur la droite. Sélectionnez votre certificat depuis l’emplacement où vous l’avez exporté et donnez une description à votre certificat (facultatif).

Pour obtenir un JWT basé sur votre certificat, j’utilise le script PowerShell ci-dessous. Dans ce script, vous devez fournir 3 paramètres :
![]()
Deux sections que je souhaite mettre en évidence sont le header et le payload. Ce sont 2 objets qui sont finalement encodés en une chaîne base64. Le header est composé des paramètres suivants :
Le payload est composé des paramètres suivants :
aud : (audience) identifie les destinataires auxquels le JWT est destiné. Dans ce cas, il s’agit de https://login.microsoft.com/[YOUR_TENANT_ID]/oauth2/v2.0/token.
exp : (expiration time) indique quand le JWT doit expirer. Cela garantit que le JWT n’est pas valide indéfiniment, mais seulement pour une certaine période. Le code ci-dessous utilise 5 minutes.
iss : (issuer) Indique qui a émis le JWT, c’est-à-dire l’entité responsable de la création et de la signature du token. Dans ce cas, le client ID.
jwt : (JWT ID) Un identifiant unique (GUID) pour le token.
nbf : (Not Before) Le moment à partir duquel le token est valide.
sub : (subject) Le sujet du token, par exemple l’entité à laquelle le token s’applique. Doit être identique à iss, donc votre client ID.
iat : (issued at) Le moment où le token a été émis.
$TenantId = "[YOUR_TENANT_ID]"
$ClientId = "[YOUR_CLIENT_ID]"
# Load the self-signed and uploaded certificate using its thumbprint
$Certificate = Get-Item Cert:\CurrentUser\My\[YOUR_THUMBPRINT]
# Convert the certificate to a base64 string hash of the certificate
$CertificateAsBase64 = [System.Convert]::ToBase64String($Certificate.GetCertHash())
# Create a start date for creating a timespan
$StartDate = (Get-Date "1970-01-01T00:00:00Z").ToUniversalTime()
#Make a timespan from StartDate and let it expire after 5 minutes
$ExpirationTimeSpan = (New-TimeSpan -Start $StartDate -End (Get-Date).ToUniversalTime().AddMinutes(5)).TotalSeconds
$Expiration = [math]::Round($ExpirationTimeSpan, 0)
# Create a timespan before which the JWT MUST NOT be accepted for processing
$NotBeforeExpirationTimeSpan = (New-TimeSpan -Start $StartDate -End ((Get-Date).ToUniversalTime())).TotalSeconds
$Nbf = [math]::Round($NotBeforeExpirationTimeSpan, 0)
# Create the header
$Header = @{
alg = "RS256"
typ = "JWT"
x5t = $CertificateAsBase64 -replace '\+', '-' -replace '/', '_' -replace '='
}
# Create the payload
$Payload = @{
aud = "https://login.microsoftonline.com/$TenantId/oauth2/token"
exp = $Expiration
iss = $ClientId
jti = [guid]::NewGuid()
nbf = $Nbf
sub = $ClientId
}
# Convert header to base64
$HeaderAsBase64 = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(($Header | ConvertTo-Json)))
# Convert header to base64
$PayloadAsBase64 = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(($Payload | ConvertTo-Json)))
# Combine header and payload with "." to form an unsigned JWT
$UnsignedJWT = $HeaderAsBase64 + "." + $PayloadAsBase64
# Retrieve the private key object from the certificate
$PrivateKey = ([System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($Certificate))
# Create a RSA Signature padding
$RSASignaturePadding = [Security.Cryptography.RSASignaturePadding]::Pkcs1
# Create a hashalgoritm
$HashAlgorithmName = [Security.Cryptography.HashAlgorithmName]::SHA256
# Create the JWT signature
$JWTSignature = [Convert]::ToBase64String($PrivateKey.SignData([System.Text.Encoding]::UTF8.GetBytes($UnsignedJWT), $HashAlgorithmName, $RSASignaturePadding)) -replace '\+', '-' -replace '/', '_' -replace '='
# Combine the signature with the JWT using "."
$SignedJWT = $UnsignedJWT + "." + $JWTSignature
Pour récupérer l’access token, nous devons effectuer une requête POST vers l’endpoint https://login.microsoft.com/[YOUR_TENANT_ID]/oauth2/v2.0/token avec les paramètres suivants dans le body de la requête :
$SignedJWT)https://graph.microsoft.com/.default.
Si tout se passe bien, vous devriez obtenir une réponse comme celle-ci :
