Graph API - Generate token using user account, clientId and certificate for delegated permissions flow as a sign-in user

K Roja 51 Reputation points
2022-10-19T06:01:12.017+00:00

Hello Team,

For using graph api, how to generate token using user account, clientId and certificate for delegated permissions flow as a sign-in user?

Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
11,138 questions
0 comments No comments
{count} votes

3 answers

Sort by: Most helpful
  1. Bhanu Kiran 3,526 Reputation points
    2022-10-19T06:54:30.23+00:00

    Hello @K Roja ,

    You can generate token using user account, clientId and certificate for delegated permissions flow as a sign-in user only when using the client credentials flow
    https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow#second-case-access-token-request-with-a-certificate

    Hope this helps.

    If the answer is helpful, please click Accept Answer and kindly upvote. If you have any further questions about this answer, please click Comment.


  2. CarlZhao-MSFT 39,101 Reputation points
    2022-10-20T07:16:37.5+00:00

    Hi @@K Roja ,

    Connect to graph PowerShell using a client ID, tenant ID, and certificate without user interaction: https://learn.microsoft.com/en-us/powershell/microsoftgraph/app-only?view=graph-powershell-1.0&tabs=azure-portal.

    Connect-MgGraph -ClientID YOUR_APP_ID -TenantId YOUR_TENANT_ID -CertificateName YOUR_CERT_SUBJECT ## Or -CertificateThumbprint instead of -CertificateName  
    

    If the answer is helpful, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


  3. 2022-10-27T08:09:04.253+00:00

    Problem is resolved with below code

     $TenantName = "xxx"  
     $AppId = "xxx"  
     $Certificate = Get-Item Cert:\CurrentUser\My\<thumbprint>  
     $Scope = "https://graph.microsoft.com/.default"  
          
     # Create base64 hash of certificate  
     $CertificateBase64Hash = [System.Convert]::ToBase64String($Certificate.GetCertHash())  
          
     # Create JWT timestamp for expiration  
     $StartDate = (Get-Date "1970-01-01T00:00:00Z" ).ToUniversalTime()  
     $JWTExpirationTimeSpan = (New-TimeSpan -Start $StartDate -End (Get-Date).ToUniversalTime().AddMinutes(60)).TotalSeconds  
     $JWTExpiration = [math]::Round($JWTExpirationTimeSpan,0)  
          
     # Create JWT validity start timestamp  
     $NotBeforeExpirationTimeSpan = (New-TimeSpan -Start $StartDate -End ((Get-Date).ToUniversalTime())).TotalSeconds  
     $NotBefore = [math]::Round($NotBeforeExpirationTimeSpan,0)  
          
     # Create JWT header  
     $JWTHeader = @{  
         alg = "RS256"  
         typ = "JWT"  
         # Use the CertificateBase64Hash and replace/strip to match web encoding of base64  
         x5t = $CertificateBase64Hash -replace '\+','-' -replace '/','_' -replace '='  
     }  
          
     # Create JWT payload  
     $JWTPayLoad = @{  
         # What endpoint is allowed to use this JWT  
         aud = "https://login.microsoftonline.com/$TenantName/oauth2/token"  
          
         # Expiration timestamp  
         exp = $JWTExpiration  
          
         # Issuer = your application  
         iss = $AppId  
          
         # JWT ID: random guid  
         jti = [guid]::NewGuid()  
          
         # Not to be used before  
         nbf = $NotBefore  
          
         # JWT Subject  
         sub = $AppId  
     }  
          
     # Convert header and payload to base64  
     $JWTHeaderToByte = [System.Text.Encoding]::UTF8.GetBytes(($JWTHeader | ConvertTo-Json))  
     $EncodedHeader = [System.Convert]::ToBase64String($JWTHeaderToByte)  
          
     $JWTPayLoadToByte =  [System.Text.Encoding]::UTF8.GetBytes(($JWTPayload | ConvertTo-Json))  
     $EncodedPayload = [System.Convert]::ToBase64String($JWTPayLoadToByte)  
          
     # Join header and Payload with "." to create a valid (unsigned) JWT  
     $JWT = $EncodedHeader + "." + $EncodedPayload  
          
     # Get the private key object of your certificate  
     $PrivateKey = ([System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($Certificate))  
          
     # Define RSA signature and hashing algorithm  
     $RSAPadding = [Security.Cryptography.RSASignaturePadding]::Pkcs1  
     $HashAlgorithm = [Security.Cryptography.HashAlgorithmName]::SHA256  
          
          
     # Create a signature of the JWT  
     $Signature = [Convert]::ToBase64String(  
         $PrivateKey.SignData([System.Text.Encoding]::UTF8.GetBytes($JWT),$HashAlgorithm,$RSAPadding)  
     ) -replace '\+','-' -replace '/','_' -replace '='  
          
     # Join the signature to the JWT with "."  
     $JWT = $JWT + "." + $Signature  
          
     # Create a hash with body parameters  
     $Body = @{  
         client_id = $AppId  
         client_assertion = $JWT  
         client_assertion_type = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"  
         scope = $Scope  
         grant_type = "password"  
         username = "xxx@demooutlook.onmicrosoft.com"  
         password = "xxxx"  
          
     }  
          
     $Url = "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token"  
          
     # Use the self-generated JWT as Authorization  
     $Header = @{  
         Authorization = "Bearer $JWT"  
     }  
          
     # Splat the parameters for Invoke-Restmethod for cleaner code  
     $PostSplat = @{  
         ContentType = 'application/x-www-form-urlencoded'  
         Method = 'POST'  
         Body = $Body  
         Uri = $Url  
         Headers = $Header  
     }  
          
     $Request = Invoke-RestMethod @PostSplat  
     # View access_token  
     $token = $Request.access_token  
    
    0 comments No comments