0

The problem I have is that I am unable to access the sharepoint REST Api with 401 : [{"error":{"code":"accessDenied","message":"There has been an error authenticating the request."}}] and I cannot figure out why.

The authentication steps I tried were:

Authentication by secret using MSAL4J:

IClientCredential clientCredential = ClientCredentialFactory.createFromSecret(clientSecret);
ConfidentialClientApplication app = ConfidentialClientApplication.builder(clientId, clientCredential).authority("https://login.microsoftonline.com/" + tenantId").build();
ClientCredentialParameters parameters = ClientCredentialParameters.builder(Collections.singleton("https://" + tenantName + ".sharepoint.com/.default")).build();
IAuthenticationResult result = app.acquireToken(parameters).join();

Authentication by certificate using MSAL4J:

IClientCredential clientCredential;
try (FileInputStream certStream = new FileInputStream(certPath)) {
    clientCredential = ClientCredentialFactory.createFromCertificate(certStream, certPassword);
}
ConfidentialClientApplication app = ConfidentialClientApplication.builder(clientId, clientCredential).authority("https://login.microsoftonline.com/" + tenantId").build();
ClientCredentialParameters parameters = ClientCredentialParameters.builder(Collections.singleton("https://" + tenantName + ".sharepoint.com/.default")).build();
IAuthenticationResult result = app.acquireToken(parameters).join();

Authentication by secret using REST API:

var headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("client_id", clientID);
body.add("scope", "https://" + tenantName + ".sharepoint.com/.default");
body.add("client_secret", clientSecret);
body.add("grant_type", "client_credentials");

var entity = new HttpEntity<>(body, headers);

ResponseEntity<Map> response = restTemplate.exchange("https://login.microsoftonline.com/" + tenantId + "/oauth2/token", HttpMethod.POST, entity, Map.class);

In all cases I get the access token but then the GET to 'https://" + tenantName + ".sharepoint.com/_api/v2.0/web/title' fails. I am using this request:

HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(accessToken);
headers.set("Accept", "application/json;odata=verbose");
HttpEntity<String> entity = new HttpEntity<>(headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);

The app is registered, all permissions are granted for app-only and granted by administrator.

1 Answer 1

0

Access denied is the expected result if you are using a registered Entra ID application with a client secret. Due to security reinforcement, only certificate will work.

FAQ: Can I use other means besides certificates for realizing app-only access for my Azure AD app? No, all other options are blocked by SharePoint Online and will result in an Access Denied message.

Source: Granting access via Azure AD App-Only

Try to generate a new certificate for your application with application permissions Sites.FullControl.All and use it to connect to SharePoint:

$password = (ConvertTo-SecureString -AsPlainText 'myprivatekeypassword' -Force)
Connect-PnPOnline -Url "contoso.sharepoint.com" -ClientId 6c5c98c7-e05a-4a0f-bcfa-0cfc65aa1f28 -CertificatePath 'c:\mycertificate.pfx' -CertificatePassword $password  -Tenant 'contoso.onmicrosoft.com'

Reference: Connect-PnPOnline

app permissions

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.