Lifetime and multiple use of an AntiForgeryToken? - asp.net

I'm trying to implement antiforgerytokens to an angular application's ajax requests.
Is there a lifetime attached with the antiforgerytoken? If I have the app open for a long while in a web browser whithout touching it, say for a month. Will the ajax requests fail due to a stale token?
Can the token be reused for multiple calls? Can I keep one token somewhere in the page and retrieve it for all ajax calls?

Indeed API are supposed to be consumed by 3rd parties, but what's regarding Single Page interfaces with AFT?
I'm concerned they still require AFT in order to prevent CSRF atacks. And here is a good way to use them in Ajax requests.
Antiforgery token is generated per Session, and remains in session data till it's expired. For new session new token will be generated. And yes, single token can be reused multiple times within the same session.
Please check the link I've added, there is example of how token might be obtained for Ajax requests.

Will the ajax requests fail due to a stale token? Yes
Can the token be reused for multiple calls? No
However, the better question to ask yourself is why are you using antiforgery tokens with AJAX in the first place. If you're using AJAX, you're using an API, even if you haven't formalized it as such (just a collection of actions/controllers that are using for AJAX/other headless communication). Antiforgery tokens don't work well with APIs because 1) APIs typically allow third-party access and 2) even if they don't, there's better ways to secure them.
If you want to ensure that only your site can access your "API", then implement HTTP authentication or some other scheme to authenticate your requests to your "API". That is how you allow long running sessions that will not fail.

Related

Create HttpClient for multiple requests but different users

I need some assistance working with .Net5 HttpClient. I am currently building a middle man API so our users can perform actions on a third party vendor API, but we cannot grant them full access to this 3rd API.
The problem to solve: My user's setup is an Angular SPA where users can perform a single action and this will trigger several endpoints from this third party vendor.
As an example:
My user could create a project in the vendor API. The following are the steps to do this:
We need to do a POST to createProject
Then a PUT to add users to the project
PUT to configure permissions and access levels
...
If any of the above fails, Call the DELETE project and notify my user something went wrong.
Therefore I believed the best way to do was to wrap all this in a single API that will take care of all the steps, validation etc...
The way this vendor works is that the first call I need to make to its API is to the /login endpoint. The call will respond with a token in the header, and a Set-cookie with the session id. In the consecutive calls I need to send this token as part of the header and keep the cookie in the context while I keep doing calls.
The challenge: according to the documentation for the HttpClientHandler, the cookie context will be reused for all the requests that go through the system.
Does this mean that if two users send a request to my API at the same time, would they be sharing the same sessionId/Token with the third party vendor?
I could find some posts in stackoverflow mentioning about a workaround when creating the HttpClient which would disable the automatic cookie handler but then I would have to parse the response from the /Login call and generate a new HttpClient with these new values? Would this count as persisting the context for this call and not destroy the headers and credentials sent originally for each user?
Sorry if this question has been answered before. I just got confused on how this is a bit too complicated. My previous experience with a similar case was Python, and in this language you can create a Session object that will only be kept for the lifetime of the request, won't share any details with other requests and will keep the context intact. Is it possible to achieve the same result with Net5?
TLDR/Summary?: On an ApiController, after receiving an outside request, how can I create and reuse the same HttpClient to do multiple HTTP requests using the same cookies without sharing cookies with any other future incoming requests.
I hope the TLDR doesn't make this more confusing.

Authorization Code Grant: is it safe to send the tokens to the client?

