asp.net mvc authentication when call from client app - asp.net-mvc

I use asp.net mvc controller instead of Web Service in my project.
When I call the controller from my client app,there will be a authentication problem. If I use Web Service ,I can use SOAP Header , but now in asp.net mvc, There is no soap header.
Please help.
I am really know a little about the web security.

Normal way of doing this when you come to http services is to pass it in authorization header in following format (if you are doing request from fiddler)
Authorization: Basic user123:pass123
user123:pass123 string is normally base64 encoded and you have to decode it on server side, check it against user store and authenticate the user. One example can be found here

You have several options.
Use a request header to contain some security token.
Include security tokens in the message that you send in the request body.
If your application uses something like Forms Authentication, you can ask consumers to call a login action, then grab the Forms Auth cookie and include that cookie in subsequent calls.

Since you are not using soap. You may use a simple http way. Which means you start a HttpRequest and handle result via HttpResponse. Thus you have to simulate a authenticate action as signing in from web browser.
You need to get the security token or cookie from the reponse. And put them into your following request. Thus your controller will recognize the request's identity.

Related

Q: Token based auth API and Javascript, can you protect other clientside files from being accessed?

Question
If you would use a similar setup as the following examples:
Simple WebAPI
Javascript OIDCClient and usermanager
Would it be possible to protect other clientside files from being accessed? Say for example i have a directory with certain files which you need a certain role to be able to access them.
Would it be possible to protect my SPA from being accessed before logging in?
Or is there a better solution which would have you end up with a protected api, folders/files on a server, SPA and a silent renew mechanism like there is in the OIDCClient?
#dmccaffery helped me out by answering my question, here is his answer for those of you who are interested.
To summarize using the OIDCClient for an SPA is certainly the way to go. Exposing stuff which needs authorization should be done by using an API. Protecting parts of your Angular App can be done using a Route guard.
The way it works is as follows:
The access token is either a JWT or a bearer token (usually) and is
added by the oidc client to every HTTP request in an authorization
header — when a web API receives a reques, the bearer token
authorization middleware will parse this HTTP header and will call the
token introspection endpoint (and potentially the user info endpoint)
to have the token validated and the users claims retrieved… if the
token was manipulated by the client, it will not be valid, and an HTTP
error will be returned (usually a 403). If the token was valid, a
claims identity is created and assigned to the http request context.
The API will now have a thread with an identity already assigned to it
that represents that user.
Also he pointed out 2 pluralsight courses which would probably be useful:
https://www.pluralsight.com/courses/building-securing-restful-api-aspdotnet
https://www.pluralsight.com/courses/oauth2-openid-connect-angular-aspdotnet

Authenticate a SAML2 (P?) token in body in asp.net mvc

