I have created my own IConnectionIdGenerator implementation which for simpicty in my webforms application names the client connection Id by the EmailAddress.ToLower() of the logged in authenticated user (if that’s not available then it defaults back a guid).
Calling the client from my page code behind all works fine.
hubContext.Clients[LoggedInUser.EmailAddress.ToLower()].updateProgress(i)
However it seems that if I open another browser or tab with the same logged in user both the foreverframe connection on both windows keeps giving a 301 result then a 200 result alternating and repeating.
I assumed that assigning the same connection Id would just give me an easy way to make sure messages correctly go to the correct user of the system no matter where they connected.
Do they always have to be unique and will I have to build another layer to manage connections to logged-in user accounts or am I missing a trick here?
Connection ids have to be unique. If you don't make them unique then one will kick the other connection offline. Internally we use the connection id as a unique identifier for a connection and we disconnect dupes.
If you get repeated 301 responses it's likely because you have a folder in your app called signalr, and it isn't directly related to sharing connection ids.
I recently tried to do the same and experienced the same problems, so my conclusion is that the connection id must be unique, otherwise everything starts to fail with repeated 301 and 200 responses.
What I did to workaround this problem was to use the default GUID connection id and instead add the connection to a group which is identified by my own id (email address in your case) after starting the connection.
This way I can call Clients[emailAddress].doSomething() and it broadcasts to all open tabs of this user.
Yes thats perfect, I came to a simlar conclusion.
I also trying to think of a way to make client broadcast messages to the same email address group unique to the current url (so a progress bar on one page does not also update a progress bar on another)
I will either make extend the group id to be something like emailAddress + currentURL so its just a combination of the two strings. However that would make any global site broadcasts (to all urls) difficult to do unless there is a way of getting the groups collection and parsing out the email addresses and sending the message to each email address + url combination.
It may be better if I just tag on some client side check and send a progress bar Id as a parameter that is unique to the progress bar on the page that is ment to be updated.
Related
Is it okay to pass IDs in the query string? For example:
example.com/viewperson.aspx?personid=22d62e18-2383-42ca-ba6d-a535355b98bb
Does this change (less risk) for an intranet site?
If a public site, assume anyone can access (shoulder serving, browser logging, etc).. even though we’re under SSL I still assume “out there”. Obviously, security will be applied to disallow an unauthenticated user from viewing page. But still a risk?
An added benefit of using query string is bookmarking a few (e.g. persons in this case) you want to call back up without having to go through the front door and look back up.
Would never pass anything meaningful, but maybe an ID is meaningful enough to not pass?
An alternative would be a cookie or session variable, of course.
Assuming these are resources you want protected its not a risk provided that requests for resources by id are both authenticated and authorised. Meaning you should verify that the request comes from a logged in user and that the user has access to that resource.
So if I belong to company 5 i shouldn't be able to open /companies/4.
Otherwise no issues and there is no alternative approach I am aware of. (by which I mean you must provide an identifier somehow)
when a user logs off my application (setting enc_token to null) how do I disable signalR (using angular)?
I tried
abp.signalr = null;
The issue is, if a user logs off then back on again, 2 connections are then made. What is the correct way to stop it?
SignalR version 2 does not have a built-in server API for disconnecting clients. Here's the docs stating it.
Essentially, you are dealing with a situation where the handling of connections, reconnects, etc. are not aligning.
You could assign your logged in user to a group and just send data based on group. This way it won't matter if you have multiple connections. When they are disconnected, remove them from the group using OnDisconnect(). Check out the section on Working with Groups at the same link.
I have some webservices which are called by some clients and that includes through mobile and web. I have no control on the clients code.
But, I need to identify who is calling my web services, via the IP address or something else.
Is there any way to identify that?
A better approach to tracking this sort of thing is to introduce the notion of an API key. That way you know exactly who is using your service and you can track their usage etc.
On every call to your service the user would have to provide their key as a means of authorisation (not authentication). This sort of approach can generally help avoid misuse of an API, however, it can't eradicate it completely. At least with this approach if you do find malicious user it's as simple as disabling that particular API key.
You should check your IIS Logs, these will list (if you have them turned on, default they are on) all the requests made to your server.
So search through the log for the URL of the service and check the logs around the time of requests you are having issues with and it will list the IP address.
Your logs can generally be found at: C:\inetpub\logs\LogFiles
If the folder is empty then you are out of luck currently, you will need to turn logging on in IIS and then you will be able to check them after a few hours and start seeing where requests are coming from.
E.g a sample from a log.
2012-10-29 04:49:44 129.35.250.132 GET /favicon.ico/sign-in returnUrl=%252ffavicon.ico 82 - 27.x.x.x Mozilla/5.0+(Windows+NT+6.1;+rv:16.0)+Gecko/20100101+Firefox/16.0 200 0 0 514
So the first highlighted item is the date and time, and the second highlighted item is the IP address (redacted as it's a real log.)
I have two web applications and both are developed in ASP.NET. Now I want to provide a feature which enables the user to click from one URL in application site (one virtual directory of IIS) A to the other URL in application site B (another virtual directory of IIS).
I have two ideas to implement them, but both of them have issues. I want to know what solution should be optimum solution?
Solution 1: using cookie, so from both application sites, we could retrieve user ID information from reading cookie, but I am afraid if cookie is disabled in browser, this "jump" feature never works.
Solution 2: When the user redirects to an URL in another site, I could append user ID after the URL, I could redirect to this URL in another site http://www.anotherapplicationsite.com/somesuburl?userID=foo, but I am afraird that in this way userID will be exposed easily which raise security issues.
I work with this sort of thing a lot. What you're looking for sounds like a candidate Single Sign-on solution or Federated Security.
You might try doing something similar to the following:
Create a simple db or other sort of table storage with two columns "nonce" and "username"
When you build the link to the other site create a GUID or other unique identifier to use as a one-time nonce, passing it as a querystring ?id=. Insert an entry into the table with the current authenticated username and the unique identifier you created.
When you reach the destination of your link, pass the unique identifier to call a webservice that will will match up the identifier with the username in the database you inserted before jumping to the second site (secure this with ssl).
If the nonce checks out with a valid username, you're all set. The webservice should remove the used entry and the table should stay more or less empty any time you are not in the middle of a transaction.
It is also good to include a datetime in your nonce/username table and expire it in 60 seconds or less to minimize the risk of replay attacks. We also require client certificates for external applications to call the webservice in order to verify the identity of the caller. Internal applications don't really necessitate using client certificates.
A nice thing about this is that it scales fairly well to as many sites as you would like to use
Not perfect security, but we've never had a significant compromise with a such as system.
As long as you have a good authentication system in place on the second website I think solution 2 is the one for you, taking into account the remark Andrew made about the sensitive ID's of course.
For more information on encryption: check the documentation of the FormsAuthentication.Encrypt Method . I think they even do something with writing a value in a cookie in that example.
If you put the userid in a query string and that's all the 2nd app uses to allow login, what's to keep me from manually typing in other users id's? You'd still have to prompt for password on the new site.
I'd use a database to hold login information, and have both sites reference that same db. Use it like you'd use a session.
D
I don't think 1) will work due to browser security (cookies from one domain cannot be read by another domain). I would go with 2), except I would encrypt the querystring value.
EDIT: For more info on cookie privacy/security issues, check out the "Privacy and third-party cookies" section here.
What are you using as the user's id? If you are using their social security number or email (something sensitive) then you are going to want to encrypt the value before you put it on the query string. Otherwise (if the user's id is something ambiguous like an integer or a GUID) it should be fine to put the id on the query string.
using cross domain, you can not SHARE the session, so I was thinking about POST
idea 1
if afraid of "showing" the username in the address, why not sending a POST?
<form name="myForm" action="http://www.mydomain.com/myLandingPage.aspx">
<input type="hidden" id="userid" value="myUsername" />
click here
</form>
but then... off course, "View Source Code" will show it
idea 2
then.. I remembered that I do the same, but sending a Encrypted string like:
http://www.anotherapplicationsite.com/somesuburl?userID=HhN01vcEEtMmwdNFliM8QYg+Y89xzBOJJG+BH/ARC7g=
you can use Rijndael algorithm to perform this, link below has VB and C# code:
http://www.obviex.com/samples/EncryptionWithSalt.aspx
then in site 2, just Decrypt and check if the user exists... if it does, continue, if not saying that the user tried to temper the query string :)
I want to let the user automatically re-login in my Flex app, which uses Basic Authentication
By the way, I have noted this StackOverflow question, which is relevant, but does not address the question of logging out client-side.
For example, after user A logs in, user B comes to the browser, goes to the login screen (perhaps in a new tab) and logs in.
This should mean that I send user B's credentials in the HTTP headers, and that since these are different from user A's, the server notes the fact and creates a new and separate session.
However, Flex's HTTP proxy catches the header and actually ignores these new credentials.
Flex does offer a way to tell the server to logout, and the Flex login code could invoke this every time before sending credentials, but that seems like an ugly workaround. I want to be able to do this client-side. I could also use a non-standard header for Basic Authentication (since I control the server-side Authentication as well), but that also seems like an ugly workaround.
Is there some way to simply end the session on client-side from Flex code? This is possible from JavaScript, for example.
And is there a way to directly work with cookies at client-side, as I can in JavaScript?
I understand that some of the limitations may be caused by security considerations, but all my communication is to the "home" server, so it should be possible to avoid the restrictions.
You're sort of asking a couple of different questions here.
You can't actually end a basic-auth "session" manually per se (at least not to the best of my knowledge); at best, you can authenticate against a kind of variable basic-auth realm, which may or may not work for you, but otherwise, you're sort of stuck with the first-authenticated session for the duration of the browser instance. Generally not the best way to go, unless you're pretty sure the user owns the machine, or can be depended on to close the browser after each session.
That leaves at least two other options, then. The first is to send in your credentials with an URLRequest object (the post you cited, which I wrote, shows how to do that), and to have your HTTP response hand back something indicating the credentials were accepted -- e.g., a GUID, maybe, generated and stored in some session table (in the database sense) on the server, perhaps. Then on successive HTTP requests, you might send along that GUID in an HTTP header, or as a value in each GET or POST request (similarly to the way Facebook handles their API clients, for instance), check the timeliness of that value on the server, and if all's well, carry on. To "log out," then, you'd simply send in a request to invalidate that GUID, perform the necessary cleanup on the server and inside your Flex app, and all should be fine: the next user can sit down, log in, authenticate, and the process continues.
Another way would be to work with cookies directly. The cookie mechanisms are actually handled mostly for you in Flex, though, since everything gets passed back and forth by the browser on your behalf. For example, if you send in a URLRequest with a username and password, and the server responds with a cookie of any kind, each request you make thereafter will package and send the same cookie, so in most cases, all you need to do is parse the initial response from the server (to set the state of your Flex app), assume the continued presence of the cookie, and when it's time to log out, send a URLRequest to log out, kill the cookie on the server, on status=200 do your Flex-app cleanup, and so on. Accessing the cookie values directly isn't the easiest thing in the world, though; you can use ExternalInterface as a proxy to JavaScript (examples of this online and here on SO, I'm sure), and get at them that way, but there's a good chance you don't even have to do that.
Hopefully that helps. Good luck!
Note also this post, which details some of the incredible distortion that Flex adds to HTTP Requests.