I want to use REST API with SharePoint, I'm not here talking about using graph API.
I created an Azure Application and selected SharePoint API to set authorizations:
I created secret for OAuth 2.0. Here are the authorizations I set for an application. it should not involve any user account ...
Now in a java application, for authentication, I'm using msal4j dependency:
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>msal4j</artifactId>
<version>1.17.2</version>
</dependency>
I also have an AuthProviderRequest object:
@Test
@Order(2)
void restAuthenticate() throws Exception {
// HttpConnectionProvider
IAuthenticationResult result = sharepointManager.authenticate(restGraphProviderRequest);
System.out.println(result.accessToken());
String endpoint = "https://{{tenantName}}.sharepoint.com/sites/{{siteName}}/_api/web/lists/GetByTitle('{{libName}}')/items";
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(endpoint))
.header(RequestConstants.HTTP_HEADER_AUTHORIZATION,
RequestConstants.HTTP_HEADER_AUTHORIZATION_BEARER_PREFIX + result.accessToken()) //
.build();
HttpClient client = HttpClient.newBuilder().build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response);
}
Here my TENANT_AUTHORITY = "https://login.microsoftonline.com/{{ sharepointTenantId }}"; And my SCOPE_MS_GRAPH_DEFAULT = "https://{{ tenantName }}.sharepoint.com/.default";
if i run my unit test i do retrieve a JWT token... I decoded the token to check if it looked correct.. for a SharePoint graph application aud should be : "https://graph.microsoft.com",
{
"aud": "00000003-0000-0ff1-ce00-000000000000",
"iss": "https://sts.windows.net/{{ tenantId }}/",
"iat": 1731857052,
"nbf": 1731857052,
"exp": 1731860952,
"aio": "k2BgYCgvOXulrW5bcsKiANamCU47NKdfuaHRkb3ilVrLSZE73MYA",
"app_displayname": "sharepointRest ",
"appid": "3a0aba82-2805-4dd7-b9f9-41c854199262",
"appidacr": "1",
"idp": "https://sts.windows.net/{{ tenantId }}/",
"idtyp": "app",
"oid": "...",
"rh": "...",
"roles": [
"Sites.Manage.All",
"Sites.Read.All",
"Sites.ReadWrite.All",
"Sites.FullControl.All"
],
"sid": "...",
"sub": "...",
"tid": "...",
"uti": "...",
"ver": "1.0",
"xms_idrel": "7 24",
"xms_pftexp": 1731947352
}
it seems here that i can do have a valid token i could use with rest API in SharePoint.
Here is the response:
- When running unit test i have a 401 response.
- When testing Url with tokenn i have: Unsupported app only token.
I tried to add authorization to application in Graph Explorer with a POST request to the following endpoint: https://graph.microsoft.com/v1.0/sites/{{ tenantName }}.sharepoint.com:/sites/{{ siteName }}
with following payload:
{
"roles": [
"write",
"read",
"delete",
"owner"
],
"grantee": {
"@odata.type": "microsoft.graph.aadApplication",
"id": "3a0aba82-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
}
After update:
- When running unit test i have a 401 response.
- When testing Url with token i have: Unsupported app only token.
I also tried to use OKHttp to authenticate:
public class RestAuth {
// Azure AD and SharePoint Configurations
private static final String CLIENT_ID = "myClientId";
private static final String CLIENT_SECRET = "myClientSecret";
private static final String TENANT_ID = "myTenantId";
private static final String RESOURCE = "https://myTenantName.sharepoint.com";
private static final String SITE_NAME = "mySite";
// OkHttp client
private static final OkHttpClient client = new OkHttpClient();
public static void main(String[] args) {
try {
String accessToken = getAccessToken();
System.out.println(accessToken);
if (accessToken != null) {
getSiteLists(accessToken);
} else {
System.out.println("Failed to fetch the access token.");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 1. Retrieve an Access Token
private static String getAccessToken() throws IOException {
String tokenEndpoint = String.format("https://login.microsoftonline.com/%s/oauth2/token", TENANT_ID);
RequestBody formBody = new FormBody.Builder()
.add("grant_type", "client_credentials")
.add("client_id", CLIENT_ID)
.add("client_secret", CLIENT_SECRET)
.add("resource", RESOURCE)
.build();
Request request = new Request.Builder()
.url(tokenEndpoint)
.post(formBody)
.header("Content-Type", "application/x-www-form-urlencoded")
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
String responseBody = response.body().string();
JSONObject json = new JSONObject(responseBody);
return json.getString("access_token"); // Extract the access token
} else {
System.err.println("Failed to get access token: " + response.code() + " - " + response.message());
System.err.println(response.body().string());
return null;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 2. Get the Lists from the SharePoint Site
private static void getSiteLists(String accessToken) {
String siteUrl = String.format("%s/sites/%s/_api/web/lists", RESOURCE, SITE_NAME);
Request request = new Request.Builder()
.url(siteUrl)
.get()
.header("Authorization", "Bearer " + accessToken)
.header("Accept", "application/json;odata=verbose")
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
String responseBody = response.body().string();
System.out.println("Site Lists: " + responseBody);
} else {
System.err.println("Failed to fetch site lists: " + response.code() + " - " + response.message());
System.err.println(response.body().string());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
I obtain: Failed to fetch site lists: 401 - Unsupported app only token.
the decoded token is absolutely similar to previous one: same aud, iss, roles...
I checked access control in admin SharePoint center :
- for unmanaged devices, i set authorizations
- i activated access for legacy authentication
I really don't get what is wrong here. thanks