How does AntiForgeryToken work behind the scenes? - c#

I know the basics of CSRF and AntiForgeryToken.
I also know that there are many similar questions around but none seemed to describe the implementation details, which is the part I'm interested in.
Each time you call Html.AntiForgeryToken(), it generates a new random token :
Can I have multiple active tokens at the same time? (I assume it's yes here)
Can I use any of those tokens in another form? (I assume it's yes here)
Can I use the same token more than once?
Is there a security reason why the token is random everytime? Couldn't it be the same token for the whole session?
The token is stored in a cookie
When I have multiple forms and tokens in my page, does it mean I have multiple cookies or only 1 cookie containing all the active tokens?
Also...
How is the token generated and is it possible to validate it manually.

1.Can I have multiple active tokens at the same time? (I assume it's yes here)
-> Yes.
2.Can I use any of those tokens in another form? (I assume it's yes here)
-> Yes.
3.Can I use the same token more than once?
-> Short answer is yes you can. Long answer: It depends on multiple factors, you would have to regenerate the token if,
Your cookie expires
Your user identity has changed.
Your additional data provider has decided that your token is no
longer valid.
4.Is there a security reason why the token is random every time? Couldn't it be the same token for the whole session?
-> You don't want anyone to be able to predict your token. Remember there is no inbuilt auto expiration of the cookie token.
1.When I have multiple forms and tokens in my page, does it mean I have multiple cookies or only 1 cookie containing all the active
tokens?
-> At any given point of time there would be only one cookie that will be active for a session,
that cookie has a SecurityToken property. Every valid anti-forgery token on the page would have the same SecurityToken (otherwise it would fail validation).
1.How is the token generated and is it possible to validate it manually.
I would suggest to read the post explaining the internals here
and code here
I am actually thinking why would you need to use the same anti-forgery token across forms.. it might be helpful if you share your scenario.

For you last question, you can validate AntiForgeryTokens with the following:
System.Web.Helpers.AntiForgery.Validate(cookie.Value, formValue);

Answering in terms of ASP.NET Core just in case anyone stumbles upon this post from Google.
The following is based off this article:
Can I have multiple active tokens at the same time?
Yes. If you have two tabs open and hit the same URL that returns to you a page with a form containing an antiforgery token, you'll have a different token in the HTML on each page. But you'll have the same token in your cookie.
Can I use any of those tokens in another form?
Yes. You can test this by hitting the URL in two tabs, open Developer Options and swap out the tokens, and the application won't know any better.
Can I use the same token more than once?
Yes. As long as the token in the HTML was generated along with your cookie, then if you're using the same cookie, you could use the same token in your HTML as before.
Is there a security reason why the token is random everytime? Couldn't
it be the same token for the whole session?
See the accepted answer by Harsh Gupta.
When I have multiple forms and tokens in my page, does it mean I have
multiple cookies or only 1 cookie containing all the active tokens?
See the accepted answer by Harsh Gupta.
How is the token generated and is it possible to validate it manually.
Here is a summary from the article I linked above:
Build a byte array using a random number generator.
Generate a unique array based on step 1.
Encrypt the array.
Prepend a magic header and the defaultKeyId to the encrypted array.
Base64URL encode the encrypted array and use this as the token
string.

Related

Refresh identity token from client from code

I am using the fine-uploader with an asp.net mvc backend to upload files directly to an azure blob-storage. The asp.net-server works as the azure-signature-endpoint(sas). This is all secured with an identityserver3 and here comes the problem: The identity_tokens lifetime is set to 5 minutes(as default). And I want the SAS endpoint to be only called authorized. So a user can only access its own data. But after I have the upload running for the set 5 minutes, it breaks. Of course, because it is not authorized and it returns the login-page from the identity-server(which the fine-uploader, of course, can't handle).
It would be easy to solve this problem, by either setting the lifetime from the token to something higher(but this is unreliable as the upload could take hours or days), or disable the lifetime(yeah would work. But I guess the lifetime has a reason to exist).
So my 2 ideas would be:
to just authorize the user once(when he starts the download)
or to refresh the token by code every time the signature gets generated.
First approach
Can I just set a boolean like user is authorized and if this boolean is set just skip authorization and just return the signature or how could I achieve this
Second approach
How would I do this?
Don't use the id token for API access, an instead use access token. Access tokens are for resources (APIs), whilst id_tokens are purely for authentication. The id_token is only meant to be used to provide the RP with means of knowing who the user is - hence no need for long time span. It's only there for converting into a user session (cookie/principal).
With access tokens you have several approaches for keeping a valid token at a client; either by fetching new ones using the client credentials flow or by using the refresh token approach.
I believe there are samples of both in the samples repo of IdentityServer.
Samples repo link

Implementing JWT authentication in Asp.net WebApi using Microsoft System.IdentityModel.Tokens.Jwt

My question precisely is that "how is the token validating information managed on WebApi side ?"
i.e
A) Is there a unique secret key for each User?
B) If yes where are these stored ?
C) Some one said the key is generated fresh every session :O ??
I would specify how I think this is to be done or can be done.
1) App sends the username and password to login Api(Part of WebApi).
2) Api validates credentials from Database and creates a JWT.
3) A standard header is created say header = {'type':'JWT', 'alg':'HMAC'}.
4) Then claims/payload section is created and a unique identifier for that user is embedded into it.
5) Then (header.claims) is Base64URLEncoded and fed into a method which takes this encoded info and secret key as parameter and signs it using HMAC algorithm(say).
6) Now the header, claims, signature(obtained in previous step) are concatenated with periods and we get a JWT.
7) This JWT is sent back to the App.
8) During next request the App sends back this JWT to the WebApi while trying to access a resource.
9) The WebApi checks the JWT and decodes back header, claims from it.
10) The WebApi obtains the Unique user identifier from claims and checks if this user exists in the Database.
11) If user is found it gets the secret key associated with the user which is also stored in the Database against the user. (May be just a GUID generated at the time of registration)
12) It checks whether the token is expired or not. This info is available in claims/payload as 'exp' Date time or whatever.
13) Assuming that the token has not yet expired, The WebApi takes the header plus claims/payload and again generates the JWT same way it did the previous time using secret key.
14) The JWT so created is matched against the JWT sent by the App. If both match(signatures) then the token is correct and un-tempered and indeed issued by the WebApi to this user.
15) The WebApi sets the claim identity and allows the access to the resource.
Now instead of every time looking for the user identifier in the Database, The WebApi may also just maintain a static array of users as they login keeping their secret keys too. So it can just get the information from this array. As user logs out the user is removed from the static array as well.(The array management is not what I want to get into now)
This is just my way of thinking about implementing it.
I want to know how much have I deviated from the way it's done otherwise? I DO NOT want to create a separate authorization server. I want the WebApi to manage this itself in a simple but of course secure way. I will use Microsoft JwtSecurityTokenHandler for .Net 4.5 for creating, validating JWT's.
Your question is very generic in this topic and it takes many pages of answer. Please take a look on: JSON Web Token in ASP.NET Web API 2 using Owin
it will answers many of your questions

