storing data on an "anonymous" user - php

I'm currently working on developing a Symfony2 app that will not only accept
user registrations, but will allow visitors to go through almost the
entire flow of the site without creating an account or logging in. Design ideas look something like this (suggestions/improvements welcome):
When a user logs in to their account, data will be persisted to the user/related entities as normal
When an anonymous user hits the site for the first time, an "anonymous user entity" is created for them as if they'd registered, but with something like USER_<session_id> as an identifier instead of a personalized username. Any activity they perform on the site is persisted to this anonymous user entity
When an anonymous user chooses to register, their anonymous user entity is upgraded to a registered user entity, preserving their data for future use
If an anonymous user leaves the site without registering, the anonymous user entity should be cleared after a while to prevent buildup of dead data
What's the best way to go about this? Specifically, what is considered "best practice" for creating/manipulating a User entity for an anonymous user without having to place code into every controller?

I would advise against using the IP address for this, as it could cause problems for users behind a NAT.
Using a custom cookie, or the sessionId (PHPSESSID) cookie as an identifier for tracking purposes would be a better idea. Google uses this strategy for its ads business. Stand on the shoulders of giants!

I have something similar to this that I've had to do. What I did was collected the anonymous users ip address (using ($_SERVER['REMOTE_ADDR'])). I then used the ip address for tracking purposes. You can then use that when they register to append their past usage to their newly created account.
You can then just run a simple query to drop any ip address that hasn't had activity in a while (most users have dymanic ip addresses so it will change every so often anyways).

Related

Best practice to create a database schema for Open Auth (Social logins)

