SharePoint 2013 Cross-Domain Library Scenario: Authentication Mechanism for Remote App - sharepoint

I have a SharePoint provider-hosted app that exposes a Web API endpoint. I'm using this endpoint as a middle man to call a secured external web service. I want to make calls to my Web API endpoint via javascript in a SharePoint Page (a Publishing Page) in my host web. Since this is a cross-domain call, I'm utilizing SharePoint's cross domain library (SP.RequestExecutor.js). I followed the steps in this article to create my custom proxy page that is required by the cross-domain library. Everything works fine. I can call my service via SP.RequestExecutor with no issues. Now, I just want to require authentication for accessing the Web API endpoint.
The article that I reference states that I'm responsible for the authentication mechanism. I just can't seem to come up with a really secure one and there are literally no examples on the web. I'd really like to leverage the identity of the SharePoint user somehow since only SharePoint users will be hitting the Web API endpoint, I just can't figure out how. SP.RequestExecutor won't let me pass the SPHostUrl querystring parameter when hitting the endpoint, so that's why I can't use the trust relationship between SharePoint and remote app. Does anybody have some ideas for authentication in this scenario that would work well when using SP.RequestExecutor to call my endpoint?

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:
The SharePoint Cross Domain Library
The SharePoint Web Proxy
Create a custom proxy page.
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 = 31232
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 any of the checks fails then it responds with 401 result.

Related

How do I view the User Agent of outgoing requests to SharePoint made from my Azure Web Application?

I'm following the guidance from Microsoft on decorating traffic to avoid throttling. This guidance specifies that you set a specific User Agent on outgoing requests from the application to SharePoint via CSOM when making API calls.
I have made this change, and would like to now verify that the User Agent is in fact appropriately modified on API calls to SharePoint.
My provider-hosted application is hosted on Azure, and while I can see CSOM calls to SharePoint (https://(mytenancy).sharepoint.com/sites/(mysite)/_vti_bin/client.svc/ProcessQuery) in the Application Map as a dependency, I can't figure out how to view the actual outbound request so as to examine it for the User Agent string.
How can I view the User Agent string on outbound requests from my Azure application? How can I verify that I've set the User Agent string on my calls to the SharePoint API?
Additional Info:
I have tried running the application as well on localhost and employed the use of Wireshark and Fiddler, but I'm only picking up requests to client.svc/ProcessQuery with my browser's User Agent string. I get the feeling I'm not even seeing all the CSOM requests.
User Agent is used for determining browser and browser version , however it seems to be dropped in processing and not available in search or export.
Please have a look at below links for further details.
UserAgent not transfered
UserAgent, Lat/Long and URL expansion data removed
Hope this information helps.
To provide feedback for the team on this specific feature , please refer to this link and upvote.
Support for viewing Raw body requests is something being considered by the Product team. Please refer here for more details on it.

Access sharepoint online list from mobile app

I am facing a problem where I need to show the data of sharepoint online list in a mobile app. mobile app can access the data via rest api. but how can i find the sharepoint context as app is external and sits outside boundary of sharepoint.
Any link to the solution or sample code will be highly appreciated.
You need to write REST API which will access SharePoint list data using managed Client object model(CSOM) and return data as JSON.
Following are the detailed steps:
1. Create REST API to access SharePoint list using CSOM
2. Call API from mobile app and include username and password in header in encrypted format
3. Inside API, Decrypt header and use that Username and Password to access SharePoint list.
Sample code for API:

Azure Mobile Services : GET operation from table

I'm trying to get data from a table I created in Azure Mobile Services.
When I setup the service, I created a new database to go along with it.
I've added a row of data to my table called TODOITEM and can query this row of data fine from the db admin tool on Azure.
Now what I'm trying to do is run a GET request on this table, as documented here...
https://msdn.microsoft.com/en-us/library/azure/jj677199.aspx
I am using Fiddler and trying to send the following request with HTTP 1.1...
https://mobilemeshtest.azure-mobile.net/tables/todoitem
X-ZUMO-APPLICATION: my azure mobile services key
X-ZUMO-AUTH: my facebook authentication key
Host: mobilemeshtest.azure-mobile.net
No matter what I try, all I get back is a 404 not found.
I'm even copying what the guy did in a PluralSight video tutorial on Azure Mobile Services, and he gets a correct 200 response.
I can't see what I'm doing wrong.
404 is pretty simple. The url is wrong.
Propably you have not set your Controller right.
If your Controller is named SomethingController then the route is /tables/Something assuming you havent customized the default Routing methods
Application Key and Authorization Key is not needed if you haven't specified the corresponding authorization attribute
for example : [AuthorizeLevel(AuthorizationLevel.User)]
RESOLVED : I was using a .NET backend, it seems one has to publish their data objects and controllers first using Visual Studio.
This blog post has a good example on how to achieve this.
If I was using the Javascript backend option, the controllers are automatically setup for you.

MVC 5 security measures

I am developing a MVC 5 internet application and have some questions in relation to security.
What security measures do I need to manually implement to ensure that my internet application is secure?
This is what I have so far:
[ValidateAntiForgeryToken] attributes on each HttpPost function
Sanitizer.GetSafeHtml function on a model attribute that has HTML
data
Identity 2.1 for authentication and authorization
Thanks in advance.
UPDATE
The application is a simple MVC internet application with a web service hosted on Azure. I am using Entity Framework 6, Web API 2.0 and MVC 5. What relevant information can I give you?
That would cover you for XSRF and Stored XSS. You should also check for:
DOM XSS in javascript (when modifying the DOM using data from query string for example).
JSON hijacking
code injection (SQL injection if you are using a SQL DB for example)
enforce HTTPS for login (both login form and login post)
... etc ...
The most common vulnerabilities are not technical bugs, for example you should:
Reduce the data you trust from the client. For example, if you have a shopping cart, it may look like a good idea to put the price as a hidden field in the buying form, so the server does not need to go to the DB to get the price for that product, but then the user may tamper the form and buy at $0, or even -$100.
Check that the user cannot fool multi-step forms, that for example allow him to order products without going through the payment page.
Check that if your application returns files by name, cannot do something like http://example.com/Home/GetFile?filename=..\..\Web.config.
Check that you are enforcing authorization BESIDES authentication. For example, a user 123 may be authenticated, but not authorized to check user 456 profile.
... etc ...
The best thing to do, is check the OSWASP page : https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project

Accessing Dynamics CRM 2011 data through a website using only HTML5, JS, and CSS

Looking to create a completely external portal using only HTML5, JS, and CSS to show CRM 2011 data. It does not look like I can use REST or SOAP because they cannot authenticate externally. Does anyone know how I would do this?
Thanks!
To do this, your OrganizationData.svc service would need to be externally accessible, and it would need to function without authentication (or, your authentication would need to happen within your javascript - where the end user would be able to read your source code). Either way is not a wise idea, since all of your data would be visible to the world!
If you are only dealing with internal authenticated users, read up on the oDATA endpoint.
If you want to deal with external and/or unauthenticated users, you'll need to find another way to do this that does all of the data filtering & authorization control you need.
I think we normally achieve this using a intermediary integration service. You could have a service which has access to the Org service through conventional CRM authentication, and which provides a number of methods which can be called anonymously (or by custom security) by client code.
For example, a web page calls the 'int' service's 'getContact' method, passing an email address of the user. The 'int' service validates the user's email address and then retrieves the required data from CRM's org service, using credentials stored in a config file (a CRM user with sufficient permissions to serve the 'int' service's methods). The 'int' service then parses the data and returns it to the client code - which has no knowledge of CRM's existence - perhaps as JSON for usability.

Resources