2

What's a good authentication mechanism to use in my remote app that is accessed via cross-domain library (SP.RequestExecutor.js) javascript code in a publishing SharePoint page in my host web?

Background:
I'm developing a solution for SharePoint Online where I need to access data, from a secured web service, for displaying directly on a publishing page. The App Part is not a good option for me because I need a responsive UI and IFrames don't work well in responsive UI scenarios. So, I've created a provider-hosted app that hosts an ASP.Net Web API endpoint. The Web API controller, for that endpoint, is what makes calls to the secured web service for the data I need. The flow is: the cross-domain library javascript code in the publishing page calls the provider-hosted app web api endpoint which then calls the secured web service. There is an article here on msdn just for this scenario.

However, the article leaves out options or ideas on the authentication mechanism to use for the provider-hosted app. It just states that it is the responsibility of the developer to implement the authentication mechanism. Has anybody implemented a solution like this that includes authentication?

  • I'm also interested in this scenario, and like you, I cannot find an example that implements authentication. – Jesús López Aug 27 '15 at 9:32
1

To summarize, you have the following scenario:

  • You have a SharePoint add in (SharePoint App).
  • A page on the add in web (app web) needs to call an external service.
  • You have an external service implemented using ASP.NET Web Api.
  • The external service needs authentication.

The first issue you need to address is the Same Origin Policy. To overcome this issue, Microsoft documentation describes three options as you know:

However, I think the best bet is to use CORS because it is a W3C recommendation, it's simpler, easier to use, comprehensive, hack-free, and specially: ASP.NET Web API 2 supports CORS.

The other issue to address is authentication. Unfortunatelly Microsoft documentation doesn't provide any example nor hint, it simply tells you it's your responsability. Searching the web doesn't provide any example or hint either. So I conclude: You need to invent an authentication mechanism. Several authentication protocols are based on chalenges such as NTLM authentication. Email address validation uses also a chalenge, it chalenges you to read an email sent to the emails address. I propose you a mechanism based on the same paradigm. I chalenge the user to create a specific list item on the SharePoint App Web (add in). So we need a list on the App Web called AutenticationChalenges with the following fields:

  • ID: autoincrement built in field.
  • ChanlengeValue: single line of text.
  • CreatedBy: user built in field.

The authentication proccess has the following steps:

1.- JavaScript on a App Web page calls https://myexternalservice.mycompay.com/create-chalenge web api endpoint with the following payload:

{
    "UserId": "3432" // the SharePoint UserId
    "AppWebUrl": "https://mysharpointonline-e849d5bbe0ddc2.sharepoint.com/MySharePointApp"
    "HostWebUrl": "https://mysharepointonline.sharepoint.com/MySharePointApp"
}

2.- The external server generates two 16-32 bytes random values: ChalengeValue and CorrelationToken, and it inserts them along with the payload into some storage such a table like the following:

CREATE SEQUENCE authentication_chalenges_authentication_chalenge_id_seq
START WITH 1;

CREATE TABLE authentication_chalenges
(
    authentication_chalenge_id int NOT NULL DEFAULT NEXT VALUE FOR authentication_chalenges_authentication_chalenge_id_seq
    CONSTRAINT authentication_chalenges_authentication_chalenge_id_seq PRIMARY KEY,
    user_id int NOT NULL,
    correlation_token binary(16) NOT NULL,
    chalenge_value binary(16) NOT NULL,
    app_web_url varchar(4000) NOT NULL,
    host_web_url varchar(4000) NULL,
    created_timestamp datetime NOT NULL
)

Then, the server returns the following result:

{
    "ChalengeId": 31232, // the value of authentication_chalenge_id column of the table
    "CorrelationToken" : "95AE040FE6844345B36B5E33BE03437F",
    "ChalengeValue" : "E38A022B7F744D3BA8C676259AECD607"

}

3.- JavaScript on the App Web page inserts an item into the AuthenticationChanlenges list setting ChalengeValue column = "E38A022B7F744D3BA8C676259AECD607" and calls https://myexternalservice.mycompay.com/login web api endpoint with the following payload:

{
    "ChalengeItemId" : 4133, // the ID column of the AuthenticationChalenges SharePoint list
    "ChalengeId" : 31232,
    "CorrelationToken" : "95AE040FE6844345B36B5E33BE03437F",
    "ChalengeValue" : "E38A022B7F744D3BA8C676259AECD607"
}

4.- The external services server look for the row on chalenges table:

SELECT * FROM authentication_chalenges WHERE authentication_chalenge_id = 4133 

If the query returns a row and CorrelationToken and ChanlengeValue match, and it has not expired yet, the server connects to sharepoint looking for the item with ID = 4133 on the AuhenticationChalenges list, ands checks that ChalengeValue is equals to E38A022B7F744D3BA8C676259AECD607, and finally it checks that CreatedBy user id is equals to 3432. If all checks success, then it responds with and ok response and sets the authentication cookie. If not all checks sucess then it responds with 401 result.

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.