We have a Web Role which used to run in a single instance for some time. To cope with higher loads (and to get a better SLA) we're currently migrating the role to support multiple instances.
The role uses Forms Authentication (with a custom membership provider), and our understanding was that we would have to enable some sort of shared session state between the instances, so if a user signs in on instance 1 and gets his .ASPXAUTH cookie, then instance 2 knows about this cookie.
We did that, and currently the role is running on two instances, and everything works well. We tested that a user stays signed in, even if his request is processed on the other instance than the one on which he signed in. If the user doesn't sign in, access is denied.
We also checked whether the TableStorageSessionStateProvider created a table in the Azure Table Storage account, and indeed, there is a table Sessions with PartitionKey, RowKey and Timestamp columns.
But, to our astonishment, the Sessions table always stays empty. No matter how many users are signed in, there is no data in the table.
How can these instances communicate, if not through the Sessions table?
You're mixing up two different things here: Authentication and Session State.
It's true that, in order to use Session State with multiple instances, you need a shared store (InProc won't work). In that case TableStorageSessionStateProvider would work since all instances have access to the session data stored here. Session state is used when you store something in the current session of the user, like a shopping cart. And you would call it like this: Session["UserShoppingCart"] = shoppingCart;.
But what you're describing in your question has nothing to do with the Session State, it's all about Forms Authentication. When you authenticate on instance 1, you'll get a ticket in return (stored in the .ASPXAUTH cookie). This ticket is encrypted and signed and contains basic information like your username, expiration, custom user data, ...
Now that you have multiple instances it could be that the next request lands you on instance 2. And I think your question was, how do the instances communicate? Well, they don't. Whenever the request starts, before it reaches your page or your controller, the FormsAuthenticationHttpModule kicks in and looks for the .ASPXAUTH cookie. It checks the signature, decrypts it and then fills the HttpContext.Current.User with the information from the cookie (the ticket).
The only link between the instances is the machineKey (used for encypting/decrypting/signing/validating the cookie). Whenever you deploy multiple instances in Windows Azure, the Fabric Controller makes sure all instances get the same machineKey. This way, instance 2 will be able to decrypt and validate the ticket encryped and signed by instance 1.
Related
I only wish to employ Auth0 as my application's API provider but otherwise
would prefer to maintain any and all data about my users within my application's own database, thus, as one might well surmise, my application's database contains a users table along with several related tables. So, once a user signs up for my app, I'd need to create records for that user within the database. Then, once the user logs in via Auth0, I'd like to retrieve that user's data via information contained within the access token. (The field that presents itself as most useful for this purpose is "azp," or "authorized party.")
I'm thinking that, once the user signs up, as part of the effort to create the relevant records within the database, I'd save the "authorized party" value to a field on the users table. (Which field I cannot say, but, for now, this seems as sound a plan as any.) Then, when the user logs in via the Auth0 hosted API, I would retrieve their record from the database via the "authorized party" value.
Does this sound like a reasonable/sound plan? This is my first time building a full-on application from scratch, and, well, this particular detail has me scratching my head.
Im running a Azure Webapp with application insight.
I know Microsoft cant show the real IP (Client_IP) so I add the real IP address to all requests (Ip).
I have a visitor client_id="h9zbt" that in the last 24h is using 48 different client_IP adresses.
The same user also has several real IPv6 adresses.
I like to block this IP from my website, but I think this looks so strange.
Is it really the same user?
How is Application insight tracking the User_Id?
Image link
Usually application insights is automatically opening a session automatically for each user (look for the ai_session key). Therefore the default user scope would be a session scope.
You can override this behaviour by sending a user context if you have some kind of sign-in. (https://learn.microsoft.com/en-us/azure/application-insights/app-insights-usage-send-user-context)
I find it likely that it's the same user on the same device, just using several IP-addresses, maybe as an unsuccessful attempt to stay anonymous.
User IDs should persist across user sessions to track how users behave
over time. There are various approaches for persisting the ID.
A definition of a user that you already have in your service.
If the service has access to a browser, it can pass the browser a cookie with an ID in it. The ID will persist for as long as the cookie
remains in the user's browser.
If necessary, you can use a new ID each session, but the results about users will be limited. For example, you won't be able to see how
a user's behavior changes over time.
The ID should be a Guid or another string complex enough to identify
each user uniquely. For example, it could be a long random number.
If the ID contains personally identifying information about the user,
it is not an appropriate value to send to Application Insights as a
user ID. You can send such an ID as an authenticated user ID, but it
does not fulfill the user ID requirement for usage scenarios.
mentioned in Azure doc.
https://learn.microsoft.com/en-us/azure/application-insights/app-insights-usage-send-user-context
App A is communicating to database X through web service Y. Service Y enables insert, update and delete operations to data in database X. Many authorized people can use app A and connect to database X through service Y.
Developer Q wants to create a database trigger to log some information about the entries and updates on a table in database X including device id or IP. Can developer Q access some device identity through the established connection to database X through service Y?
If he/she can't, is there a workaround?
Short answer yes. The how is a bit more involved. You did not include what language the web service is written in so keeping it high level and focusing on the implementation agnostic way first.
Most languages used to code web services capture request information - device info, web client info, ip address (not reliable though), authentication identification (if not anonymous access), etc. So one typical way to track this data is create a session table in the database that you write all the pertinent request data to for web service session. Then derive a key for each session. Finally add a column for the session key to each table you execute DML on. Alternate approach is to have an operational table (what you already have) and a matching log table. the operational table doesn't have a session key column, but the logging table does. There are other ways to log activity, these are just some to demonstrate the point.
Another way, OO example, is to create a derived connection class that you add in web service session info to. This can then be accessed at the database command execution, usually done via a command object, and instead of writing triggers you programmatically do the logging.
In your particular case, the latter approach seems more appropriate than triggers since triggers could fire when someone does DML on the database directly, or another interface instead of the web service. In which case there would be no request info to begin with.
How would I retrieve all valid sessions for a specific user? For example, if the user is logged in from multiple devices and decides to change password, or reset password. I need to be able to expire all active sessions and log the user out of all devices. This is specially important if the user is suspecting that his/her account has been compromised and needs to change the password. Currently I can retrieve RMEs but not sessions. I know this is doable from the UI but I need to put this feature in an SDK or API. Is there a curl command to easily achieve this?
Sarah,
Currently there is no endpoint that will let you invalidate all user sessions.You would need the session token of each session and then call the /json/sessions/?_action=logout REST endpoint multiple times (once per session).
That being said you can use the following class to get the list of sessions for a particular user:
com.iplanet.dpro.session.service.SessionCount
You can read the javadoc here.
There are some constraints for using this method though. Session Quota must be enabled. You can enable Session Quota on the admin console by going to Configuration -> Global -> Session page and:
Set the number of "Active User Sessions"
Turn on "Enable Quota Constraints"
To sum up, you can create your own custom endpoint that will take the User ID and invoke SessionCount.getAllSessionsByUUID(uuid) to get the list of active sessions. After that, you can iterate through the list of sessions and invalidate them one by one.
Hope this answers your question.
I am trying to use the new authentication system and I cannot find any decent articles/documentation to get what i want. Plenty of stuff out there explaining how the authentication process works out of the box but realistically you will need more.
First of all how do you control which database you store user information? I have read in many place that you can add a connection string. Ok great, but how do you get that connection string to be used by the authentication system?
And how would this work in a web farm, assuming user account information is split across databases with a little piece of logic which decides which database a user should login against?
I have used keystone extensively and it really isnt bad to implement. Its the authentication mechanism of Openstack. Check it out here http://docs.openstack.org/developer/keystone/
To answer your question users would first authenticate with it, receive a token, then they would present their token at any of your servers. If your data is split up, you can configure keystone to only allow access to certain areas of you backend via groups.
Changing the underlying database needs to steps. You have to add the connection string for the database you want to use for Identity. After this you have to change the base constructor call in your DB context to pass your new connection string to the base class (this is your missing step). An example for it is shown in this thread.
For your second question I don't have a good answer, because I haven't used Identity in a multiple DB servers scenario yet.