I'm wondering how to solve the following issue:
I have a web asp.net app where Forms Authentification is used, connected to the Active Directory. Also, I have a connection string to MS SQL db in the web app, where one global user (with given privileges) is used. The problem is that when I want to store information about the user (e.g. data modification log) in database, I can only get the global user info provided in the connection string, not the real user who is logged in.
Is there any possiblity to log onto a web app with my personal credentials, after, use a global user credentials to connect into the database and pass my personal user credentials (but not as parameters in store procedure) that database will think that the user who is logged in is not the global user?
I assume, it might be only possible if I also create same users in the database and use Impersonalization?
Or any other possibillities?
Thanks in advance.
What are you doing to get the current user? Are you doing something like SELECT #user = SYSTEM_USER? This will obviously only return the user that you connect to SQL Server with.
I would rather keep to using a single SQL login that the application uses, but pass in the username when you are making changes, e.g. through a sproc or a table update:
CREATE PROCEDURE dbo.DoSomething
#id INT,
#username VARCHAR(50)
AS
-- Make your changes.
INSERT INTO dbo.[Audit] SELECT 'update', #id, #username
GO
In ASP.NET you can grab the currently logged in user through User.Identity.Name property of the page.
You could use a role within your database to handle permissions, and then get the users you need in a group in AD, and assign permissions to that AD group to access your database under the role you define. (This way you don't need to assign each user to your database as you create them).
You would then use windows authentication right the way through from your web site to the database, and have the user identity that you need for logging. (You'll need to set identity impersonate="true" in your configuration).
I would note that this is only going to work (easily) if your servers and your users are all on the same network.
Related
That's my question. I am using Hasura, and defining 'user' permissions.
Users are of course allowed to modify their own information, and not allowed to insert new records into my users table.
But when they signup, they should be allowed to insert themselves. So how can I define this permission?
To make my scenario more clear:
I have a React app, that uses an external OpenID provider. So a new user signs up there, and the provider returns a JWT to my app, containing a user I've never seen before.
My app does not know that, it just uses the access token to send to the Hasura backend to retrieve further info about this user, using the 'user' role. But it uses a query which will automatically insert the user if not found.
There's really not a safe way to allow sign-ups without involving a backend service. It is a very bad idea to allow anonymous inserts into your user table, even if you added a unique constraint against a user ID or email address.
If you have the option of using NextJS, see the Hasura example for configuring NextAuth. This works by configuring your app with a protected API route that uses your Hasura app's ADMIN_SECRET to insert new users who have authenticated with a third-party.
If NextJS isn't an option, Hasura's Auth0 example similarly uses a callback method to insert an authenticated user if they don't exist.
In the user table, for the user role, you need to add a permission with custom check. And the check should be user_id equals x-hasura-user-id.
{"id":{"_eq":"x-hasura-user-id"}}
For non-logged-in users, leverage the anonymous role by setting the permissions that make sense for your use case: https://hasura.io/docs/1.0/graphql/manual/auth/authorization/common-roles-auth-examples.html#anonymous-not-logged-in-users
Edit after the comment:
Ah, I see. When the user comes to your app, your app goes and retrieves some data that it expects every user should have (for example perhaps the user info store on the user table). But since it's a new user, this info is not there.
At this point, your React app knows that:
there's someone with a legitimately signed JWT cookie (use a library to verify the signature) and
there's no user info from the backend. Therefore, the React app shows
a "Welcome new user, wait while we're setting up your account".
Then
the React app makes a mutation to a signup Hasura action you'll
prepare. Once that returns, you proceed as usually (redirect the user to their home page).
use hasura action handler instead. Inside your handler, do a check if the user already exists or not. If not then insert a new row.
Here is my problem if i can call it that way.I have implemented authentification with custom memebership provider in asp.net mvc 2.0.Everything works well but i have one problem.When user log in he provides its username and password and i check this through databse in MSSQL then i validate user and pass and use FormsAuthentication to set only UserName as profile information.
But when that user wants to create new item(lets say for sale or something) that belongs only to him and can be listed with other items that user created i can use this username(in FormsAuthentication) check it in database and connect that item to appropriate user with foreign key but that works if username is unique so i need additional informations like ID column from database table "user" to store and use it later so what is the most secure and "best practice" way to store additional information of user and use it later because username as i mentioned must be unique in database and it is not enough information about logged user.
Couldn't you store the User object (or whatever additional info you have) in the Session? or using a cookie at the client side (if you need to persist the login state even after the user closes his browser etc)? Let me know if you need specific examples.
EDIT: After reading your comments, if you are looking for a "secure cookie" solution have a look at this: http://www.codeproject.com/Articles/13665/HttpSecureCookie-A-Way-to-Encrypt-Cookies-with-ASP
I use it to store the user's id (only his id). When I retrieve this cookie I load the user given his id. Some in-memory caching allows me to avoid loading the user on each request.
But just wanted to clarify that the session object seems great for what you are trying to do + you dont have to worry about security (for the average app that is).
I havent worked on ActiveDirectory Membership provider earlier, I have a doubt on creating an application using AD membership provider. If I need to foreign reference a user in a different table(lets say a custom role table ) then what primary identifier(Foreign key) should I use to identify the user in the the table which holds the relation of Role and the users.
Also , where is the additional information(other than AD details) about the user is stored like User Name, Department, Current project etc.
Is a snapshot of Active directory taken frequently and stored in a table in the database which is then used in sql joins?
The base membership provider (and derived providers such as the ActiveDirectoryMembershipProvider) uses UserName as a functional key (queries for members expect UserName as the key query parameter and return a single MembershipUser object). Those queries return MemberShipUser objects that have basic membership information—including roles, email, comments, etc. If you want to combine the ADMembership Provider with extra information, you're best off using the UserName as the key to do so. Storing extra data is easier if you use a database because .UpdateUser only commits Email, Comment, and IsApproved properties.
And no, snapshots are not taken, though you can enable caching if you wish. The provider queries AD directly when it needs the information.
The aspnet membership database when created resides in App_Data folder and is quite handy as it supports all the Login controls very well. The user roles can be very well managed by the aspnet configuration manager. The profile properties are managed all by the the database itself.
The database thus created can be seen in the server connections. If you analyze the datatbase you will see that every user has a specific userId apart from the username. Both of them are unique. You need not copy all user data in other tables. You can specify the related data using joins. Once a user is logged in, you can refer him/her by User.Identity.Name (c#) in your code behind.
Kindly view the database tables using the Server Explorer in Visual Studio and you can view the tables structures -- aspnet_Users, aspnet_Membership, aspnet_Profile etc...
I'm making a small portal in ASP.net (with C#.net4) where users can login and add, edit their personal information (PI). But I don't get how to load information (stored in a SQL server DB) in the page when a specific user is logged in.
For example: If Sam is logged in, he can view his PI. When Vicky is logged in, she can view her PI.
who can help me with this?
thanks in advance.
You need to retain the ID of the logged in user in a session variable and then use it to filter the query with which you fetch each user's info.
So if a user's ID is 278 then your query would run as:
SELECT first_name, last_name, * FROM user_table WHERE user_id = 278
From a session variable stored like:
Session["UserId"] = currentUserId;
The ASP.NET membership provider has already taken care of this for you. Have you considered using it? You can manage all of your authentication, permissions, roles, and access/edit profile information -- which you define. You access the data via the membership objects, and you won't need to write a single line of SQL to do it. It will save you loads of work instead of trying to reinvent the wheel.
Use the regular membership as described in the other answers. Then leverage the Profile system so that each user can view/edit their info when logged in (per the question). CAVEAT: ASP.NET profile system only works out of the box with the Website project template. If you want to use the Web Application project template, then follow the steps here:
ASP.NET: Web Site versus Web Application Project
When you have the profiles up and running, the profile data can be stored in session objects while the user is logged in.
I have a web page that runs under an account named, WebUser (IIS runs under this account)
Now the problem here is that, when the webpage is accessed by users (intranet),
users are authenticated through Windows Authentication.
The webpage calls a stored procedure, SaveClientInfo.
When I was trying to get the user's name (say, User1) who was calling SaveClientInfo,
I was getting WebUser instead of User1 through SYSTEM_USER
Is there a way to get User1 from SaveClientInfo without having to pass in the user name to the stored procedure?
Here is the relevant piece of sproc definition
create procedure SaveClientInfo
#ClientID int
... --; other parameters
as
begin
declare #UserName sysname
--; returns the name of user name that IIS runs under
--; But I would like to log the name of the person
--; who is accesing the site through Windows Authentication
select #UserName = SYSTEM_USER
--; Save client data and the person who saved the info
...
end
GO
Unless you use impersonation in your web app, so the web application connects as the Windows authenticated user, no you can't.
Retrieving the name of the user from the SQL should just give you the username associated with the connection - typically, the user account used by ASP.NET.
On the .NET side, You can use (C#)
string s = Environment.User.Identity.Name
to retrieve the name of the user logged into your site. We use this to track who's making changes to the db through our admin site, among other thngs.