Asp. Net 5. Jwt tokens revocation

I am using jwt tokens middleware and Asp.Net.OpenIdConnect.Server in my app. In fact, it works fine. But I am confused in one thing. If I use tokens, I can not immediately grant new claims or ban my users. For example. I give my user access token, which expires through 2 days, and refresh token, which expires through 2 weeks. Then I give to this user admin rights. But he will know about this only through 2 days, when his current access token expires, and auth server will give him new token, using refresh token. How can I give him new rights immediately, on the next request?
I understand, that I need to check database for every request, and give to user new access token, if needed . But where should I do it in aspnet 5? Maybe there are some good practices for such thing?
One way doing it is to put a unique identifier into your claims, which you can query to see if it's still valid. You can use the memory cache to store it or some distributed memory cache such as Redis, so you don't have to hit the database every time.
When you ban the user or add a token, you mark this token as invalid by removing it from the cache. Each time you the user refreshes the token, it you should create a new unique id inside the token.

In WCF/WIF how to merge up claims from two different client's custom sts's tokens

I'm trying to create something like: Client authenticates and gets token from custom STS1, next client authorizes with machine key and is issued token on custom STS2 and gets another token. With last token, client requests methods on RP service.
All services are hosted on IIS and are using active federation scenario.
Both STS's have endpoints with ws2007Federation and ws2007Http bindings, and RP use ws2007FederationBinding with STS2 as an issuer.
If I create channel with CreateChannelWithIssuedToken I can see only token from STS1 and can't get token from STS2.
So I decided to pass token from STS1 as ActAs RST's property on request to STS2 token. And that failed - cannot decrypt token.
How can I pass both tokens to STS2 and merge up claims in them?
Is it a bad idea - to send with RST just extracted claims from STS1 token?
Generally you will only want to utilize one token at each step. So if you need to merge up claims, you will want to do that at the claims transformation step of the second STS.
So the flow would be authenticate with STS1, then authenticate with STS2 with the token from STS1. At that point you would pass through the claims and transform to add additional claims as needed. Then the resulting Token would be ready to consume from the RP application.
I have actually started a blog series about a really similar scenario that we recently architected. Not to be overly self promoting, but it doesn't make me any money, so I'll post it in case it is helpful.
http://www.livingthearchitecture.com/mixing-sso-with-existing-technologies/
I would be glad to go more in depth, but depending on the specifics of your scenario, the specifics of the solution will change greatly. I think the above expresses the general approach you will want. Let me know if I can help any more.

