I have created a REST application in Delphi using kbmMW middleware. It works really great, is fast, efficient etc. But in testing I've used both a Delphi client - which more closely simulates how it will be used in production (iOS, Android, Windows Tablet clients), and several different web browsers with manual REST uri entry.
The REST response format for the most part is JSON, but can be anything I want it to be. One of the REST calls I coded returns the session token.
In order to obtain the session token one has to request a resource using https; when the server sees that you have not yet authenticated it kicks back a 401 unauthorized, which tells the browser to force an authentication dialog, seeking username and password, or triggers the indy client to supply the pre-coded credentials.
I set the internal, kbmMW-wrapped Indy http component to use basic authentication (only inside ssl, of course); once authenticated the server generates a session-based token and returns the token to the client.
When I test this in my Delphi client, which uses Indy's TIdHTTP client, and I set it to use basic auth, set the username and the password, and initiate the request, the Indy components preserve the session token and apparently reuse it. I can call the function on the server that returns my session token, and the token remains the same for the lifetime of the session.
If I authenticate with the browser and the un/pw dialog, then call the function to return the session token, I am required to authenticate once using un/pw, but every subsequent request to retrieve the session token returns a different token every time.
My question is, does this mean that a web browser poses a potential security risk to my server? What governs how long a session lasts when the requesting client is a TIdHTTP vs. when the requesting client is a web browser (I've tested IE, Chrome, Firefox, Opera - all the same response)?
Why does a browser get a different token with every request, while an indy client reuses the same token over and over until expiration?
Does this mean that a potential hacker could compromise my server by utilizing a DDOS attack vector and creating sessions on my server until it runs out of memory?
I thought that the Indy http server would distinguish a requestor based on form vars like Referer, IP Address, Browser type etc. How can a browser, executing the same request over and over with the same IP, Referer etc. force a new login at the server side each time?
Is the browser caching the username and password and ignoring the token?
The server side authentication event only fires once with an indy client request, but fires with every request from a web browser, resubmitting the un/pw combo every time, and ignoring the token.
Should I set an ETag in the response header to the token so that the browser won't keep logging in and creating new sessions?
Help!
Related
I am learning about CSRF Tokens and how they help secure your web application. I understand the basics of it, but I am confused as to how it works in practice when the web server and api are separate. In practice how is the token generated, added to the HTML and known by the API?
For example, if I host my web app on something like Nginx or S3 and serve APIs via Spring Boot, how does the HTML with the embedded token get generated and passed to the client? Would the Sprint Boot API need to generate the token and HTML and return that to the client? Is there a different flow that am I missing? If this is the case, what is the point of it being embedded in HTML at all?
All of the documentation I have read assumes you are using something like MVC or skips over this entirely.
CSRF protection is only necessary for requests made by a client (for example, a browser) that silently adds credentials for the current user, by sending a session cookie, resending username and password that were previously typed in ("Basic Authentication") or by including a client certificate. This is because users may be tricked into making unwanted such requests by visiting a malicious web page, and these unwanted requests are then made with their credentials, that is, on their behalf.
For requests made by your web server to an API endpoint, this does not apply, therefore the API endpoint need not offer CSRF protection. A web server cannot be tricked into making unwanted requests.
Or can it? Imagine that the web server offers a "proxy" endpoint that converts incoming requests into requests to the API endpoint, and that sends the API response back to the client:
Client --request--> web server --converted request--> API endpoint
Client <--converted response-- web server <--response-- API endpoint
Further imagine that, as part of the request conversion, credentials from the client are forwarded to the API. For example, a session cookie coming from the browser is converted into an Authorization: Bearer <jwt> header that is sent to the API endpoint. Then an unwanted request to the web server endpoint with credentials effectively becomes a request to the API, and a new CSRF vulnerability has appeared: this time on the web server.
The web server must then protect its own "proxy" endpoint against CSRF by issuing and validating a CSRF token.
I am using OkHttp to login to a website with username and password. After login any attempt to request a resource is followed with a token=xxxxxxaxx-xxax-xxxa-xxaa-axaxxaxaxxxx in the query path.
I am not certain this is a security token, or just a UUID? It follows the format 8-4-4-4-12 in length and is always lower case alphanumeric.
In order to send new requests to the service I need to acquire/generate token after login. In some cases I note in future requests that both the InstanceId=&token= is passed - where they both pass the same value for token and instanceid.
After login I do not see this token in the of the response headers, it just starts to appear in all future requests.
After login the following URLs are accessed:
portal
launch
htmlnavigator
getCSRFTokenVaue
getUserLocale
createToken
I have confirmed that the token returned by the createToken URL is not the same token that is used in later requests.
The various cookies sent by the server I can user with CookieManager, but where does the security token come from (or usually come from?) - What browser tools might help me beyond reading all the headers and responses.
It is a REST service, and each frame within the browser gets its own token, so difference requests in the same frame use the same token, open a new frame and that frame uses a new token.
The token is passed in the URI.
The web application UI has frames/pages within the main page and opening each new page generates a new token specific to that page
Multiple requests to each frame all send the same token so the tokens are not query authentication (like here)
If more information is required I will update the question but I can not name the system.
It may not be possible to know exactly what the url token is used for, but from what you say, different frames (tabs) in the same browser get different tokens, so it could be a frame specific session id (unusual but might be used to permit multiple sessions in systems where auth is stateless while preventing side-channel attacks) or more likely a form of double-submit CSRF token.
I want to build a REST API which will be used by both mobile app and also a website. I was wondering how would I go about implementing a simple login system for users?
For a simple website, after checking the username and password, one could set a SESSION variable and have the user "logged in".
Now, REST is stateless so I suspect that the above is not the way to go about. I thought that a possible solution would be to have the server generate and return an access token each time the user logs in, and the client will need to attach this access token to every subsequent request to access protected endpoints.
Is the above a viable solution or what is the industry standard for something like this?
(I found OAuth 2.0 to be overkill, but I could be wrong)
There are several token authentication schemes, but if you're looking for the industry standard, then JWT (JSON Web Token) is the way to go. Here's how the process usually goes:
Client sends his credentials (e.g. username and password) to the server.
The server verifies that the credentials are correct, generates a JWT and returns it to the client. Client saves the token in e.g. localStorage.
For each subsequent request, the client will attach the JWT as a part of the request (usually in the "Authorization" header).
Server will be able to decode the JWT and decide if the client should have access to the requested resource.
Now, some interesting features of JWT come from the fact that there is data encoded in it. Some of it everyone can decode, and some only the server can decode.
So, for example, you could encode the user's id and profile picture in the JWT so that the client can use the data from it, not having to do another request to the server to get his profile.
JWT has embedded info about expiration. The server can set the expiration time.
Another cool thing about JWTs is that they are invalid if changed. Imagine you stole someone's token, but it's expired. You try to change the expire information inside the token to some time in the future, and send it to the server. Server will deem that token invalid, because the contents doesn't match the signature attached, and a valid signature can only be generated by the server.
I want to test an API which has the followoing instruction:
This API requires the caller to have an authenticated user web session.
When I login to the application and send a GET request in other tab it works. But I want to send a PUT request now so I cannot use browser. How can I have an authenticated user session while sending request through some other rest client. For eg: postman/ mozilla rest client.
I have tried logging into application through chrome and then using postman rest client. But it did not work. I have also tried Basic authentication providing application username and password.
So, given you mentioned you're using JWT, your API is most likely handing out this token upon logging in. At this moment your web client (javascript?) is probably storing it somewhere (cookie, local storage, session storage… – you can use your browser's dev tools to inspect). For all subsequent requests, this token is attached. If this token is getting persisted as a cookie, the browser itself takes care of attaching it to every request. If it is persisted somewhere else, your client has to "manually" attach this token to every request.
If you want to test your API call, first you need to login and get your hands on the token. Then, for all authenticated requests, you need to attach this token (probably as the Authorization HTTP header).
After going throught lot of comments from different people about session management for Rest supported applications, here what I have thought of doing.
My application can be accessed from Browser (as a normal web app) and Mobile devices as well. Application was written with the http session management in server at first for browser based app. Now while getting Mobile client, we have implemented Rest web services, with same service layer for mobile device and browser client as well.
When user logs in with mobile device, we are creating a unique auth token, generate a http session and we store the http session with this token ID as key, value map in app. Later on we expect every user request from mobile device to return this token, and using this token get the session from map and continue.
Can somebody review my approach and confirm if it is fine?
Now, I have a second question - We are using JsonPRequestBuilder from GWT to invoke my back end REST services with jersey-guice. How do I send this token in http header during jsonp call from GWT?
"Session in REST" is an oxymoron.
When user logs in with mobile device, we are creating a unique auth token
Seems fine, though it looks a bit like you reinvented OAuth.
generate a http session and we store the http session with this token ID as key, value map in app.
Keeping some cache on the server-side for faster access is fine, but don't call it a session, and don't bind it to a specific token (you can bind it to a user if the data is user-specific; the user ID would simply be part of the cache key if it makes sense).
You don't talk about expiration of that cache, or how/when you clean it up and free memory.
Now, I have a second question - We are using JsonPRequestBuilder from GWT to invoke my back end REST services with jersey-guice. How do I send this token in http header during jsonp call from GWT?
As #Arcadien said, JSONP is just about inserting a <script> element in the page, so you only have control of the URL, and thus this is where you should/can pass the authentication token (albeit not being really secure).
May I question the reason you use JSONP from a mobile "native" app? AFAIK there's no SOP issue from UIWebViews or similar, so a RequestBuilder or XMLHttprequest would Just Work™.
For the second : with JSONP, you have to add your token as plain http parameter, you have no access to an object like Request when using regular XMLHttpRequest. So you can't set any kind of headers, everything should go in the query string.