How to secure an API - asp.net

I am developing an API as a middleman between a Windows app and the database. The webserver will just be an ASP. NET generic handler returning json.
Users will log into the app and their credentials will be transmitted over the wire. From there what I was going to do was generate a session key that the app could use from then on with every request.
This will not be an open API in the foreseeable future.
Now what I am wondering is if this is secure enough? How can I stop people from using fiddler to just replicate the calls?
Is there a better approach to this? Would it help if I used SSL?
I don't want to complicate matters by using oauth.
Thanks!

Use SSL. In order to obtain the session token the client should authenticate himself with a username and password transmitted over SSL. Once authenticated the token should be transmitted to the server over SSL to prevent from man-in-the-middle attacks.
So here's the flow:
The client sends his credentials (username and password) over SSL to a web method
The web method verifies the credentials and generates a session token and returns this session token to the client.
The client sends the session token on subsequent requests to protected resources.
The server verifies the token and if valid grants access to the protected resource.
You use simple Forms Authentication to generate the session tokens. The FormsAuthentication.Encrypt and FormsAuthentication.Decrypt methods could be a good start for you. The forms authentication token contains an encrypted value of the currently authenticated user. If you are running in a web-farm make sure that you have static machine keys on all nodes of your web farm, otherwise a session token encrypted on one node might not be decrypted on another node.
As an alternative to session tokens you could use basic authentication over SSL. The drawback is that credentials are sent over the wire on each request. Even if you are using SSL, the password is still transmitted over the wire, so this method is less secure than session tokens but easier to setup.

Related

Is Basic Authentication a Session based authentication and why Jwt is more recommended?

I'm learning about Basic Authentication and Jwt Authentication with Java and Spring and I want to ask you if basic authentication is a session based authentication?
I know that in a session based authentication, when the client log in, a sessionId is stored in cookie on the client browser and after that when the client make another request, the server compares the sessionId with the data stored in the memory of the server. And also I want to ask you how is the sessionId sent from client browser to server? Is it sent in the header like a token or how?
And the last question is how the server validate the Jwt token? I know that in case of session authentication, the sessionId sent from client is compared with the data from the memory of the server. But what's happen in case of Jwt authentication? The token is sent with the header and I know that the server validate it and there is no data in the memory of the server. Then how the server compares the token? Any feedback will be apreciated! Thank you!
if basic authentication is a session based authentication?
I know that in a session based authentication
well then why do you ask?
Actually - basic authentication means, that the user credentials(username and password) are sent in the Authorization http header
Authorization: Basic base64(username:password)
The server may or may not use a session cookie. Session cookie may be used with other authentication means or even without any authentication
how is the sessionId sent from client browser to server?
As a session cookie A session cookie is sent as an http header which browser treats as session-persistent
And the last question is how the server validate the Jwt token?
The JWT token should be signed. Note the token has usually 3 parts
header.body.signature
the header specifies a signature type (an asymmetric key or shared secret) and the signature is authenticated (signed or hmac-ed) header and content.
So - the server must validate the issuer, expiration and the signature.
So the server (service provider) doesn't need know the client's identity upfront. The service provider needs to know the issuer's (authentication service which issues the jwt token) public key or shared secret key.
After the jwt validation the service can assume the caller's identity based on the information in the jwt token.
why Jwt is more recommended?
It depends in the use case. (everything has its pros and cons)
I'd recommend using jwt in a distributed and/or microservice architecture. The service doesn't need to access the credentials or to authenticate the user.
In the basic authentication we need to send the username and password for every request.
In the session authentication we will send username and password at initial request. Then from server response we get the session id which stores in browser and gonna use that for requests.
In the token authentication we will send username and password at initial request. Then from server response we get the token and gonna use that for requests.
hope u got it!!

Session authentication for both browser and non-browser clients

I would like to know if the following design for token-based authentication is sound.
Client posts login credential
After validating, server generates (session_key, expires_at) <- (a 256-bit pseudo-random string, some date in the future) and save it in the storage system of choice.
Server sets the session_key in the HTTP-Only cookie in the response.
Server sets the response payload {session_key: ..., expires_at: ...}. The reason is that non-browser clients do not have cookie and they will read this payload, locally store it for the future use.
Concretely, I think the system needs to send the token in the payload as well as a cookie for non-browser clients. Is this a common practice? Or am I missing something important, and there are better alternatives?
As I pointed out in another question, this is fine. It doesn't expose the session key any more than if it is only in a cookie. This could only happen if the attacker can call your authentication endpoint with a valid user/password combo.
Make sure your authentication endpoint does not accept valid sessions and echo back their key as that could expose you to CSRF and session stealing!
For alternative authentication methods, check out the Web Authentication Guide, I put together.

Security of JWT over unsecure network compared to forms authentication

