Schema Changes to Integrate Facebook and Google Login - sql-server

I have Users table to store user details with password and the authentication for the Application is working good with this.
But we want to integrate Facebook and Google Login in our system so please advise the related schema modifications.
CREATE TABLE dbo.Users(
UserId int IDENTITY(1, 1) PRIMARY KEY,
UserTypeId int, -- Admin = 1, End User = 2. (We have a master table for this, but eliminating here for simplicity)
UserName nvarchar(16) NOT NULL UNIQUE,
UserPassword nvarchar(16),
FirstName nvarchar(64),
LastName nvarchar(64),
DateOfBirth date,
Gender char(1),
PhoneNumber nvarchar(16),
Email nvarchar(128) UNIQUE,
IsActive bit,
UpdateTime datetime default CURRENT_TIMESTAMP )
Here is what I am thinking:
1) Once the user authenticated from Facebook or Google then the application will have claims (emailId)
2) The application should validate the emailId existence in Users Table and if exists it will allow login.
Q1> So will this require any update for the existing Row in Users Table?
Q2> If the user record does not exists (based on emailId claim record) then I think we should add the new record in users table?
Q3> In case of Add: What will be the Username and Password values?
Q4> Can the user (the added record) do a normal login without Facebook login?
Thanks.

In order to accept OpenID logins, you will have to accept and store the users' OpenID-URLs. This URL identifies the user just like an email address does.
Q1: Depends: If you want to allow both OpenID-logins and normal login for the same user, you will have to add another column to the table. If you don't allow mixed logins, you could use your Email column to store the OpenID URL.
Q2: Yes, if you see a new OpenID-URL, handle it just like an unknown email address
Q3: You will have to ask the user to pick a username - I assume you do the same for your current users. If you want to allow both logins for the same user, you will have to ask the user to set a password - otherwise they can only login through their OpenID provider.
Q4: Only if you did ask for a username and a password (see Q3)
Please note that allowing the same user to login through OpenID and using conventional username/password introduces potential security problem: A user might not unserstand that you're asking them to set a password and enter their Facebook (or Google) password. Or they might just not care and use the same password everywhere. If they do so and your database does not encrypt the password properly, your database will store the Facebook names and unencrypted passwords... even if just 10% used the same password on your site - just imagine what they could do with that.

Related

Require old password when setting a new password to a specific user in Oracle

Does Oracle 12 support having the old password required when changing a password to a specific user?
What I would like:
ALTER USER user_a IDENTIFIED BY secret123;
-- ERROR, missing old password
ALTER USER user_a IDENTIFIED BY secret456 REPLACE secret123;
-- OK
ALTER USER user_b IDENTIFIED BY secret789;
-- OK, since user_b does not require old password when changing it
Thanks!
Yes, this is supported since Oracle 9i, when a function was introduced that checks a new password for complexity and optionally for difference to the old password. As Oracle stores only hashes, not the passwords, it cannot compare old and new passwords unless the user supplies it during the change.
So, all users with a PROFILE where the PASSWORD_VERIFY_FUNCTION is set are required to have the old password, even if this function doesn't check any passwords:
CREATE OR REPLACE FUNCTION always_true (
username VARCHAR2,
password VARCHAR2,
old_password VARCHAR2) RETURN boolean IS
BEGIN
RETURN TRUE;
END always_true;
/
CREATE PROFILE always_true
LIMIT PASSWORD_VERIFY_FUNCTION always_true;
CREATE USER user_a IDENTIFIED BY secret123 PROFILE always_true;
GRANT CREATE SESSION to user_a;
Now user_a has to specify the old password:
ALTER USER user_a IDENTIFIED BY secret123;
ORA-28221: REPLACE not specified
ALTER USER user_a IDENTIFIED BY secret456 REPLACE secret123;
User altered.
A user with a profile without PASSWORD_VERIFY_FUNCTION or this parameter set to NULL doesn't have to specify the old password:
CREATE PROFILE without_function
LIMIT PASSWORD_VERIFY_FUNCTION NULL;
CREATE USER user_b IDENTIFIED BY secret123 PROFILE without_function;
GRANT CREATE SESSION to user_b;
Now user_b can change his/her password without having the old password:
ALTER USER user_b IDENTIFIED BY secret789;
User altered.
The second option is to have the privilege ALTER USER, but that is only for administrators, as they can change all the passwords of all account.
Oracle docu says
You can omit the REPLACE clause if you are setting your own password for the first time or you have the ALTER USER system privilege and you are changing another user's password. However, unless you have the ALTER USER system privilege, you must always specify the REPLACE clause if a password complexity verification function has been enabled ...
so the answer would be - add a password verification function to those users that should provide the old password (and revoke the password change system privilege from them).

SQL Server: Users & Logins — Where does the user name come in?

