Issues with access Sharepoint v1 API (Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown.)

FNU LNU 20 Reputation points
2023-09-26T21:39:12.2333333+00:00

Hey, perhaps this was answered dozen of times already, however I keep getting

Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown.

when trying to access Sharepoint v1 endpoints like https://<name>.sharepoint.com/_api/web/lists and I believe the issue is in permissions I granted (or rather not granted).

What I did so far:

  1. Created an App in AD
  2. Created secret in AD: User's image
  3. Granted Application permissions to my app - I read in some other topics that delegated permissions do not work:
    User's image
  4. Given the data User's image
  5. Now I'm sending a request for token using v1 Oauth2:
    https://login.microsoftonline.com/<Directory (tenant) ID>/oauth2/token with the following body:
client_id:<Application (client) ID>
client_secret:<Client secret Value from step #2> ===> what's secret ID there? 
grant_type:client_credentials
scope:https://<site>.sharepoint.com/.default
  1. I'm getting a valid bearer token, which I then use for endpoint https://<name>.sharepoint.com/_api/web/lists
  2. I get 401 error with
{"error_description":"Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown."}

Again, I understand that I clearly miss a permission, but no guide I found so far say how exactly to set them.
I don't want to use Graph API and want to stick to V1 of Sharepoint API. Could you help me understand what I do wrong and how to fix it?

Thanks!

Microsoft 365 and Office | SharePoint | For business | Windows
0 comments No comments
{count} votes

Accepted answer
  1. RaytheonXie_MSFT 40,471 Reputation points Microsoft External Staff
    2023-09-28T01:30:07.7333333+00:00

    Hi @FNU LNU,

    I'm glad to hear you solve the problem ,if you have any issue about SharePoint, you are welcome to raise a ticket in this forum.

    By the way, since the Microsoft Q&A community has a policy that "The question author cannot accept their own answer. They can only accept answers by others." and according to the scenario introduced here: Answering your own questions on Microsoft Q&A, I would make a brief summary of this thread:

    [Issues with access Sharepoint v1 API]

    Issue Symptom:

    When access Sharepoint v1 endpoints by Azure ad, the request will return {"error_description":"Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown."}

    Solution:

    #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(2)).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"
    
    
    #Copy
    # 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 = "xxxxxxxxxxxxxxxxx"
    password = "xxxxxxxxxxx"
    
    }
    
    $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
    

    Here is the article for reference

    https://learn.microsoft.com/en-us/answers/questions/1063462/generate-bearer-token-active-directory-certificate?page=1&orderby=Helpful&comment=answer-1064918#newest-answer-comment


    You could click the "Accept Answer" button for this summary to close this thread, and this can make it easier for other community member's to see the useful information when reading this thread. Thanks for your understanding!

    0 comments No comments

2 additional answers

Sort by: Most helpful
  1. RaytheonXie_MSFT 40,471 Reputation points Microsoft External Staff
    2023-09-27T02:13:18.6466667+00:00

    Hi @FNU LNU,

    The error message seems that resource parameter in the token endpoint call was set incorrectly. You could refer to the correct token endpoint call for a V1 app to call SharePoint Online looks like the following:

    POST https://login.microsoftonline.com/<TARGET-TENANT-ID OR NAME>/oauth2/token
    
    client_id= <Application ID from Azure Portal>
    grant_type=client_credentials
    resource= https://<TARGET-TENANT-NAME>.sharepoint.com
    client_assertion_type= urn:ietf:params:oauth:client-assertion-type:jwt-bearer
    client_assertion= <See Link Above to create assertion>
    
    
    

    The links above omit how to calculate the x5t value for the certificate JWT. You can use this:

    echo $(openssl x509 -in certificate.pem -fingerprint -noout) | sed 's/SHA1 Fingerprint=//g' | sed 's/://g' | xxd -r -ps | base64
    

    which I got from here: How to obtain value of "x5t" using Certificate credentials for application authentication

    Here is also some nice article for you to reference

    https://blog.mastykarz.nl/azure-ad-app-only-access-token-using-certificate-dotnet-core/

    https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens#payload-claims


    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.


  2. FNU LNU 20 Reputation points
    2023-09-27T17:33:16.9933333+00:00
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.