I've done a database schema for user management alongs with their roles and permissions. The problem actually began, when I decide to integrate a multiple "Open Auths" such as Facebook Login, Google Login, etc...
My database table DB.USERS looks like this at the moment:
id
oauth_id
username
email
password
remember_token
...firstname,lastname,etc...
At the moment, problem is, whenever user tries to login via one of the OAuth (Google, Facebook) and there is an email already taken (either by one of the oauths or application's auth library), it triggers an error and cannot proceed.
I wonder what's the best approach to create a database schema for such method ? Anyone who already have an experience with it ?
I'm using a Laravel 4.2
It is an entirely normal situation that the same email address is reported by different social login sources. First of all you need to answer a question - what do you want to do in such cases?
If you trust the social login to report a valid email address, you could simply merge new login source into an existing account.
You could also choose to create separate accounts for each separate login source - in such case you should treat email similarly as a name - without requiring it to be unique. This is problematic if you want to allow email+password logins on your own.
Another questions to consider:
What happens if email address reported by social login changes for an existing account? What if new email matches another existing account?
Do you allow users to change email proactively?
Design the process first and then use a suitable DB schema.

Database vs application security design

So I'm currently in the process of creating a small public website (where users can, for example, log in and change personal information), but I am wondering how the database security is actually designed for that type of thing, so I have several questions.
When an internet user accesses a page like stackoverflow, for example (without logging in on the site), which database user or role is he logged on in order to be able to see all the posted questions? Then, when the user logs in with his account, does his role in the database change (since he has more rights)?
If I setup my database to have a "Users" as well as a "Permissions" table, I can make sure that a user can only have access to his own data, at least application side. But how do I make sure the data is still protected database side since I suppose every public user has the same "database login" or "role"?
I know my question is probably a bit unclear, but don't hesitate to ask me for clarifications. I didn't really know where to begin.
Thanks.
P.S.: I'm currently using SQL Server
Database role doesn't change, but functions do. Users are authorized from the back end code, not from directly database. If you are trying to create logins for every single user for your database, that would not be a good aproach since there could be thousands or milions of users which somehow can have direct access to your database with some permissions.
You've almost answered your own question.
Generally, your website will run under some user account, lets call this 'IWEB', this user account will be the same for everyone that hits your website, regardless of whether the user is logged into your website or not.
IWEB will have permissions to read data from a database. That's how the anonymous users work.
In your database you will have a user table, possibly a permissions table. IWEB will be given database permissions to create new users, update users. It possibly will be prevented from deleting users.
Your application will (though IWEB) use these tables to control who has access to your application and who can update what. A bug (e.g. SQL Injection) in your application could allow a malicious user to create admin accounts, change other users passwords etc...
In certain scenarios e.g. using Windows Authentication, you can pass through the user logged into your site, translate that into a database user and given them permissions. However you are unlikely to do that for a public facing website.
You could possibly do something where the tables are not directly accessed, but are controlled through stored procedures, denying access to the underlying tables. One of the parameters is the currently logged in user, that could then control access at the database layer (prevent a user updating another users profile). Unless of course your application has a bug that could allow an attacker to change their currently logged in user.
It all depends on your security requirements. In the main though, you will control access at your application.
What's wrong with having an Anonymous user in the Users table, having the lowest privileges in the Permissions table?
To your first question: When a user first lands on a web page they have no 'role'. Your scripting will decide what the users can and cannot see.
For example you have a post that only certain user can see. That post will be hidden by default. Your script should then run a test to see if the user is currently logged in and if that user is in the permission group to view that post. If they are, then show the post.
Your database should not be accessible either way.

Reusing OAuth Access Tokens

On my site, I intend to offer users the ability to authenticate via OAuth. I don’t want to ask them to first register with me and then connect an external account; I want to offer single sign on.
I believe we’re supposed to reuse Access Tokens; certainly within sessions and even between them.
Google goes so far as to say they’ll limit the number of access tokens to 10 per user per application. (Apparently Google still supports OAuth1, but recommends Auth2 now) 10 is a pretty small number.
Using cookies (like this) seems like a good plan for identifying a user between sessions, but I’m having trouble with the scenario where a user has deleted cookies or connects from a new machine.
How do I know who the user is before I’ve requested another Access Token for them? Request tokens do not contain the userid, right?
Thanks
You will have to maintain your own user accounts anyway, no matter which protocol and which provider you choose. A token (or a URL in the case of OpenID) that you get from a provider is unique for a given user and you are supposed to associate it with your internal user account and recognize user by it.
If you don't want to provide any registration UI it's okay: just get the token, retrieve all the user info you need from the provider and store all this somewhere in your database. You will also have to issue and recognize your own cookie for your users, or else they'll be forced to go through provider auth every time they visit your site.

Automatically login to current website if user is logged in to another website

I have about 100 websites coded in ASP classic. Each website accepts orders and stores them in database. However, the payment of these orders must be made on another website, also coded in ASP classic. All websites are owned by same company, hosted on same IIS server and use the same SQL Server database.
Now, the user registers by entering some personal information and logs in to one of these website (e.g. website-for-newjersey.com) and places an order. He is then redirected to the payments website (payments.master-website.com on https) where some of his personal information (address, city, state for shipping; name for credit card holders name; etc) appears on the payment form. Credit card specific information is entered on that page.
Because of the sensitivity of information shown on that page, the user must login to the payment website before he/she can view the pre-filled payment form. And I do not want the user to login twice (once on each website). Is there a reliable way of checking if the user is logged in to the referring website using classic ASP.
Long story short
On website B I need to check if the visitor is logged into website A
On website B I need the ID session variable from website A
Both websites use same database server
I need clear instructions
PHP or ASP.NET solution is acceptable if it is generic/portable
From the calling site you could create a guid or some other randomly generated value. Store it on the users record (set to expire in a specified time period) in the database, encrypt it and pass it over SSL to the payment site where it is decrypted and then compared to the database. If they match then the user is logged in, if it doesn't match then they are asked to log in.
Another way although I'm not sure it can be done with different domain names is using sessions. Since they are all on the same machine it might be possible but I'm not 100% sure on that one.
What you asked is called single sign on (SSO) and can be implemented in few ways. There are many topics on this matter, example: What's your favorite cross domain cookie sharing approach? but they all vary due to individual requirements.
In your case you have different domains (so you cannot share cookies across them), you mix http and https (which might be a problem) and you have many applications so you won't make many changes.
So I would recommend to consider Robert's suggestion:
When user is authenticated for the first time (website A) you save a GUID in the database. Add a new table for sessions with columns for GUID, userid, ip and timestamp or save it as a part of orders data. Store GUID in the session object.
On the page that had a link to the payment site set it in the query string or as a hidden variable (if it's a form).
On the other domain (website B) check for the GUID and then look it up in the database. If it wasn't too old then authenticate the user, otherwise redirect him to a login page.
If you cannot change a link to the payment site then you could try to skip the step 2 and validate the user by his ip but this might be too risky.
Pass-port based authentication is a centralized authentication service provided by Microsoft that offers a single logon and core profile services for member sites. For more information, see the following Microsoft Web site:
Passport Authentication Provider
If you can't implement a Single Sign-On at your infrastructure level, you should use Identity Federation which allows applications of different trusted party to share authentication through claims.
This can be done using Security Assertion Markup Language (SAML) directly or with products/standards like :
SimpleSAMLphp
Active Directory Federation Services
Also you can take a look at OAuth or OpenID which are more shared authentication schemes than SSO or identity federation.

Integrating openID and oauth as website login, signin and authentication system

First of all let me start by saying that this question is not about different openID and oAuth implementations. There are many classes about these.
My question is what to do after authenticating a user:
How to add this user to the user table in the database?
How to handle different logins for the same user? (Remy Sharp's example suggests
something for openID)
How to combine oAuth and openID in the database?
Any ideas?
Your question has to main parts to it:
Authentication
Authorization
Usually the two are not treated differently if the identity provider (IP) is your own, which has been the most common setup in web apps until now.
When using an OpenId Provider such as Google, the authentication part is seperated from your control. You will get a token back telling you if the user is authenticated or not. The token will normally contain the following claims: Name, Email and Named Identity where the last is the unique id of the identity at the IP.
So far so good.
The trick is now as you ask, how do I authorize this user?
well, there are a couple of approaches to this.
First off, when you create a local user in your system, you can prepopulate the Name and Email values based off the claims you get from the IP. In this process, you can start and say that all users that have a profile stored in your system are authorized, or you can develop further processes that will add whatever details you need to know about the user.
Then, how do you avoid that the user is not re-registered if they switch from google to facebook as the IP?
This is where things get tricky. The most common claim that Google, Yahoo, Facebook will provide to you is the email address and Name. So what you can do, is try to match the incomming claim with existing customers in your app. This is not failsafe however, as people can have different emails in different systems.
The name value is also not safe.
In our setup, we start by matching emails, as we know that most IPs validate email addresses. This will reduce duplicates a lot. After that check, we start our own validation process where the goal is to see if the person is already registered. This process looks for the customers mobile number in our database, and if a match is found, we send a one-time-password to the customer to verify correct ownership of the phone number.
Since login is a time sensitive setup, we are created a simple SQL table that maps external identities to our customer numbers. This allows us to implement this kind of validation logic outside all our web apps (and thereby reduce code redundancy)
The most simple way would seem for me, to have a basic user table, where you add the user at register and have a extra 1:n table where you save possible authentications. Maybe you need more than one table, if there are methods, which need way more columns than others.
I implemented login via OpenID from google and met similar problems. I used openid library from janrain.
I don't created separate table for openid. I used secondary emails instead (secondary emails are stored in table of users).
While logining through google it's possible to demand user emails (I believe there's the same oportunity in any other openid provider). After I get response from google that user is logined, I look in table of users. If provided email was found in table (it doesn't matter whether it's primary or secondary) I login the user. If the email is not found, I ask user whether he has an account. If yes, he is proposed to login with existing login/password, after that I add secondary email to user. If the user doesn't have an account a new account is created.
So you don't need special new tables for these tricks.

Categories