REST API token authentication

I just started a development of my first REST API in .NET. Since it will be stateless I will use tokens for authentication:
Basic idea (System.Security.Cryptography):
AES for encryption + HMACSHA256 for integrity
token data will consist object with properties: username, date of issuing and timeout
database will hold username, hashed password and HMAC hash
Login:
check if credentials are valid (username, compare hashed password to db value)
if true, encrypt data object
use HMAC on generated token and store it to database
return token (without HMAC) to user (cookie/string)
Request to method which requires authentication:
user sends token with each request
token is decrypted
if it is expired, error
if not expired use HMAC and compare username + generated hash with db values
if db check valid, user is authenticated
The way I see it, this approach has following pros:
even if db is comprosmised, it does not contain actual token (hash cannot be reversed...)
even if attacker has token, he cannot increase expiration by updating fields since expiration date is in the token itself
Now firstly, I wonder if this is good approach at all.
Besides that I still didn't figure out, where to store AES and SHA256 keys on server (should i just hardcode them? If I put them into web.config or use machine key than I have a problem in case of load balanced servers,...).
And lastly where do I store AES IV vectors, since Crypto.CreateEncryptor requires it for decryption? Does it mean that users have to send token + IV with each request?
I hope this makes any sense and I thank you for answers in advance.
UPDATE:
Ok, now I did some more research and came down with this solution:
token will contain originally specified data (username, date of issuing and timeout)
token is generated with encrypt-then-mac (it includes AES encrypted data, IV vector + tag of these 2 values for authentication, generated with HMACSHA265)
token tag will be written to db
user will be authenticated if:
tag is valid (token authentication)
data can be decrypted
token has not expired yet
tag matches the one written in database
user is not blocked in database (token invalidation on demand)
keys will be stored in web.config separate section. Same keys will have to be on every server (per application of course)
I didn't use FormsAuthenticationTicket because in .NET there are following issues:
same keys are used for different purposes (machinekey for view states, resources and formauthtickets)
mac-then-encrypt, used by .NET is not considered as safe as encrypt-then-mac
no built in way to invalidate token before it is expired
This is a follow up from the comment thread under the question.
You seem to be a bit confused as to what, exactly, OAuth is, so hopefully I can clarify it here.
OAuth is not a web service or something you consume. It is a protocol that describes the way that a site can authenticate a user against a service, without allowing the site to know what the user's credentials are. As a side benefit, most OAuth providers also have a web service to query the user's information, and permission to do so can be granted at the same time.
Typically, you are interested in implementing OAuth from the perspective of the site (eg, AcmeWidgets.com) so that a user can log in via Facebook or Google or something. However, you can also implement the service side (eg, where Facebook normally would be), and allow others to authenticate against YOU.
So, for example, let's say you have a web service to allow for third-party sites to provision Acme-brand Widgets for users. Your first third-party implementor is the popular MyBook.org. The flow would look something like this:
Someone invites the User to use the "Acme Widgets" app on their MyBook profile.
The user clicks on the button, which redirects to AcmeWidgets.com. The URL looks something like:
http://acmewidgets.com/oauth/user?r=http%3A%2F%2Fmybook.org%2Foauth%2Fclient&appid=12345
The user is asked if they want to allow MyBook to access their data and provision widgets.
The user clicks Yes, whereupon Acme Widgets notes that the user has allowed it.
The user is redirected back to MyBook, at a URL like this:
http://mybook.org/oauth/client?token=ABCDEFG
MyBook, on the server side, now takes that token, and places a web service call BACK to AcmeWidgets:
http://acmewidgets.com/oauth/validate?token=ABCDEFG&appid=12345&appsecret=67890
AcmeWidgets replies with the final authentication token identifying the user.
Alternately, it fails, which means the user is trying to fake a token, or they denied permission or some other failure condition.
MyBook, with the token, can now call AcmeWidgets APIs:
http://acmewidgets.com/api/provision?appid=12345&token=ABC123&type=etc
This is all known as the OAuth dance. Note that there are a number of implementation defined things here, like URLs, the means of encoding the various tokens, whether tokens can expire or be revoked, etc.
Hopefully that clears everything up for you!

Categories