Let's say I have a SPA with a back-end on the same domain. If I had to connect to an external OAuth provider (let's say Google), the Authorization Code Flow (without PKCE) is the safer option. This means that:
The SPA requests a code to the Authorization Server
Then, it sends that code to the back-end
The back-end exchanges the code (and a secret) with the AS in order to get the tokens
The back-end sets a Session Cookie with the SPA to keep the user logged in
This flow is the most secure because the SPA never sees a single token. It doesn't use them. If I have to make a request to the API with the Access Token, the SPA will make a request to the back-end which in turn will use the Access Token to get the resources. And the back-end is also responsible for using the Refresh Token. So far so good.
Now, what if the back-end, upon successful exchange (once it gets the tokens), sends the tokens back to the browser? That way, the client can hit the API's endpoints on its own.
In theory, this should be avoided if I'm not mistaken. Giving the tokens back to the front-end kinda defeats the purpose of the Authorization Code Grant, you might as well use the Authorization Code w/ PKCE in order to get the tokens on the front-end directly, right? With the Code Grant, it's the back-end that gets authenticated, not the SPA.
But I'm thinking: that's what Firebase does, isn't it? As far as I know, Firebase uses the Authorization Code (without PKCE), redirects to the Firebase App's back-end (__auth/handler) and then it still gives the tokens to the front-end (id token, access token, refresh token).
Am I missing something? Or is it ok to give the tokens to the front-end at the end of the Authorization Code Grant?
PS. Obviously, in the Firebase case, the back-end will not actually use those tokens, it relies on the browser ones that are sent in each request I imagine. In the case I mentioned though, the back-end stores those tokens so in theory I'll have 2 sets of tokens: the ones that the back-end received with the code exchange, and the ones that get sent to the browser (initially they're the same, but they're different after the first refresh). Should the back-end discard the tokens completely and rely on the browser ones? I assume it should, because if Refresh Token Rotation is enabled, the back-end would have an invalidated Refresh Token after the first refresh by the browser. This situation is driving me nuts. My opinion is that the tokens should remain on the back-end, but I'm trying to figure out how can the Firebase approach be safe.
Interesting isn't it? There are trade offs involved, and different technologies make different choices on how to use tokens.
SHORT ANSWER
If is not inherently unsafe to use access tokens in the browser. It is generally recommended to keep the tokens short lived, confidential and to store them only in memory.
Whether to use tokens like this may also depend on the data sensitivity and the opinions of your stakeholders.
BIG PICTURE
What we'd really like is for these two technologies to work in an equivalent technical way. After all, both typically need to do the same job, of calling APIs to access data and then presenting screens to users.
Web UIs
Mobile UIs
It is totally standard to use access tokens in a Mobile UI, but some people have concerns about doing so in a Web UI.
WEB UIs
One option is to keep tokens out of the browser and use a 'web back end', as you describe. Many people prefer this from a security viewpoint, but it has these downsides compared to a pure SPA architecture:
You have to double hop all calls to APIs via the web back end, which is less efficient
The need for a web back end that runs code to issue auth cookies can result in suboptimal hosting, where you are unable to deploy web resources using a Content Delivery Network
There are other complexities due to the two forms of back end credential: cookies for web and tokens for mobile
PROOF OF POSSESSION TOKENS IN 2021?
Hopefully these are not far away for public clients - where DPoP tokens can be sent between Web UIs and APIs. This will mean access tokens stolen from a browser cannot be replayed and will further reduce the need for web back ends:
DPoP Proposed Standard
BROWSER THREATS
Of course there is more to browser security than cookies v tokens, and security is about covering risks. It is worth thinking about threats that concern you and how to mitigate them - this blog post has some notes on how I reasoned this out for an online code sample of mine a while back:
Browser Threat Model

Constrain clients to ones coming from the own app/website for unauthenticated web API

