1

I've created an Auth. Provider for Microsoft SharePoint and after visiting the OAuth-Only Initialization URL and running a callout using that Auth. Provider, everything works as expected.

I've created a class that makes callouts to SharePoint that creates folders, files etc... This works great when I'm the one making the callouts. However, when another User makes the callouts (initiated from a Trigger), I'm getting an error:

First error: Argument cannot be null or empty.

This is because of the following method:

private static final AuthProvider AUTH_PROVIDER = [SELECT Id FROM AuthProvider WHERE ProviderType = 'MicrosoftACS' LIMIT 1];

public static String GetAccessToken() {
    return Auth.AuthToken.getAccessToken(AUTH_PROVIDER.Id, 'Microsoft Access Control Service');
}

This is because I've visited and authorised myself from the initialisation URL. However, I don't really need/want every other User having doing this and, instead, would prefer the app to use just one "account" to do this.

I've tried doing System.runAs as an admin User that is authorised but Salesforce completely ignores this, my guess is because System.runAs only works in unit tests. I can't see any way to use a specifc User's Auth. Provider credentials, nor get a specific User's access token programmatically. I can't see any way of programatically "logging in as" a specific User in Apex either.

Is there a way around this using an Auth. Provider or would I have to use Apex to get the token by posting a set of credentials to SharePoint from Apex?

  • IS your apex class marked without sharing? – Mohith Shrivastava Jan 15 '18 at 17:04
  • @MohithShrivastava It's not marked as anything with respect to that. Might defining that help? – Dan Jones Jan 15 '18 at 17:06
  • Looks like the methods are specific to logged in user only – Mohith Shrivastava Jan 15 '18 at 17:10
  • 1
    @MohithShrivastava I think that's the case at least with Apex. Looking at a few things as a workaround. I'd really like to try to use Auth. Providers though! It only seems to work if I log in as a user and visit the initialisation link though. :/ It does make sense why though. – Dan Jones Jan 15 '18 at 17:21
  • 1
    @MohithShrivastava I've got a programmatic solution below as an answer. Maybe Auth. Providers can't be used without self authorising? That would make sense although in this instance I'd really like to use a UserPassword type flow. The hunt continues! – Dan Jones Jan 15 '18 at 17:59
-1

Here's a workaround solution for this type of use case. I've written a method that has the following:

String data = 'grant_type=client_credentials';
data += '&username=<User Name>@<Company Name>.com';
data += '&password=<Password>';
data += '&client_id=<Client Id>';
data += '&resource=00000000-0000-0aa0-aa00-000000000000/<Company Name>.sharepoint.com@<Tenant Id>';
data += '&client_secret=<Client Secret>';

Http http = new Http();
HttpResponse response;

HttpRequest request = new HttpRequest();
request.setEndpoint('https://accounts.accesscontrol.windows.net/<Company Name>.onmicrosoft.com/tokens/OAuth/2');
request.setMethod('POST');
request.setHeader('content-type', 'application/x-www-form-urlencoded');
request.setBody(data);
request.setTimeout(60000);

response = http.send(request);

System.debug(response.getBody());

This has been sanitised, but should give you an idea replacing things like <User Name> and <Client Id> with those generated from the app in SharePoint. But, this does return some JSON like below when executed anonymously.

{  
   "token_type":"Bearer",
   "expires_in":"3599",
   "not_before":"1516037987",
   "expires_on":"1516041887",
   "resource":"00000000-0000-0aa0-aa00-000000000000/<Comapny Name>.sharepoint.com@<Tenant Id>",
   "access_token":"<Access Token>"
}

Obviously, sanitised again. But rather than seeing <Access Token> you'll see the world's longest String which is essentially the key you'll need for headers when making requests:

request.setHeader('Bearer: ' + accessToken);

So, this is how we'd use Apex to make a callout to SharePoint to get an access token using a specific SharePoint User's credentials. Hopefully this helps anyway with any similar issues. I'll continue seeing if we can't leverage the use of Auth. Providers or mark this as an answer in a couple of days.

  • The custom solution was always possible like this but with auth provider wondering if there is a way – Mohith Shrivastava Jan 15 '18 at 18:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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