Manage web application security on shared computers and kiosks - asp.net

We have a web application that is publicly accessible.
When a user is logged in he fills his personal details.
The Problem
The user may forget to close the browser in a kiosk or a shared environment, potentially allowing some other user to see his personal information.
We are using a session timeout of 5 min,
My Thoughts
Is it better to build a separate app for Kiosks environment where i can ask the users Is this a shared computer or public. If yes how would i Implement it further?
For every 3 minutes of inactivity we want to prompt the user: "Do you want to continue?" If yes, get confirmation for password, just to make it more secure.
I have seen the below link
Security considerations for an ASP.Net web application that will be used on a public computer or kiosk
Could you please share more thoughts on this issue: how to make it more secure.

You will have to use JavaScript of some sort. The server does not have the ability to update the client Web page without some sort of client side scripting (obviously JavaScript) to handle a request. I have done something similar, asking a user if they want to keep their session alive through showing a Pop-Up message. But in your case it seems like you should create a DNN page for re-login and add a custom module or HTML block with a simple JavaScript in it to every page you want to check logins (or put it in your template header or footer) which redirects the user to a re-login screen. Something like:
function setHeartbeat() {
setTimeout("heartbeat()", 300000); // every 5 min
}
function heartbeat() {
window.location.href = "Relogin.aspx?LastPage=" + window.location.href;
}
then Relogin.aspx will have a message at the top that the user has been idle for 3 minutes, and provide the password box. After the user logs in you can redirect them back to LastPage (it's been a hwile since I've used DNN, but I think there is a way to format the URL so it automatically redirects).
A more user friendly option would be to show a Pop-Up after the 3 minutes, showing a message and password field with an OK button. Again, this can be done with jQuery, where you have something like:
<div id="confirmSession" style="display: none">
<p class="message" style="display: none;"></p>
<p>You have been idle for 3 minutes, if you want to continue your session please re-enter your password.</p>
<p>Password: <input type="password" id="password" /></p>
<input type="button" id="btnContinueSession" />
<input type="hidden" id="userName" value='<%# HttpContext.Current.User.Principal.Identity %>' />
</div>
and the following JavaScript:
function setHeartbeat() {
setTimeout("heartbeat()", 300000); // every 5 min
}
function heartbeat() {
$("#confirmSession").show();
}
$("#btnContinueSession").click(function () {
$.ajax({
type: "post",
url: "/relogin.aspx",
error: function(returnval) {
// Login failed for some reason, typically page not available 404 error, or code threw an error. so have the user try again.
$(".message").text(returnval + " failure");
$(".message").show();
},
success: function (returnval) {
$("#confirmSession").hide();
setHeartbeat();
}
});
});
Here you'll have to create a relogin.aspx page or some other service which will take in the username and password, re-validate the user, then either throw an error if the password was invalid (caught in the jQuery above and shown to the user). This is obviously a bit more work, and will need custom coding for the validation, versus simply redirecting to a login screen, but it much more user friendly.
In this Ajax approach, it's worth noting that your server session timeout may have to be longer than 3 minutes. If it's three minutes or less, and the user enters their password, they will already be logged out of the server, and you'll get an invalid authentication error. So overall redirecting to the login page may make the most sense. But you'll want to make sure that if a user has entered data that you save it in a cookie or somehow, so you can re-fill it (I've heard hundreds of times of people being frustrated that their data was "lost").
Examples I've taken from are:
Keeping Session alive with jQuery
StackOverflow Ajax Post success error
StackOverflow keeping session open/alive

Related

How to pass parameters from Wordpress Contact Form 7 to an external server?

I have a login form created in Wordpress using Contact form 7. I'm tryig to pass parameters from this form to an external server. But it is not happening.
I am a designer, and not much of a programmer. I understand code(sometimes) but can not write it from the scratch.
I have designed a website for a client. This client has a "Flying Returns" like logistic membership system in which members get lots of perks in shipping etc. This system is on their own server. They want the users to log in to that system from this website.
So I have created a login form using Contact Form 7. I have set skip_mail: on; I have tried a few plugins login, but either they dont log into different servers or are expensive, or does not yield correct URL and hence does not log into the system. Therefore I have finally decided to make it happen using code.
Their programmer has given me following JS code that will take the parameters from this form and pass on to their system. IF the parameters are correct, then the user is logged into the system and taken to the member's dashboard page on their server (not my website/server), else it returns an error message, {"error":"Login Data Incorrect.."}
I have tried to put this code with in the contact form. Here is the code (i've hidden the actual IP address, sorry):
<script>
document.addEventListener( 'wpcf7submit', function( event ) {
alert( "Fire!" );
document.location.href="http://49.XXX.XXX.202:XXXX/glslink/servlet/GPLogin?password="+$('#password').val()+"&emailid="+$('#emailid').val();
}, false );
</script>
If I remove the document.location line, it shows the alert. But the above, in its entirety does nothing. If I use the URL, replace variables with actual values and paste it browser, it logs me into the system without a hitch.
I have tried quite a few different codes which I could find as possible solution on internet, this site including, but to no avail.
Please help me out. I want the email and password to be passed to this external server, if they are correct then the user should log in and see their dashboard there. Else if it gives the above mentioned error message, then I should be able to reset the form and give an error message to the user.

Can't reset user's password in Google Identity Toolkit: "CAPTCHA_CHECK_FAILED"

I'm trying to setup my Google Identity Toolkit so users can reset their passwords. I'm following the documentation here: https://developers.google.com/identity/toolkit/web/required-endpoints#send_email_url
I'm using the PHP Gitkit Client outlined here: https://github.com/google/identity-toolkit-php-client/blob/master/src/GitkitClient.php
Specifically the function getOobResults() on line 307 seems to be unhappy for some reason. Here's where I'm at:
User sets up account and logs in successfully
User then logs out and starts to log back in, enters email in and clicks "Forgot password"
reCaptcha is shown, click check box and then hit continue
At this point my 'Send Email URL' endpoint (gitkitEmail.php) is successfully called and the following POST is set to it (dropping the full '&response' param since it goes on for a while):
action=resetPassword&email=xodfebefa%40nada.ltd&challenge&response=03ACgFB9tGlNt2KAGhrVY....
I then take that string and parse it using parse_str(); since getOobResults() is looking for an array. However, response I get back is always:
{
"response_body": {
"error": "CAPTCHA_CHECK_FAILED"
}
}
I searched around but can't find any details on this error. Any help would be appreciated. I don't have a reCaptcha setup anywhere on my site, unsure if this is expecting me to do that and that's why it's failing? Also, I did bump all my code to a production environment and got the same error there as I did on my localhost.

SqlConnection.ChangePassword new password does not work immediately

I inherited a web application that has uses individual SQL account for authentication. I need to update the login procedure to use a different type of hash.
Pseudo code
if (login(newhash(password)) == 0) // login using new hash function doesn't work
{
if (login(oldhash(password)) == 1) // login with old hash works
{
SqlConnection.ChangePassword(connstr);
login(newhash(password));
}
}
The problem is the second login(newhash(password) would not immediately work. If I put a System.Threading.Thread.Sleep(5000) in between the ChangePassword and the login then it would work. SqlConnection is closed properly when doing the login()
I also tried using sp_password instead, but it still won't authenticate immediately with the new password. Is there any way to eliminate this "password change lag"?
EDIT:
I added SqlConnection.ClearPool(conn) and the problem persist. SQL Profiler showed the following:
Audit Login Failed
Audit Login
SQL:BatchStarting
SQLBatchCompleted
Audit Login Change Password Event
Audit Login
Audit Login Failed
So everything is expected from 1-6, however I don't know where does #7 come from.
I believe it's a connection in the connection pool that is getting in your way, How Can I Prevent Recurring Automatic Connections to Oracle Database? . Try clearing the pool before trying to reauthenticate, https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.clearpool(v=vs.110).aspx .

Race condition when going directly secured page

I am running into a race condition when an unknown user is trying to access a secured page.
Iron-Router code:
function secured() {
if ( Meteor.user() == null ) {
Meteor.loginWithLinkedin({
},function (err){
if(err){
console.log("Error when login with LinkedIn."+JSON.stringify(err));
}
});
}
}
Router.map(function () {this.route('customer_researchRequest', {
before: secured,
waitOn: waitOnHuman,
path: '/research/request',
template: 'customer_researchRequest',
layoutTemplate: 'customer_requestLayout'
});});
On the server:
ServiceConfiguration.configurations.remove({
service: 'linkedin'
});
ServiceConfiguration.configurations.insert({... settings ...});
If the user goes directly to /research/request, there is a race condition.
before condition fires
(on client)ServiceConfiguration.configurations has no configuration
client has exception about no linkedin service defined.
server publishes the ServiceConfiguration.configurations to the client
At this point, my solution is to hard code in the clientId and other linkedin config information into the linkedin authentication code ( Yech ).
Is there a better more elegant/correct solution?
Update #1: My solution was to tweak the meteor-linkedin package so that it expects the linkedIn clientId as an option and does not depend on the ServiceConfiguration.configuration. This way the clientId is always available.
Edited to address comment:
Maybe a different use of reactivity can help. Set up a deferred redirect to customer_researchRequest, by first diverting the user, then bringing them up
A) Have secured() save the original destination path to the session. Redirect to a page you allow without security (or a 'Loading...' page), to avoid your #3
B) when the login callback happens, save another flag to the session, indicating that #4 is no longer true
C) have a Deps.autorun redirect to the desired path when both flags become true.
Someone else may know a smarter way, (maybe waitOn should test for the config) but ...
The best solution turns out to be my "hack" of creating a forked meteor-linkedin which accepts the client configuration in the login call.
We edited the meteor-linkedin so that the Meteor.loginWithLinkedIn() call supplied the linkedIn clientId.
Currently, Meteor's ServiceConfiguration is stored in a mongo table and needs to be published from the server to client. The clientId is essentially a static configuration variable that might as well be encoded into the client code. Just putting the linkedin clientId directly in the login code turns out to be infinitely more reliable and simpler.
Even if Meteor was to 'fix' the publishing race condition, we would stick with our solution: it is bulletproof and guaranteed to work. You can borrow our code our meteor-linkedin and accounts-meteor-linkedin
The meteor dev people aren't planning on fixing the issue. I agree with this decision, it is much better to just have the (constant) client configuration on the client rather than being stored on the server and sent to the client.
Update: In the end for a variety of reasons, we almost entirely abandoning the meteor oauth code. The client-side centric approach with popup dialogs caused numerous problems. I talk about some of the issues on the 1911 bug report. We ended up triggering the oauth code ourselves server-side.