I am trying to learn JSON Web Tokens (JWT) and did a sample successfully using the article series present in Implement OAuth JSON Web Tokens Authentication in ASP.NET Web API and Identity 2.1 – Part 3.
I read about JWT and fond that the token can be decoded using JWT debugger present in https://jwt.io/ . The tokens are not encrypted – just encoded.
I have an existing ASP.Net web site which uses forms authentication. I am planning to make some functionality of this as Web API and use JWT for authentication.
Since JWT can be decoded, if some malicious hacker can read the token, they can get authenticated and get access to the resources.
Question 1
How is security of JWT compared to ASP.Net forms authentication? Is it more, less or equal secure over and unsecured network?
Question 2
The article "How to Avoid Session Hijacking in Web Applications"
illustrates a method for validating the IP address to which session_id was issued during login, and IP address of all subsequent requests, in the Application_AcquireRequestState event. This will be possible if the session id is stored in the server.
If I store the original IP addess on the JWT token also, is there a way to make sure that the token is not forged (to validate the original IP address and current IP address in each request)?
References:
Cookies vs Tokens. Getting auth right with Angular.JS
Session hijacking attack
What if JWT is stolen?
Stealing JWT from authenticated user
Content visibility of JWT is not a security issue because content is protected against alteration by a digital signature. But if an attacker gets access to a token, he can impersonate user. So use HTTPS if posible and keep the token in a secure storage
If you want to hide the content. JWT can be used with JWE encryption.
Forms authentication will probably use an opaque token in a cookie to maintain the server session. So if you store the JWT in a cookie marked with HTTPOnly I would say that security level is more or less the same. Note that cookies are vulnerable to CSRF attacks. However storing JWT in localStorage or accesible with javascript will do it vulnerable to XSS attacks.
In any case you need extra security measures, so there is no a magic solution and depends on the context
EDITED Question2 (Avoid session hijacking validating IP address
This technique can be applied in the same to JWT just adding the source IP address to the token. Since the token is signed, you can compare source TCP IP address with token address to validate the token origin.
Note that it is fully possible to send data with a fake sender IP, but replies will go to the fake IP address used by the sender, so they will never reach to the attacker.
But validating client IP has drawbacks, for example in mobile devices IP can change when the user switches from wifi to 4G, then the current token will be rejected

Authenticating with Web API

I am using ASP.NET WebAPI for a web service that I am building. He web service will use the Identity service to authenticate users.
I am a bit stuck as to how to authenticate users externally. Our current system is very basic- we send a username and password in the XML request as a separate field and it is all done in 1 request.
From what I can see from looking on Google, the best way is to request a token from the Ali and then pass this token in subsequent requests. Is there a way where I can do it all in 1 request (that is, send to the API my request for data as well as the username/password or perhaps an API key in a single request?)
From what I can see from looking on Google, the best way is to request
a token from the Ali and then pass this token in subsequent requests.
Is there a way where I can do it all in 1 request (that is, send to
the API my request for data as well as the username/password or
perhaps an API key in a single request?)
I'm not sure why your web service want to know user's username and password in Token based Authentication.
In Token based Authentication, your web service should not ask for user's username and password.
Instead, user first verifies the user name and password using a token issuer that your service trusts.
Upon successful verification, the token issuer provides the user with a token. Once the user has that token, it uses it to call your service.
For that, you do not have to reinvent the wheel. Here is JwtAuthForWebAPI nuget package for OAuth2 and OpenId Connect.
It is not secure at all to keep sending username/password with each request, you need to configure your api to issue access tokens for specified life time i.e. 24 hours. To do so you need create and end point (/token) which accepts the username/password validate the combination then issue an access token.
The client which receives this access token is responsible to store is securely and transmit it with each request to an any protected resource using the request "Authorization" header using bearer scheme.
As well you can not do this in one request, you need to obtain the access token at the beginning the you keep calling your protected resources using this access token until it is expired.
You can read more about this in my detailed blog post about Token Based Authentication in Web API

Create session oriented API's in asp.net Framework 4.0

I am working on a project where mobile apps connects to website through a set of API's. I considered creating API's using "Generic Handlers". This was seems to be working fine until restriction are defined for sensitive data. User has to be authenticated before he makes request for data.
I created a login API where user credentials are validated and a encrypted string which contains the same credentials which he provided at the time of login are returned back to the user after successful validation.
Each time a user makes request after successfull login, an encrypted string was supplied back to server in header. On server side, the encrypted data is decrypted and validated against with the credentials stored in DB. This step is unnecessary as user is recently authenticated. Is there anyway I can avoid authenticating user for each requests. I am planning to go with WCF services where Session can be effectively used to achieve the same (is this is something good idea?)
I did the same steps as you are doing for my API's. Here are some of the changes I made in the authentication part.
Client sends his credentials (username and password) to /api/login
Server validates the credentials and forms an encrypted string with identify of user and some necessary data like expiry date. Call this as token.
var tokenStr = "user_id=1234;expire_date=" + DateTime.Now.AddMinutes(20).ToString();
var encToken = AESCryptoService.Encrypt(salt, tokenStr);
Return this encrypted token to the client
Client sets this token in the HTTP header (X-App-Token) to make future API calls.
Server detects and decrypts this token. Here you can trust this token if decrypts with your salt. Get the user_id and set the current thread principal and proceed with the request.
If the token expires (read expire_date) then return 401 Authentication request, so that the client can request the token again.
You can also use SHA-1 or MD5 or some signing/encryption mechanism to make sure that the token string cannot be altered other than you.

Resources