I am trying to get a better understanding of the distinction between users & logins. I know how to create them, and I understand that they are required, but I don’t yet understand how SQL Server uses this distinction.
As far as I understand, a login has access to the Server, while a user has access to a database and its objects.
If I execute the following:
CREATE LOGIN fred WITH PASSWORD='…';
USE stuff;
CREATE USER wilma FOR LOGIN fred;
USE nonsense;
CREATE USER pebbles FOR LOGIN fred;
Then I have a Login of fred with two user names associated with two databases. My guess is that these user names can be regarded as aliases for fred.
I undersand that it is common to use the same username as the login name, but clearly not necessary.
The next step is to login as fred. I cannot login as one of the users.
At this point, I don’t see what happens next. How do I become one of the users, and what would do for me?
You never authenticate as a user.You authenticate as a login, which then maps to a single user in zero or more databases.
Create the login
CREATE LOGIN fred WITH PASSWORD='fredsecret', CHECK_POLICY = OFF;
GO
Create the users
USE stuff;
CREATE USER wilma FOR LOGIN fred;
GO
USE nonsense;
CREATE USER pebbles FOR LOGIN fred;
GO
Change context so it looks like I'm fred
SELECT SUSER_SNAME() --gbn
EXECUTE AS LOGIN = 'fred'
SELECT SUSER_SNAME() --fred
Note the differences
USE stuff
SELECT SUSER_SNAME(), USER_NAME()
USE nonsense;
SELECT SUSER_SNAME(), USER_NAME()
GO
and go back to me
REVERT
The name of the login (fred in this case) is only used for authentication to SQL Server. After authentication you mostly use the sid value: which links login (server principal) and user (database principal)
SELECT name, sid FROM sys.server_principals
USE stuff
SELECT name, sid FROM sys.database_principals
USE nonsense
SELECT name, sid FROM sys.database_principals
In my case, it is 0xC7C14DE4BFDF2445A7DABE158CC399F0
Note, sid is unique in a database. This will fail
USE nonsense;
CREATE USER barney FOR LOGIN fred;
GO
Msg 15063, Level 16, State 1, Line 10
The login already has an account under a different user name.
You connect to the server under the login, on base stuff will be CURRENT_USER wilma and on nonsense CURRENT_USER = pebbles

Different Permissions in Apache Shiro for every User?

I built a database with the entity user and permission
user (id, email, password, permission)
permission (id, create_user, delete_user, user_fk)
create_user and delete_user is BOOLEAN.
Relationship: One-One
Now every user can have it's own permissions.
My question is: How can I use shiro to read the permissions from the database?
If you really only wish to assign permissions on user level, you can "fake" the roles table to make Shiro happy.
As Wouter mentioned, use the JdbcRealm and specify the 3 queries for your table setup.
You should modify your permission table to have this structure:
permission (id, permissionname, user_fk)
Then you insert rows for the create_user/delete_user rights as needed.
This way it's very simple to add another permission (reset_password for example) to your setup, without the need to modify the db schema.
In the shiro.ini (or how you call the your shiro config file):
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
For the queries use then this:
jdbcRealm.authenticationQuery = select password from user where email=?
jdbcRealm.userRolesQuery = select id from user where email=?
jdbcRealm.authenticationQuery = select permissionname from permission where user_fk=?
The small trick in your setup is: you don't have roles at all, so we just return the id of the user as the role name.
When the lookup in the permission table is done, it then uses the role name (=user pk) and returns the associated permissions.
You should configure a JdbcReam in your .ini file:
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
If you change your schema to adhere to the shiro queries, no extra config is needed. You need tables users, user_roles and roles_permissions.
See the source code how the exact column names should be:
https://svn.apache.org/repos/asf/shiro/trunk/core/src/main/java/org/apache/shiro/realm/jdbc/JdbcRealm.java
Alternatively you can configure your own queries to match your schema in the .ini file like so:
jdbcRealm.authenticationQuery=<your password select statement>
jdbcRealm.userRolesQuery=<your role names for username select statement>
jdbcRealm.authenticationQuery=<your permissions for role name select statement>

can I base my asp membership provider 'applications' by a guid

I created an asp portal for my customers. They all access the same website and pass in a tokenid, which is a guid. This guid tells me what company they belong to and what they have access to.
I have the membership provider set up to not allow duplicate email addresses and everyone under the same application. So, with this in mind, I figured I could do the following to allow them to register with more than one company with the same email account.
Create an membership provider application for each tokens (for each company).
Write a script that finds all of the accounts that are based on this guid and place them under appropriate application
Will this work? Will it allow my customers to create a login for each token/company using the same email address?
Thanks for the help!
If you script out
[dbo].[aspnet_Membership_FindUsersByEmail]
, you'll see (the default implementation) is already "separated by application". (because this procedure takes "ApplicationName" as a parameter.
So if you programmatically set the
MembershipProvider.ApplicationName
http://msdn.microsoft.com/en-us/library/system.web.security.membershipprovider.applicationname.aspx
Then you should be able to do what you want.
Here is the signature of the procedure mentioned above:
ALTER PROCEDURE [dbo].[aspnet_Membership_FindUsersByEmail]
#ApplicationName nvarchar(256),
#EmailToMatch nvarchar(256),
#PageIndex int,
#PageSize int
AS
REMINDER:
You do not deal with the stored procedures directly. You use the API of the MembershipProvider.
But here is the simple test.
MembershipProvider mp1 = Membership.Providers["App1"];
mp1.CreateUser (.................. )
MembershipProvider mp2 = Membership.Providers["App2"];
mp2.CreateUser (.................. ) /* use same email */
Now, I think you'll have to define each MembershipProvider (and its name) in your config file.
But here is an MSDN link:
http://msdn.microsoft.com/en-us/library/system.web.security.membershipprovidercollection.item.aspx

Find if correct password with hash and random salt

I have a database with users and I want to have a random salt for each user that is saved in the column Salt and a hash of their salt+password in the field password.
I can insert them like this:
INSERT INTO users([Username], [Password], [Salt])
VALUES('David', HASHBYTES('SHA1', 'randomgeneratedsalt' + 'theirpw'), 'randomgeneratedsalt')
But how do I select them?
My own try is:
select *
from users
where Username = 'David'
AND Password = HASHBYTES('SHA1', Salt + 'enteredpw')
Of course I can select the salt for the user that is trying to login, but I'd like to do it without doing so.
You select them by username, which must be unique. After you locate the user you can compare the presented password hash against the stored one. Only need be careful to display the same error whether username was not found or hash don't match (ie. prevent information disclosure that the username is valid).

Resources