I am developing an ASP.NET Core Web Application using a combination of MVC Views and Web APIs. I also use Identity for user management.
I now want to enable Anti-Request-Forgery Tokens for our Web API. For that, I use the IAntiForgery service in Razor views to GetAndStoreTokens and forward the RequestToken to a $.ajax call as a header, as described in the official documentation in section JavaScript.
When I run the corresponding page that performs a Web API request with the user being signed in (Cookie-Authentication), I can also see that the request token is set properly as an HTTP Header (see orange box in image). However, the Anti-Forgery validation of ASP.NET Core denies the request with the following message:
Antiforgery token validation failed. The required antiforgery cookie ".AspNetCore.Antiforgery.ybHEizTXFmU" is not present.
Thus, the cookie-part of the Anti-Forgery-Token (blue box) is the problem here - the key starts with a different ID: .AspNetCore.Antiforgery.lUjKpn5xN20 instead of .AspNetCore.Antiforgery.ybHEizTXFmU
How can this happen? The Web App and Web API reside in the same process / at the same domain, so no Cross-Origin-Calls are performed. Is this a problem of $.ajax (which I can't explain because the browsers cookies of the target site should be reused) or a problem within the ASP.NET Core Anti-Forgery (or even Identity) module?
Related
I have the following setup:
1) WebAPI that accepts JWT Bearer tokens for auth.
2) Portal (WebApp) that puts a nice face on the json output from this WebAPI. It does OpenIdConnect authentication and uses Cookies to persist login information. It is an ASP.NET Core MVC app.
3) The WebAPI and WebApp are on different domains.
4) The WebAPI layer is designed to be called by any 3rd party who can present a valid token - either via App auth (client_credential flow, for eg) OR Delegated User auth (implicit flow, for eg). The WebAPI also does RBAC auth.
At this point, the problem I have is this:
1) I want to be able to make AJAX calls from the WebApp controller pages (cshtml) to my WebAPI so that the pages are responsive and there are no POSTs. So I integrated ADAL.JS into the page for that purpose. It works from a functionality pov.
2) HOWEVER, this results in multiple authentication dialogs (web page popups).
-- 1st auth popup. Upon navigation to the Portal homepage, I get challenged and have to enter my credentials on my company login page (federated AD auth).
-- 2nd auth popup. Then when I invoke anything on the Portal pages that involves ADAL.JS (namely the AJAX calls), it causes another login dialog because ADAL.JS cannot see the login cookie from ADAL.NET layer. This dialog comes up and goes away without any input needed tho (because the cookies from (1) are sent along to the server automatically by the browser). At this point, I have the ID_TOKEN and an ACCESSTOKEN for the PortalApp's client_id show up in the ADAL localStorage area.
-- 3rd auth popup. Then another dialog pops up; it uses a Hello pin login (I assume this is due to 2-factor auth requirement enforced by my tenant). At this point, I see the ACCESS TOKEN for the WebAPIApp's client_id show up in the ADAL LocalStorage area.
And now my AJAX calls start working.
Is there a better way to do this so that I can get the benefits of AJAX and not have to resort to serverside POSTs and have only 1 auth dialog instead of 3?
(I thought of may be switching ALL authentication to be done by ADAL.JS for the entire site, but I like the paradigm of using the [Authorize] flags and RBAC for the Controllers. OR is there a way to make my WebAPI accept both JWT and Cookie authentication?
Thanks!
Currently I have created a WebAPI Project using identity framework and I have setup tokens to be returned when authenticating with the API.
So now I am looking at creating a standalone MVC application that will allow the user to make calls to the WebAPI to get back end data.
The goal is to separate functionality so that other applications can also start interacting with back end data through web calls.
So the confusion now is how do I setup my MVC project so that I can use the Authorize attributes on controllers with the token received from the WebAPI. I think I need to enable bearer tokens in the ConfigureAuth method in Startup.Auth.cs. However will that be sufficient enough? Or do I also need to enable the cookie authentication?
MVC and Web Api are fundamentally different when it comes to authentication. With Web Api, the bearer token has to be set in the header of the request, but this is not an issue as all API requests are done programmatically by the client, i.e. there's human-intervention involved in setting up the client to authenticate the request properly.
MVC is a different beast in that the actions are accessed generally via a web browser, which will not automatically affix a bearer token to the request header. What it will do is pass cookies set by the server back to the server. That's why cookie auth is used most typically for MVC web applications.
What you should do is enable cookie auth for the MVC site and then set up your sign in action to authenticate via the Web Api. When you get back a valid auth from the Web Api, then you can manually sign in the user via the Identity API:
await SignInManager.SignInAsync(user);
Trying to search for this results many many results for securing a WebAPI and how to secure an MVC application, but i could not find a solution.
What i want to achieve:
i have an MVC website with a modal Login form,
When the user enters he's credentials to the the form, an Ajax request is sent to a WebAPI with the credentials.
The WebAPI should return (i guess a ticket, since that is what i found).
The ticket would be then saved into the sessionStorage of the browser (no cookies),
Each page request to the website will check for the token, and enable/disable the parts that need to be secured.
All the examples i have found are showing either MVC only authentication,
or WebAPI authentication, but i could not find anything that does the described above.
The sessionStorage is available only for client-side use. You can manipulate or retrieve values from the storage using Javascript, but you can't directly read data from the server. Since MVC typically renders HTML Views server side, you have no options to send the token stored in the sessionStorage on each request.
The situation you described is an hybrid solution which can't be achieved without the use of cookies.
A simple solution is to set the login data (specifically the token if you will use a token-based approach) in a cookie issued by the Web API endpoint during the login phase.
Ok, the situation is this.
We already have an existing ASP.NET MVC 5 site with Custom Forms Authentication, Logon, Registration etc with a custom database for roles and profiles already implemented.
We now are adding some new functionality to the MVC site and we decided to use Web Api 2 OData 3 endpoint which lives in another domain. The Web Api currently doesn't include any authentication but we need to be able to map the requests to a certain user to get his roles etc from the backend. The MVC and API sites use the same backend.
What we would like to accomplish is, that when the user logs on in the MVC site, the MVC site calls the Web Api server-to-server with the user's credentials and receives a token that the client can then use to call the web service with.
When API receives a request with the token, it can then map the request with the user in backend and do authorization.
As far as I understand it, Simple Web Token (SWT) could pull it through. But considering the environment, .NET 4.5.1 / Web Api 2 / OData 3 with Entity Framework in Azure Web Role, I started thinking is this SWT something I should really use or if there is any NEW technologies recently published that could easily pull this through. I don't want to add any unnecessary 3rd party dependencies to the project if the .NET stack already contains something like it.
So, what would be the simplest way of pulling this kind of authentication through without adding unnecessary dependencier to the project.
The solution we are looking for, is only temporary meanwhile we redesign our authentication scheme. So we are looking for something really simple to implement that works with least dependencies that need to be removed later on.
I'm using this in a project I'm currently working on. I use the OAuth 2.0 OWIN Middleware component that ships with Web API 2.0 (if you add a new Web API project with Authentication enabled, it includes the base infrastructure).
You would use the Resource Owner Password Flow as defined in the OAuth 2.0 specification. Basically you request a Token from the Web API OWIN Middleware sending:
client_id - identifies your MVC endpoint
client_secret - identifier your MVC endpoint
username
password
And in response you get a bearer token. The token generating is based upon a claims principal, the OAuth middleware component has predefined hooks for adding claims. This token now needs to be added as authorisation header to each response. On the MVC side you might add this to session so that it's always available to make backend API calls in the context of the user associated with an incoming HTTP request. If you're using WCF Data Services Client, you'll need an authorisation service/manager or similar that you can hook into OnRequestSending and OnResponseReceived events, so that you can insert that bearer token into the HTTP headers.
You can customise the OAuth Middleware component as you need to quite easily, it took a bit of time to figure it out as it's not too well documented, but downloading the Katana source code did help a bit as the source code does have some good documentation.
The nice thing about it all is that you simply need to enable HostAuthenticationFilter and add Authorize attributes on the Web API side and it's ready to go. You can get access to the claims principal object and use claims as identifying pieces of information for your user - e.g. identity, roles, other attributes etc.
To get started, look at http://www.asp.net/vnext/overview/authentication/individual-accounts-in-aspnet-web-api
Also as a wrap, I did consider the use of JSON Web Tokens (JWTs) as there is an OWIN library available for generating and parsing these. The use case here would be that you authenticate, get a JWT back, and then use the JWT to get an OAuth 2.0 bearer token. The JWT is useful if you want to move authentication elsewhere, or if you want to get additional information about the user at the MVC side of things.
I am working on a Windows Phone 8 app and a ASP.NET MVC 5 website and each of these will access a WebApi service (WebApi 2). The website and WebApi are based on the templates provided by VS2013 RTM and have been setup using the "Individual Account" authentication option available in the project template.
The template sets up the WebApi project to enable bearer tokens, application cookies and external login cookies, etc, and the exposed actions have the Authorize attribute on them.
My two questions are:
1) If I were to use Azure Mobile Services to authenticate a user using Google/Twitter on the WP8 application how can I get the WebApi to allow the authenticated user to access the actions?
2) Same as #1, but from a ASP.NET MVC 5 website perspective?
From I what I can see it would appear that each request requires a bearer token. To get this token would I be correct in thinking that I would access the "token" endpoint exposed by the WebApi to get the token and that would need to be passed with each request?
For 1, you can use azure mobile service WP8 sdk to launch a browser control to authorize user from external site. The code should be similar with WebAuthenticationBroker in windows store app.
For 2, the web api template with individual auth is using an implicit flow in OAuth 2.0 to return the application access token back to client. In MVC app, you can redirect user to
http://<web api domain address>/api/account/externallogin?provider=Facebook&redirect_uri=<your callback url in MVC app>&response_type=token&client_id=mvc.
And in your MVC view, you need to use javascript to get access token from url fragment, which won't be sent to server. In your web api server, you need to allow the client id and the callback url in ApplicationOAuthProvider.
For both 1 and 2, you are not using token endpoint to get the token. You are using the authorize endpoint to get token by implicit flow.