I am developing an enterprise app where I need to pass a Session ID in REST requests which will pass the same id in my EJB methods.
The approach I have taken is:
Create a Session ID whenever user logins. Use this session id to pass as Header Param in each api except login. (I am still figuring out how to exclude one REST API)
Use this session id in the Header and pass it to each EJB. (How to read header param in subsequent Rest calls after interceptor is invoked.)
Can anyone please let me know, if this is the right way to go?
Also, will generating a one-way hash for creating a session token useful rather than sending a auto-generated primary key?
Passing a token as a header parameter to identify a logged in user is a common approach. Actually using OAuth is basically the same idea, but adding a standard way of doing so and adding the possibility of expiring/revoking tokens.
About generating a one-way hash, yes. That's the way to go. An auto generated primary key would be a terrible idea. If I log in and I am assigned session 1427, I can be almost 100% sure that there is a 1426 session available for a different user right now. Huge security hole.
Make sure you make those tokens as hard to guess as possible and use https throughout the whole process or you will be exposing your login tokens to eavesdroppers.
Yes. Dont use autogenerated primary key. If you are using multiple layers of application and dont want to use JSESSIONID, use SecureRandom to generate a session-token and use it.
Related
I am not sure if I am using the right terminology, but I was looking at the documentation and trying to work out if I could achieve the following with Shiro:-
Allow the user to login via a post of JSON
Check credentials and send a session ID to the user (probably on the header)
For every subsequent request, send the session ID transmitted on the login response on the request header
Use a SessionDAO which stores the session data in the DB (thereby creating a "sessionless" application).
I know how to create the session DAO, but I wasn't sure how to set the current subject on a web application. Is this possible? Is there any reason not to do this?
If you need to manage a session then the application is not sessionless. That said, take a look at the [DefaultWebSessionManager].(https://github.com/apache/shiro/blob/master/web/src/main/java/org/apache/shiro/web/session/mgt/DefaultWebSessionManager.java). Though, if you are going through the hassle of setting a header anyway, you could just set the cookie header, and use this implementation as is.
I am attempting to make a website's back-end API (I want to make the back-end independent of the front-end so I'm only making a server-side API for now, abiding to RESTfulness as much as possible). I haven't done this before so I'm unaware of the 'best' & most secure way to do things.
How I do it now:
Some parts of the API should only be accessible to a specific user after they login and up to 24 hours later.
To do this, I am generating a random Session ID whenever a user logs in (I'm using passwordless logins so the user is assigned that ID when they click on a link in their email) on the server side, which respond by sending that session ID to the client once. The client then stores this session ID in localstorage (or a file in disk if the client is not a web browser).
Next, I store that ID along with the associated email in my DB (MySQL table) on the server side.
Now every time the client want something from my API, they have to provide the email & session ID in the URL (I don't want cookies for now), which the server checks against the ones in the DB, if they exist then the server responds fully else responds with an error.
After 24 hours, the server deletes the email/session ID pair and the user has to login again (to generate another session ID and associate it with their email).
Now the questions:
Is my method secure or does it have obvious vulnerabilities? Is
there another battle-tested way I'm not aware of?
Is there a better way for the client to store the session ID (if
they are a web browser)?
What is the best way to generate a unique session ID? Currently I
generate a random 16-char string that I set as the primary key of
the session-email table.
Is using a MySQL table the most performant/best way to store session
IDs (given it will be queried with each request)?
Do I need to encrypt session IDs in any way? Is it secure for the
client to send it as a 'naked' URL param?
Sorry for having too many questions in one post but I think they're related by the single scenario above. If it makes any difference, I'm using F# and I expect my client to either be an android app or a web app.
Your REST API MUST not know anything about the REST client session, not even the session id. If you don't want to send a password by every request, all you can do is signing the user id, and the timeout, so the service can authenticate based on the signature. Use JSON web token: https://en.wikipedia.org/wiki/JSON_Web_Token
You can have a server side REST client, which can have the session your described. The question is, does it really worth the effort to develop a REST service instead of a regular web application? I am not sure in your case, but typically the answer is no, because you won't have any 3rd party REST client and your application does not have enough traffic to justify the layered architecture or it is not big enough to split into multiple processes, etc...
If security is important then you MUST use a true random generator algorithm or hardware. https://en.wikipedia.org/wiki/Random_number_generation#.22True.22_vs._pseudo-random_numbers It is not safe to send anything through HTTP, you must use HTTPS instead. You MUST use the standard Authorization header instead of a query param. https://en.wikipedia.org/wiki/Basic_access_authentication
Lets assume i have REST api with products and i want it to be accessible only for specified users.
The list of users is known for me and i'm looking for some way to give them safe access to my API.
I don't want to create authentication with username and password, generate token and this stuff.
What i can imagine is that i'm giving each of my users some secret string
and they use it in every request.
And what i need is some example/tutorial/name of this kind of solution,
i'm sure there are some standards for that but i don't know it.
I know it's kind of nooby question - sorry for that, i'm just asking ;).
Thanks in advance!!
You are looking for a simple shared-secret authentication. A simple solution in this case is just to check for the secret as a param (or it could be in the request header). For example, the client can call:
https://example.com/valuable-stuff?secret=2Hard2Gue$$
You implement this in your web request handler as:
SECRET = '2Hard2Gue$$'
function showValuableStuff() {
if (params['secret'] != SECRET)
return NotFounderError;
// now retrieve and output the resource
}
Some practical considerations are:
Use a secure connection for this to prevent the secret being leaked (ie a secure HTTPS exposure).
Be careful where you store the source code if you're hard-coding it. A fancier solution is use an environment variable which is set on the server, so you keep this out of the source code. Or at least to encrypt the part of the source that contains the secret.
While this is fine for simple solutions, it violates the basic security principle of accountability because you are sharing the secret with multiple people. You might want to consider allocating each individual their own random string, in which case, you may as well use HTTP Basic Authentication as it's well supported by Apache and other web servers, and still quite a lightweight approach.
I am a newbie who is writting ASP.Net web API service for the very first time. The issue I am having is how to pass user information or different contexts via service request. For example I want to pass user context (i.e username, user preferences etc.) and lets say security context (i.e. api key, secret etc.) thru each service call. The options I found
1. using Query string
2. custom HTTP headers
3. overload authorization header to pass Jason object
4. cookie
I ditch the idea of using query string as it has 2k limitation, custom header could be ripped by proxy services, dont want to use cookie,creating a jason object of all the context and send it via auth header can work but seems like not a smart way. Any idea? what is the best way of passing those extra information.
I really appreciate if someone help me with some examples.
What options are available for authentication of an MVC3 Web API application that is to be consumed by a JQuery app from another domain?
Here are the constraints/things I've tried so far:-
I don't want to use OAuth; for private apps with limited user bases I cannot expect end users to have their accounts on an existing provider and there is no scope to implement my own
I've had a fully functioning HMAC-SHA256 implemention working just fine using data passed in headers; but this doesn't work in IE because CORS in IE8/9 is broken and doesn't allow you to send headers
I require cross-domain as the consuming app is on a different domain to the API, but can't use jsonp becuase it doesn't allow you to use headers
I'd like to avoid a token (only) based approach, as this is open to replay and violates REST by being stateful
At this point I'm resigned to a HMAC-SHA256 approach that uses either the URL or querystring/post to supply the hash and other variables.
Putting these variables in the URL just seems dirty, and putting them in the querystring/post is a pain.
I was succesfully using the JQuery $.ajaxSetup beforeSend option to generate the hash and attach it to the headers, but as I mentioned you can't use headers with IE8/9.
Now I've had to resort to $.ajaxPrefilter because I can't change the ajax data in beforeSend, and can't just extend data in $.ajaxSetup because I need to dynamically calculate values for the hash based on the type of ajax query.
$.ajaxPrefilter is also an issue because there is no clean/simple way to add the required variables in such a way that is method agnostic... i.e. it has to be querystring for GET and formdata for POST
I must be missing something because I just cannot find a solution that:-
a) supports cross-domain
a) not a massive hack on both the MVC and JQuery sides
c) actually secure
d) works with IE8/9
There has to be someone out there doing this properly...
EDIT
To clarify, the authentication mechanism on the API side is fine... no matter which way I validate the request I generate a GenericPrincipal and use that in the API (the merits of this are for another post, but it does allow me to use the standard authorization mechanisms in MVC, which I prefer to rolling my own... less for other developers on my API to learn and maintain)
The problem lies primarly in the transfer of authentication information from the client to the API:-
- It can't rely on server/API state. So I can't pass username/password in one call, get a token back and then keep using that token (open to replay attack)
- Anything that requires use of request headers is out, because IE uses XDR instead of XHR like the rest of the browsers, and it doesn't support custom headers (I know IE10 supports XHR, but realistically I need IE8+ support)
- I think I'm stuck generating a HMAC and passing it in the URL somewhere (path or querystring) but this seems like a hack because I'm using parts of the request not designed for this
- If I use the path there is a lot of messy parsing because at a minimum I have to pass a username, timestamp and hash with each request; these need to be delimited somehow and I have little control over delimiters being used in the rest of the url
- If I use data (querystring/formdata) I need to change the place I'm sending my authentication details depending on the method I'm using (formdata for POST/PUT/etc and querystring for GET), and I'm also polution the application layer data space with these vars
As bad as it is, the querystring/formdata seems the best option; however now I have to work out how to capture these on each request. I can use a MessageHandler or Filter, but neither provide a convienient way to access the formdata.
I know I could just write all the parsing and handling stuff myself (and it looks like I will) but the point is I can't believe that there isn't a solution to this already. It's like I have (1) support for IE, (2) secure and (3) clean code, and I can only pick two.
Your requirements seem a little bit unjustified to me. You can't ever have everything at the same time, you have to be willing to give something up. A couple of remarks:
OAuth seems to be what you want here, at least with some modifications. You can use Azure's Access Control Service so that you don't have to implement your own token provider. That way, you have "outsourced" the implementation of a secure token provider. Last I checked Azure ACS was still free. There is a lot of clutter when you look for ACS documentation because people mostly use it to plug into another provider like Facebook or Google, but you can tweak it to just be a token provider for your own services.
You seem to worry a lot about replay attacks. Replay attacks almost always are a possibility. I have to just listen to the data passing the wire and send it to your server, even over SSL. Replay attacks are something you need to deal with regardless. Typically what I do is to track a cache of coming requests and add the hash signature to my cache. If I see another request with the same hash within 5 minutes, I ignore it. For this to work, I add the timestamp (millisecond granularity) of the request and some derivative of the URL as my hash parameters. This allows one operation per millisecond to the same address from the same client without the request being marked as replay attack.
You mentioned jQuery which puzzles me a bit if you are using the hashing method. That would mean you actually have your hash algorithm and your signature logic on the client. That's a serious flaw because by just inspecting javascript, I can now know exactly how to sign a request and send it to your server.
Simply said; there is not much special in ASP.NET WebAPI when it comes to authentication.
What I can say is that if you are hosting it inside ASP.NET you'll get support by ASP.NET for the authentication and authorization. In case you have chosen for self-hosting, you will have the option to enable WCF Binding Security options.
When you host your WebAPI in ASP.NET, you will have several authentication options:
Basic Authentication
Forms Authentication - e.g. from any ASP.Net project you can enable Authentication_JSON_AppService.axd in order to the forms authentication
Windows Authentication - HttpClient/WebHttpRequest/WebClient
Or explicitly allow anonymous access to a method of your WebAPI