Search code examples
microsoft-graph-apimicrosoft-graph-sdks

Failing to authenticate Microsoft Graph Java/Kotlin Client correctly


I have a bash script that uses curl and the microsoft graph api to get what I want. But I fail to translate this script into Kotlin code with the MS Java Graph Api SDK.

The working script is:

export CLIENT_ID='XXX' 
export CLIENT_SECRET='XXX' 
export TENANT_ID='XXX'
exoprt SCOPE='api://ourApp/2023/CustomScope'
export TOKEN=`curl \
    -d grant_type=client_credentials \
    -d client_id=$CLIENT_ID \
    -d client_secret=$CLIENT_SECRET \
    -d scope=$SCOPE \
    -d resource=https://graph.microsoft.com \
    https://login.microsoftonline.com/$TENANT_ID/oauth2/token \
    | jq -j .access_token`
curl -X GET \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    https://graph.microsoft.com/v1.0/servicePrincipals/XXX/appRoleAssignedTo \
    | jq .

I get a list of role assignments to my app. (The api with correct permissions is exposed under that scope)

Now I'm trying to recreate this in Kotlin using the docs: https://learn.microsoft.com/en-us/graph/sdks/choose-authentication-providers?tabs=csharp#client-credentials-provider

val clientSecretCredential = ClientSecretCredentialBuilder()
    .clientId(appId)
    .clientSecret(secret)
    .tenantId(tenantId)
    .build()

client = GraphServiceClient(
    clientSecretCredential,
    "api://ourApp/2023/CustomScope"
)

val result = client.servicePrincipals().byServicePrincipalId(appObjectId).get().appRoleAssignedTo

If I fire the request with this client I get the error

com.microsoft.aad.msal4j.MsalServiceException: AADSTS1002012: The provided value for scope api://drupalwiki/2023/SyncEverything openid profile offline_access is not valid. Client credential flows must have a scope value with /.default suffixed to the resource identifier (application ID URI)

If I use "https://graph.microsoft.com/.default" as a scope, I only get an empty list. I also cannot rename our scope to e.g "api://ourApp/2023/.default" in the end because the Azure UI says this name is invalid. Apart from that, since the bash script workds, I would just like to initialize the client in the same way, is that possible?

Chees and thanks!


Solution

  • That's because appRoleAssignedTo is not a property, but a relationship, so you need to request for appRoleAssignedTo like this

    val result = client.servicePrincipals().byServicePrincipalId(appObjectId).appRoleAssignedTo().get();
    

    The scope must be https://graph.microsoft.com/.default