REST API token authentication - c#

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!

Related

JWT Authentication: Bearer token + Cookie

I know this topic has been discussed many times, but there are so many articles around (and answers here in SO) that I'm a bit lost.
My scenario is the following: I have a WebApi written in ASP.NET Core 6 and I want to authenticate a mobile PWA app written in VueJS, using JWT authentication.
Reading through some articles and looking at the CheatSheet recommendations here and here, this is what I have come up with:
When I try to authenticate my user in the PWA, if the user credentials match, the server generates a token which contains also a claim with a "fingerprint", a SHA256 encrypted random generated string. The same generated string is added in a dedicated cookie that is returned with the response to the client: the cookie has the HttpOnly, Secure and SameSite options enabled
Once authenticated, I store the authToken and the refreshToken in my IndexedDb. First question here: why would I need to use a sessionStorage in my case when the user will never create a different session of my PWA anyway? NOTE: my token does NOT contain any user sensitive data
Whenever I do a request from the PWA, with axios, I use the withCredentials: true option and I send to the server not only my token as a Bearer in the Authorization header, but also my fingerprint cookie
For each request received, the server unpacks the token, checks its validity (issuer, audience, signature, expiration, etc.), but also checks that the fingerprint contained in the JWT claim matches the one in the received cookie
So, from my understanding, the usage of this fingerprint guarantees that any XSS attack retrieving the token from the client storage won't be able to authenticate against my WebApi because it won't have the corresponding cookie. At the same time, the cookie is protected from XSRF attacks with the options I'm using for the cookie itself.
Is this correct? Is it strong enough?
And also: can I simplify/enhance my algorithm by using the Antiforgery token built-in mechanism provided by ASP.NET Core?

How to validate the SalesForce Consumer Key and Consumer Secret

We have a system, where we want to push the records (e.g. Contact, Account, Opportunity) from our system to SalesForce.
To achieve this, we have used ForceToolKit for .Net. We are successfully pushing the contact records from our system to Salesforce.
First customer has to provide the consumer key and secret and upon providing these details, the user will be redirected to Salesforce login page for OAuth. We are storing the RefreshToken and it will be used at the time of Data push.
Here, if user provides incorrect consumer key, then it is redirecting to Salesforce login page and shows below message:
error=invalid_client_id&error_description=client%20identifier%20invalid
Now, we have to validate the Consumer key & secret before it redirects to Salesforce URL and check if it is valid or not.
Can anyone help me on how to achieve this?
I understand your question so why the Error will be like mismatch of URL which you provided in Enpoint URL. This is first reson and next is consider the method post or get but main Reason is URL mis match intha URL you have to use request type. And consumer key secret key and username password this are the maditory to get the access token.
As Aleander said, it's the first wrong endpoint URL and you need to consider additional things.
Instance = login for Production, and test for the sandbox.
URL - https://<instance>.salesforce.com/services/oauth2/token
Method - POST
Params -
grant_type - password (hardcoded)
UserName - Username which you may have
Password - Here it's a bit tricky if you have IP enabled in the org for your user profile, then you need to append your security token with the password.
Consumer Key - consumer key you're trying.
Consumer Secret - Consumer secret you're trying.
You can check similar details in the below link as well -
Link - https://medium.com/#krissparks/postman-a-salesforce-rest-web-service-28edc0a69851

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

WPF-Client for WebAPI - how to handle password for authentication

I'm developing a Client/Server-Application with ASP.Net WebAPI and WPF.
Right now I'm thinking of authenticating the client with basic authentication over https. You can suggest better solutions but windows authentication and server side sessions won't work for me.
For basic authentication I need the password on the client in plain text (base64) to send it over the wire on every request, right?
But i don't want the user to reenter the password on every request, so I have a Login-Window on the application start.
The WPF PasswordBox uses SecureString and is not bound to the viewmodel. But at least right before the request I have to get the password as normal string to encode it to base64.
So sooner or later the password is in RAM in plain text no matter what I do.
What are the best practices to hold the password for later requests?
cache the PasswordBox
cache the SecureString
cache a plain text string because it will be in RAM either way
cache the base64 encoded string because at least it is obscure ;)
...?
So how do I handle this in a reasonably secure way?
Other applications by big players (MS, Google, Apple, ...) don't request my password for every call, so there has to be a way.
You should read into authentication tokens, this is a commonly used method and the asp.net-web-api framework provides a lot of functionality provided by OWin.
Basically the flow is as follows:
Authenticate at your web-api.
Return a token
Use this token in the header of every following web-api/http request
The benefits:
Doesn't store the username and password in memory (well, just for a single call)
Token can be invalidated at server side
Functionality out of the box with web-api2
You can read about it here:
http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/
As for your WPF client:
You can create a .net client for your http/web-api requests by using the:
HttpClient https://msdn.microsoft.com/en-us/library/system.net.http.httpclient%28v=vs.118%29.aspx
Some psuedo code will look like this:
public async Task<IEnumerable<DataContainer>> GetDataForTarget(string id)
{
var requestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri(new Uri(Host),
string.Format("api/Data?id={0}", id)));
var response = await Client.SendAsync(requestMessage);
//etc...
}
Note:
For the token based security to work you'll need https, otherwise the token can be intercepted. Everybody who knows the token can make calls to the web-api on behalf of the corresponding user. So, basically the problem shifts from securing the password to securing the token. The benefit of a token is that it should have a much shorter lifetime than a password, thats why it's more secure. Nevertheless it's arguable to store the token in a SecureString.
Meanwhile at the server side
It's is good practice (or even unethical if you don't) to, provided that users can pick their own passwords, you use a one-way encryption mechanism at your server to store the passwords.
This can be accomplished by using a (encryption-strong) random salt and a asymmetric-hash encryption using that salt.
To verify the user, just encrypt the incoming password with the stored salt and check if it gives you the stored hash value. In this case no actual passwords will be stored at your server and there is no way to retrieve the users password (.... well ehh excluded some technical details).

Authenticaion, hash, salt, https process?

Hi I think I may have done this the wrong way round can anyone help explain how you hash/salt a password. Do you do it from the client or the webservice?
I have a datacontract which has a password datamember, in my service I do this to create a hash/salt of the password before it is saved:
So here is the process in which I was thinking.
Rest Service has https for secure connection
User creates account (along with password)
//to stop packet sniffing when user creates account https is used during POST so no one can see the password?
web service then creates a hash of the password to store it
//so if anyone did get access to the service/database they couldnt make much use of the data in terms of breaching accounts
Then some means to authenticate that user there after
Is this correct?
Sounds like you're on the right track. Hashing along with the salt value should never occur on client side, as attackers will have access to that code. And https would indeed secure the connection, disallowing others from reading the data.
During authentication you do the same thing: take the password the user entered via https, hash/salt that value, then compare the result hash with the value in the database. And of course if you ever return a Student object to the client, it should contain neither of the values.
It may be wise not to reuse the Password property of Student since now you can't tell whether it contains the plain password or the hashed value.

Categories