These are the criteria:
My users are unauthenticated.
My app is a single page web app (written in JavaScript) that uses RESTful web API endpoints to fetch data from my own server.
Objective: I'd like to constrain the web API to only allow requests from my own app, without requiring users to authenticate. Are there existing techniques for this?
The issue is that since the web app's code and the requests made by it are transparent to the client it can't hold a secret for authenticating with the server.
I thought about creating single-use access tokens on the server side, then use those from the client side for the API calls. Now this would make it harder to do requests from the outside, but still you could make requests if you fetch this token from the original website first (even if you'd have to do it for every request).
If it matters I'd implement this with an ASP.NET MVC website and ASP.NET Web API endpoints.
Similar to this question but not entirely the same.
Thanks in advance.
I asked pretty much the same question a couple of years ago, and for unauthenticated users, some kind of token is pretty much going to be your only option. It doesn't make it impossible to get unauthorized access to your API, but does make it a little more painful.
I took a slightly different approach in my solution, using 2 cookies to protect some anonymous GET requests. One of them was the anonymous identification cookie, which was used as an encryption salt for another custom cookie given to the page that delivered the javascript. Only when the API request received both of these cookies and the decrypted result was satisfactory did I allow the WebAPI to respond. But like I mentioned, this only makes it more painful to gain access outside of the javascript app, not impossible.
Here is a reference for using tokens in WebAPI: http://codebetter.com/johnvpetersen/2012/04/02/making-your-asp-net-web-apis-secure/

Asp.NET WebAPI custom authorization

I want to create a authorization mechanism for an application based on WebAPI and AngularJs.
I've seen some articles, which use BasicHttpAuthentication, but i really don't like the whole idea of sending username, and password on every request. The more it doesn't fit for me is because i want to use OpenId authentication, where you don't have username/password pair.
I'm thinking about a solution, but I don't really know how to implement it. The concept is that user is authenticated as in an usual Web application - posts a form with user / password or selects an OpenId provider. If the user is authenticated succesfully, it is placed in a static object, which stores the User object for a certain ammount of time. Next a usertoken is generated and passed to the Client Application. The client passes the token on each request to the server, if the user exists in the above mentioned static object with the appropriate authentication token it is authorized to get the data.
Firstly - Do you think this is a good approach to the problem?
Secondly - How should I pass the authentication token, WITHOUT using cookies? I guess it should sit in the request headers, like in BasicHttpAuthentication but, I really dont' know how to handle it.
BasicHttpAuthentication
I'm with you on feeling dirty about caching the username and password on the client and forever transferring it with every request. Another aspect of Basic authentication that might work against you is the lack of sign-off. Other than changing the password, you can't "invalidate" a basic authentication session. Tokens on the other hand, will typically offer an expiration date, and if you want server-side invalidation you can check the issue date and say "any tokens older than issue date xyz are invalid".
Server State
You mention "If the user is authenticated successfully, it is placed in a static object". But this is independent of the token? This sounds like you're wanting to implement server state management of authentication sessions, but this isn't strictly necessary. The token itself should be sufficient for user authentication, managing server state is another potential obstacle. Server state can become difficult to manage when you factor app-pool recycles or web-farm environments (what if you want two services to share the same authentication token, but not require communication with a central "authentication server" for storing the state / session?)
Passing Authentication Token
Headers is definitely a good place for it. Really, where else is there? Cookies, Headers, Message. Other than a browser client, cookies don't make a lot of sense, and including it in the message can muddy your message formatting a bit, so headers is the only remaining option that makes much sense in my view.
Client Implementation
You've not specified, but I suspect you're interested in calling the service from .NET? In which case System.Net.Http.HttpClient could be your friend. In particular, the DefaultRequestHeaders collection. You can use this to add a custom header to store your authentication token.
Server Implementation
When researching ASP.NET authentication recently, I learned a lot about customisation by examining the Mixed Authentication Disposition ASP.NET Module (MADAM). I wasn't interested in using MADAM as-is, but learning about it from that article and examining the source code gave me a lot of ideas of how I could insert my own authentication module into the web stack.

Looking for authentication/impersonation strategies for a RESTful API

I've got a requirement to allow impersonation ("act as") in my API. So a user with the appropriate permission can exercise the API as another user. I'm wondering if there are some specific strategies employed in this space?
I can create an endpoint to begin and end the impersonation. Beginning the impersonation might involve getting a user and their permissions and loading them into memory for the current request, easy enough. What about subsequent requests? Is it bad practice to add an HTTP header indicating a "Impersonated-User"? If that header exists, use it to do auth on subsequent requests? What about using a cookie with that UserId? Or additional information?
Is there added benefit (assuming a .NET impl) to assigning the impersonated users to the Thread.CurrentPrincipal? The current permission and role implementation is custom, essentially using a bit array (although this is on the table for change in the future).
HTTP doesn't include any native support for delegate credentials / impersonation, so a combination of HTTP Basic Authentication with a custom header indicating which other user the client is trying to act as would be fine.
I would avoid polluting your API with the idea of "beginning and ending the impersonation", however. That implies stateful session knowledge that must be maintained between API calls, and it will make it more difficult to manage on the server side.
I would just have the client pass all the required information (their creds and the impersonation principal) with each call, and validate them each time against the resource being invoked.

Resources