Firebase: How do I implement secure session tracking? - firebase

EDIT: To try to simplify this question... at a very basic level, and I believe this has to be a fairly basic need of a session system... how do we have a SECURE session tracker without breaking onDisconnect functionality? If you add security rules, onDisconnect doesn't work, if you DON'T add security rules anyone can "spoof" a login session by writing to the unprotected table or deleting someone else's presence.
I'm trying to solve a problem where "onDisconnect" is not being called because my security rules only allow the logged in user to write their presence data in /sessions/$userid/"true" ... onDisconnect works so long as that user is logged in, but if that user closes their browser AFTER they have been logged out, or logged out due to timeout, onDisconnect gets blocked by the security rules.
At first I thought... "oh, I can just trace back to where logout happens and put in another clean up of session presence there." but had I thought that through more I would realize that the auth = newFirebaseSimpleLogin callback "else" block seems to be the only way to detect log outs. ON TOP OF THAT, the callback is returned AFTER the logout occurs so that returns me to square one where I need to be logged in so that the onDisconnect call can remove my session, but by this time, I'm already logged out.
Am I missing something? Is there a pre-logout call I'm not aware of? Is there something special I can do in the security rules file that will allow onDisconnect to remove sessions post logout?
Here is the security rules block I have for the "table" in question:
"sessions":{
"$user":{
".write": "$user == auth.uid"
}
},
And in the JS it's just simple:
var con = ref.sessions[user].push(true);
con.onDisconnect().remove();
And as expected, since I'm not logged in onDisconnect I get:
FIREBASE WARNING: set at /sessions/simplelogin:16 failed: permission_denied
EDIT: What's with the downvote? =/

I'd suggest removing the presence bit before calling logout().
If you then want to track "presence" of a logged out user, you could either set a new presence bit as an un-authed user, or you could log in anonymously:
https://www.firebase.com/docs/security/simple-login-anonymous.html

Related

How can I be informed when logged out by server in Meteor

I often got message like the following when using my Meteor App:
09-15 22:42:52.400 3233 3233 I chromium: [INFO:CONSOLE(970)] "Error logging in with token: Error: You've been logged out by the server. Please log in again. [403]", source: http://localhost:12056/packages/meteor.js?hash=9725414143125e6990547986c27b473f43c89e8b (970)
I think it's because the token is expired for some reason (for example when I use Accounts.setPassword to change the user's password by force on server side, I will sure get this at next login attempt)
I don't want to know how to solve this question, I want to know, if there is an event or something else I can be informed when logged out by server, because I determine whether to go "main" page or "login" page by whether Meteor.userId() has value. when logged out by server, even Meteor.userId() has value, last login state is already invalid and re-login is needed.

How to verify users current password?

So, maybe I missed this somewhere in the docs but I couldn't find anything of the sort.
I wan't my users to have to type in their current password to be able to create a new one. From what I understand if the user is authenticated he is able to update his password without providing his current one.
Even if this might be somewhat secure I would rather have him type his old one to prevent people from going on already authenticated sessions from say family members or so and changing the pw.
Is there any way to do this?
(I have no problem using the Admin SDK since I already set up a server for these kind of things)
UPDATE: (Use - reauthenticateWithCredential)
var user = firebaseApp.auth().currentUser;
var credential = firebase.auth.EmailAuthProvider.credential(
firebase.auth().currentUser.email,
providedPassword
);
// Prompt the user to re-provide their sign-in credentials
user.reauthenticateWithCredential(credential).then(function() {
// User re-authenticated.
}).catch(function(error) {
// An error happened.
});
PREVIOUS VERSION
you can use reauthenticate API to do so. I am assuming you want to verify a current user's password before allowing the user to update it. So in web you do something like the following:
reauthenticateAndRetrieveDataWithCredential- DEPRECATED
firebase.auth().currentUser.reauthenticateAndRetrieveDataWithCredential(
firebase.auth.EmailAuthProvider.credential(
firebase.auth().currentUser.email,
providedPassword
)
);
If this succeeds, then you can call
firebase.auth().currentUser.updatePassword(newPassword);

Updating User's Info without allowing user write ability

How could you setup rules on Firebase which would allow a user to become a paid user of your app? For example, if I have the following data structure:
{
users: [
{
isPaid: false
},
{
isPaid: true
}
]
}
How could you setup firebase rules to not allow the user to update it themselves (by fudging a request), but still allow it to be updated automatically when they "pay" for your app?
I've thought about randomly generating a number and asking the user to enter that number or something like that, but I don't think that would work... Has anyone done something like this?
You'll need to have a server process that securely writes the paid flag using a Firebase secret (that can be found on Forge for your Firebase). Set the ".write" rule for /users/isPaid as false - the server code can bypass this rule since it knows the secret. You should call firebaseRef.auth(secret) from your server code first.

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 :)

Report-bulk-objects in Adobe Connect

I would like to get a list of meetings on the server however when i do a https://example.com/api/xml?action=report-bulk-objects&filter-type=meeting replacing the domain with my connect domain i get an access denied response. I am signed in to the connect work space and I am in the admin group. What could be the cause of this?
response:
<results>
<status code="no-access" subcode="denied"/>
</results>
This should work if you're in the admin group, logged in, and submitting the request from the same browser that's logged in. You might try adding the session parameter to your request ("&session=breez123abc456def")
The value of the parameter must be that of the BREEZESESSION cookie set by the Connect server on your authenticated session. One of several ways to discover that is with the common-info API method: https://connect.example.com/api/xml?action=common-info It'll be in the /results/common/cookie element.
If this still isn't working, check the debug.log on the server(s) for the failing request; there should be additional information there.

Resources