ACS - bypassing user redirection to IdP?

I have only recently been looking into ACS, AAL, WAAD and I would like to avoid redirecting users to the login page of their IDP. I want to keep my users within my site and present them with a dropdown to choose who they wish to authenticate with and an area to request a username and password, then acquire token via code. Is this possible?
I have been reviewing some sample applications and produce a quick mock-up, but cant seem to get things working e.g.
_authContext = new AuthenticationContext("https://littledeadbunny.accesscontrol.windows.net");
string enteredEmailDomain = UserNameTextbox.Text.Substring(UserNameTextbox.Text.IndexOf('#') + 1);
IList<IdentityProviderDescriptor> idpdList = _authContext.GetProviders("http://littledeadbunny.com/NonInteractive");
foreach (IdentityProviderDescriptor idpd in idpdList)
{
if (String.Compare(ServiceRealmDropDownList.SelectedValue, idpd.Name, StringComparison.OrdinalIgnoreCase) == 0)
{
Credential credential;
credential = new UsernamePasswordCredential(enteredEmailDomain, UserNameTextbox.Text, PasswordTextbox.Text);
_assertionCredential = _authContext.AcquireToken("http://littledeadbunny.com/NonInteractive", idpd, credential);
return;
}
}
Using the code above, when I try to use the Windows Azure Active Directory User (admin), i get the error "Data at the root level is invalid. Line 1, position 1." where I attempt to acquiretoken.
When I use Google, I get an error "0x8010000C: No identity provider matches the requested protocol".
If there is a working sample? if I am doing something obviously wrong, I would appreciate the correction.
This is not supported for passive identity providers. IdPs like Google, Facebook, etc. don't want other people collecting credentials for them, as this leads to security issues and possible phishing attacks. They also don't support it because they need to be able to show a permission dialog (that screen that asks the user if they want to release data to you) which they can't do without the browser redirecting to them. Furthermore, Google in particular supports two-factor auth, which you couldn't replicate, and generally collecting credentials opens up whole cans of worms around other UI problems such as incorrect or forgotten passwords.
This is also generally a bad user experience, because your users are fairly likely to already be logged in to Google and have cookies there. If so, and if they've already consented to your app, they would just be silently redirected back to you. In your scenario, even if the user is already logged in they'd still have to provide a username/password.
The correct way to do these sorts of logins is to render a browser control in your app that allows the user to log in at their IdP, which is what AAL helps with.
I had the same error, executing a powerscript solved that error
PS C:\windows\system32> $replyUrl = New-MsolServicePrincipalAddresses
-Address https://mydomain.accesscontrol.windows.net/
PS C:\windows\system32> New-MsolServicePrincipal -ServicePrincipalNames
#("https://mydomain.accesscontrol.windows.net/") -DisplayName
"MyDomain Namespace" -Addresses $replyUrl
But i'm stuck anyway with a 403 permission error
If you get any further i would like to know how :)

Resources