I have an ASP.NET MVC application which currently allows users to connect via two ThinkTecture IDP servers. The MVC app trusts both of these IDP servers and it authenticates users perfectly.
The current setup uses the < System.IdentityModel.Services.WSFederationAuthenticationModule > and the < System.IdentityModel.Services.SessionAuthenticationModule > in the < modules > section in the web.config to handle these.
We now have a new party who want to authenticate their users by sending us a SAML v2 token, but the MVC app doesn't seem to recognise it.
I've compared the POST response from both the IDP server (SAML1) and the new login server (SAML2) and there are some subtle differences, which maybe causing problems.
The IDP server seems to use < trust:RequestedSecurityToken > attributes to wrap to < saml:Assertion >. Whereas the new client sends a POST request body containing < saml >< samlp:Response >
My questions are:
1)Is this new < samlp:Response > a SAML2P version which is not supported by Microsoft WIF? Or is it just interested in the < saml:Assertion > element?
2) Where will WIF look for the SAML token? POST Body? Authentication header (Bearer)?
3)Currently, when the user is not authenticated, it redirects them to their local IDP servers, they login and it returns the SAML response, with is then picked up. But the new client, will simply pass a request to view a page with the SAML token (true single-sign-on). I wonder if this difference is causing problems. I currently manually handle redirects to the user's local IDP, so have tried to turn this off for the new client.
EDIT
After much digging...
SAML2 Protocol is not supported by Microsoft WIF and ever likely to be.
SAML2 Protocol messages are usually as a form parameter (saml= < saml:Response>< etc... within the body of the HTTP POST. In my case it didn't use the standard parameter format of (saml=), the XML was just directly inline in the HTTP POST body.
Indeed its not officially supported but you can do something like this to make it work.
http://blogs.msdn.com/b/bradleycotier/archive/2012/10/28/saml-2-0-tokens-and-wif-bridging-the-divide.aspx
AFAIK, samlp is a protocol that is not (yet?) supported by WIF. It is a replacement for the querystring parameters used in WS-Federation. You should look for third party extensions (How should I implement SAMLP 2.0 in an ASP.NET MVC 4 service provider?). Since I haven't used any myself I cananot give further advice.
The best solution I've found is the Kentor IT - AuthServices.
It handles digitally signed SAML tokens.
Although it will not work out of the box for me, as my third party seem to be using a non-standard binding technique (rather than the standard HTTP Post or HTTP Redirect), so I will have to build my own custom-binding.

Why does the Implicit Authorization Grant in OAuth require a "Web-hosted Client Resource"?

I am referring to the Figure 4 of the following link to understand the working behind it:
https://tools.ietf.org/id/draft-ietf-oauth-v2-31.html#grant-implicit
I cannot understand why there's a need for Web-Hosted Client Resource? Why doesn't the User-Agent simply pass the Access Token directly to the client?
Firstly, update your reference of OAuth 2.0 to the latest one.
As we know, in implicit grant,
after resource owner grants access, the authorization server redirects the user-agent back to the client using the redirection URI, and access token is in the fragment.
For example: http://www.myapp.com/googleapi/oauth/#access_token=ya29.JACdaU44_m0MQh0AAABLMVzZHm4KnUWyBECHJ9oM_0M2JC9x0xO6UoI9W8YNEw&token_type=Bearer&expires_in=3600
Since the fragment is not returned to the server (hash fragment is only intended for the client), client-side script must parse the fragment and extract the value of the access_token parameter.
Now, here comes to your questions, of course we can write a function in our client to parse the access token from the fragment and use it directly, it's simple and straightforward. Here is a tutorial using this manner.
But, in the standard, there is Web-Hosted Client Resource. Why?
'Web-Hosted Client Resource' is a client Resource, it may include some html pages and JavaScript, and of course it's web-hosted, rather than in the User-Agent. Since authorization server will hit our web application again at the redirect_uri with access token in fragment, our client-side web application server will respond it(parse the hash fragment).Here is a tutorial using this manner
In a word, the difference between these two manners is where you put the parse function.
Put it directly in the client it self, and the function detects if the user-agent hit the redirect URI, and if so, parses the access token from the fragment.
Put it in web-hosted client resource(locates in the redirect URI), when the authorization server hit the redirect URI with access token, the function locates the redirect URI parse it.
The second one is standard, for it makes the most of the redirect URI, also you can use the 1st one as well.
As far as I know, I haven't found any security consideration about the 2nd way.

How should I secure my SPA and Web.API?

I have to implement a web site (MVC4/Single Page Application + knockout + Web.API) and I've been reading tons of articles and forums but I still can't figure out about some points in security/authentication and the way to go forward when securing the login page and the Web.API.
The site will run totally under SSL. Once the user logs on the first time, he/she will get an email with a link to confirm the register process. Password and a “salt” value will be stored encrypted in database, with no possibility to get password decrypted back. The API will be used just for this application.
I have some questions that I need to answer before to go any further:
Which method will be the best for my application in terms of security: Basic/ SimpleMembership? Any other possibilities?
The object Principal/IPrincipal is to be used just with Basic Authentication?
As far as I know, if I use SimpleMembership, because of the use of cookies, is this not breaking the RESTful paradigm? So if I build a REST Web.API, shouldn't I avoid to use SimpleMembership?
I was checking ThinkTecture.IdentityModel, with tokens. Is this a type of authentication like Basic, or Forms, or Auth, or it's something that can be added to the other authentication types?
Thank you.
Most likely this question will be closed as too localized. Even then, I will put in a few pointers. This is not an answer, but the comments section would be too small for this.
What method and how you authenticate is totally up to your subsystem. There is no one way that will work the best for everyone. A SPA is no different that any other application. You still will be giving access to certain resources based on authentication. That could be APIs, with a custom Authorization attribute, could be a header value, token based, who knows! Whatever you think is best.
I suggest you read more on this to understand how this works.
Use of cookies in no way states that it breaks REST. You will find ton of articles on this specific item itself. Cookies will be passed with your request, just the way you pass any specific information that the server needs in order for it to give you data. If sending cookies breaks REST, then sending parameters to your API should break REST too!
Now, a very common approach (and by no means the ONE AND ALL approach), is the use of a token based system for SPA. The reason though many, the easiest to explain would be that, your services (Web API or whatever) could be hosted separately and your client is working as CORS client. In which case, you authenticate in whatever form you choose, create a secure token and send it back to the client and every resource that needs an authenticated user, is checked against the token. The token will be sent as part of your header with every request. No token would result in a simple 401 (Unauthorized) or a invalid token could result in a 403 (Forbidden).
No one says an SPA needs to be all static HTML, with data binding, it could as well be your MVC site returning partials being loaded (something I have done in the past). As far as working with just HTML and JS (Durandal specifically), there are ways to secure even the client app. Ultimately, lock down the data from the server and route the client to the login screen the moment you receive a 401/403.
If your concern is more in the terms of XSS or request forging, there are ways to prevent that even with just HTML and JS (though not as easy as dropping anti-forgery token with MVC).
My two cents.
If you do "direct" authentication - meaning you can validate the passwords directly - you can use Basic Authentication.
I wrote about it here:
http://leastprivilege.com/2013/04/22/web-api-security-basic-authentication-with-thinktecture-identitymodel-authenticationhandler/
In addition you can consider using session tokens to get rid of the password on the client:
http://leastprivilege.com/2012/06/19/session-token-support-for-asp-net-web-api/

How to make WebAPI actions accessible only from my app?

A common use case for WebAPI would be to have shell views rendered by MVC controllers, which contain javascript that then hit your API to access data.
But let's say you have some expensive API operations and you don't want people remotely accessing those endpoints -- you only want your MVC views, delivered by your application, to access them. How could you go about protecting them?
In this case Request.IsLocal doesn't work, because javascript is invoking it from the client's browser on their machine. Even if it did work, you need to dig to get the real HttpContext in order to find this property -- and that solution wouldn't work in self-hosted WebAPI.
For API endpoints that require a valid IPrincipal, you could protect them with the [Authorize] attribute. But what about API endpoints that you want your app to be able to access for anonymous users?
I have tried a solution and will post it separately as an answer, because I'm not sure if it's the best (or even a good) approach.
If your MVC site uses authentication, you could enable forms authentication for your Web API methods. You could write a custom [Authorize] attribute that will check for the presence of a forms authentication cookie which will be sent from the AJAX call and if present construct the principal.
Another possible solution is to protect your API with tokens which is a more RESTful style. The idea here is that when a user authenticates on your MVC website you could generate and pass a token to the view which will be used when sending the AJAX request to the Web API which in turn will verify the validity of the token and its signature.
If on the other hand your site doesn't use authentication, then things will get very complicated because you have no way of knowing whether the request comes from a trusted client since you are using javascript to call your API methods.
Before you go harping about "what have you tried", here is what I have tried. It works. Just not sure if there is a better way.
Create an MVC action filter and add it as a global filter during Application_Start.
Create an Http (WebAPI) action filter and use it on actions that should reject remote requests.
The global MVC filter does this:
Looks for a specific cookie in the request. If the cookie is there, its value is decrypted. The decrypted value should be a string representation of a DateTime, so use DateTime.TryParse to get it out. If the value is correctly parsed to a DateTime, and that DateTime is less than a day old, STOP HERE and do nothing else.
If the cookie is not there, or cannot be decrypted / parsed, or is older than a day, write a new cookie to the browser. Use the current DateTime.UtcNow.ToString() as the value, encrypt it, and write it with HttpOnly = false.
The WebAPI filter does this:
Looks for a specific cookie in the request. If the cookie is there, decrypt its value and try to parse it out as a DateTime.
If the value is a valid DateTime and is less than 2 days old, STOP HERE and do nothing else.
Otherwise, throw a 403 Forbidden exception.
A couple of notes about my current implementation of this. First of all, I use AES encryption with a shared secret and a salt. The shared secret is stored as an appSetting in web.config. For the salt, I enabled anonymous identification and used Request.AnonymousID as the salt. I'm not entirely fond of the salt because it's tricker to get at in a WebAPI controller, but not impossible as long as it is not self-hosted.

Resources