Some weeks ago I discovered OpenID Connect and IdentityServer V3. I ran some of the supplied examples and I am today at the point where I need to go further but I don't know how to proceed:
Actually we have an "home made" authentication and authorization process and we'd like to move to an OpenID Connect solution. Identity Server seems to be the perfect candidate to do this.
Today our users are stored into an SQL Server Database and ideally I'd like to "connect" this table to Identity Server (without touching to the schema of this table). I read about "MembershipReboot" but it uses its own Database. I also heard about making a custom user service but in the sample (CustomUserService) I did not find anything helpfull. Today I'am a little bit lost because I don't know where to go and I realize that I'am not very far from the target.
I need help
Thank you
In the Custom User Service Sample you mentioned, it includes three variations of user service to show different approaches, but you really only need one of them.
In the LocalRegistrationUserService sample you'll find lines like these:
public override Task AuthenticateLocalAsync(LocalAuthenticationContext context)
{
var user = Users.SingleOrDefault(x => x.Username == context.UserName && x.Password == context.Password);
/// snip ...
and these:
public override Task GetProfileDataAsync(ProfileDataRequestContext context)
{
// issue the claims for the user
var user = Users.SingleOrDefault(x => x.Subject == context.Subject.GetSubjectId());
/// snip...
You need to replace those calls which look up values from the in-memory Users collection with something that opens a connection to SQL server and looks them up there instead.
See the Custom User Service documentation for more methods supported, but those two (AuthenticateLocalAsync, GetProfileDataAsync) plus your SQL lookup are all you need to get started.
Related
I was trying to access user information like first name, last name of the user in my ASP.NET Core MVC project with Windows authentication. I actually make it work after searching for a solution on the web but I am quite new to this stuff and beginner level programmer so not understanding what is happening in the part that I just copy paste in my project.
I couldn't find any explanation in that website as well. I would be really happy if someone can explain this to me. Many thanks in advance.
The website reference for this code: https://sensibledev.com/how-to-get-user-details-from-active-directory/
Home controller:
var username = User.Identity.Name;
using (var context = new PrincipalContext(ContextType.Domain, "yourdomain"))
{
var user = UserPrincipal.FindByIdentity(context, username);
if (user != null)
{
ViewData["UserName"] = user.Name;
ViewData["EmailAddress"] = user.EmailAddress;
ViewData["FullName"] = user.DisplayName;
ViewData["GivenName"] = user.GivenName;
}
}
That code takes the username of the user who logged into your website and looks it up on your domain to find more information about the person.
var username = User.Identity.Name;
The User property is ControllerBase.User, which refers to the user currently logged into your website. Since you're using Windows Authentication, this will refer to an Active Directory user. User.Identity.Name gets just the username.
The rest is for looking up the account in Active Directory.
new PrincipalContext(ContextType.Domain, "yourdomain")
This means "I want to talk to a domain called yourdomain".
UserPrincipal.FindByIdentity(context, username)
UserPrincipal.FindByIdentity finds an account on the domain. So this is saying "find this username on the domain".
Then the users details from the account are put into the ViewData collection so that the data is accessible in the view. More details on that here.
From your website's perspective, all Windows code runs under some Windows account.
If you use IIS and Forms authentication for example, then Windows knows nothing about you - you are likely to be running under an anonymous account name which all users will run under. If you drill down through your running code, it is possible to find different Windows accounts at different code levels, such as in your top level code, the underlying IIS thread, etc.
You are trying to use Windows accounts for your web site but you have to ensure that the web server it is running on is also using Windows Authentication - I know you checked this option when creating your site.
Your user identity can be cast to various types because it has to work seamlessly whichever authentication methodology is in use. You can also check your user to see if it is of a particular security regime.
Have a look at https://learn.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.1&tabs=visual-studio
You get the security principle information using
var context = new PrincipalContext(ContextType.Domain, "yourdomain")
PrincipleContext is the class that has the information once you create a new instance of it, passing in parameters for the type of domain (an enumeration) and the name of your domain (a string).
The USING block ensures that the instance is disposed once the block completes - otherwise you have to call DISPOSE on that instance yourself (remember if there is an exception you might not have captured this so you will at least have to manage this scenario.
Once you have an instance of of your domain context you can use it to search (in the case of Windows, the LDAP database) for users, whether by SID or unique name, in your case (every name must be unique - two users in the domain cannot have the same name).
The website has the security ID of the user, the code you are following gets a Domain object for that user which has the properties you will display. You could call other objects that might tell you which Windows Security Groups the user is a member off. In that way you can have a web site where a users ability to view a web page or click a button is down to which Groups in the Domain the user is a member of.
we are looking for brand new implementation for Identityserver4,
I wnet thru the documentation and install the Project on VS2017 and DB in sqlserver.
Database is created with the default migration script provided for bot ConfigurationData as well as Operational DAta.
I am very much confused , where the user will be how the clients will be add etc?
Also in the startup the default ASPNEtIdentity is add, but in database there is no ApplicationUser table, so where the userdata will be?
My requirement is simple - User will be aple to login to application by his credentials(or may be by 3rd party application) and will use the application or
API will directly use Identity server to with clientcredential scope,
Here please do let me know:
Should I introduce AspNetIdentity or Not, and Why?
Where is the user table and Password of the user in the database generated by the migration.
How we can add User clients and resources to the Created Database
Do I need to add Login/Logout page ?
In API APIResource is used to defined the Resources "api1" and same is used by the client code to get the access but this "api1" is not used anywhere with the definition/signature of the Method, so ow will it be correlated?
First off, IdentityServer4 on it's own does not handle users or authentication thereof - you either need to use ASP.Net Identity and the integration library that hooks it up to IdentityServer4 or build all of that stuff yourself.
So to sum up:
Yes you'll need to use that or roll your own user store and authentication logic
Either provided by ASP.Net Identity or built yourself
https://www.identityserver.com/documentation/admin-ui/ may fit your needs or you could build your own tooling and/or scripts to do so
Yes although the quickstart samples provide good basic starting points
The bearer token middleware by default will validate the audience (ApiResource.Name) but I prefer to enforce scope at a more granular controller or action level using a filter (e.g. [ScopeAuthorize("my.api")] public MyResult ApiAction() { ... }). This filter will check that the specified scope is defined in the set of claims in the ClaimsPrincipal).
I can print
System.Security.Principal.WindowsIdentity.GetCurrent().Name is #System.Security.Principal.WindowsIdentity.GetCurrent().Name
in a razor (.cshtml) file, however, I do not know how to print the app pool or verify that it is indeed accessing the database to login to it (as the login currently fails, that portion is an even tougher question).
This may require creating a string in the controller action trying to access the database, e.g. near something like:
db.myTable // etc
Thanks in advance.
The name you are returning in the code sample is the windows user id that the app pool is using (look in the app pool properties to see what windows username it is using).
This user name, complete with domain name, needs to have access to the db.
You may like to create your own windows user just for the app pool to use something other than local service as it may not be a good idea to give any local service access to your database.
As Will says in his comment, sql profiler should be able to help you find out what's happening if you are not sure.
i'm total newbie about security with MVC4. I develop an MVC APP using WebMatrix. Its pretty cool but i didnt like the tables and columns schema.
I'm using REVERSE ENGINE CODE FIRST and i want to know what is the right thing to do. I'm reading a lot about membership providers and webmatrix.
There is a way wich i can use WebSecurity class with my own database? My login method isnt the simple login pattern (string user|username|email, string password). This application requires a long as login user like long userKEY, string password.
I'm totally confused about the terms and any kind of hint can help a lot.
Thanks
The WebSecurity class is a wrapper around the SimpleMembershipProvider which is designed to work with SQL Server and SQL Compact 4.0. The schema that it works with is hard-coded into the SimpleMembershipProvider so you cannot use the WebSecurity class for your own schema.
However, you can build your own provider based off ExtendedMembershipProvider and have it communicate with any backing store you like. Probably the easiest/quickest thing to do is go to the source code for SimpleMembershipProvider and copy that, altering the SQL in the various methods as required.
I am using Entity Framework and have the same model on many databases and servers. I want to set my connection string at runtime based on the logged in user. I am currently overriding CreateObjectContext() in my DomainService and setting the connection string there. This works great, but I'm concerned with the lack of security. For example, in my DomainService, I have an invoke method called SetConnectionString() where I pass in the connections string each time I need a new Entity. This is being done from the DomainContext (client side). Since I am using SQL Integrated Security, I am concerned that someone could manipulate the connection string on the clinet and get access to a database that they are not authorized to use.
What is the most secure way to dynamically set the connection string for the domain entity I want to use at runtime?
I do have the database name and server settings in a database that I could look up from the DomainService if I passed in my project id or some other piece of information, but I am then right back to the same issue - someone could easily spoof this info.
Ideas??
-Scott
Hopefully my answer is relevant as the same security issues are faced by flash developers...
The only way to make this really secure ("this" being database connections from your client side code) is to make each user only have read-only access to their data in the database.
As you are realizing, there is no way to stop the user from monitoring/modifying data that you are sending back to the server. Even if you encrypt the communication, the user still has access to the code and in the case of flash, source code due to trivial decompilation.
I am not a DB developer, but I do security audits of stuff like you are asking often, so the following advice could be wrong, but I just googled, and it seems like maybe you could use views to restrict users (sets of credentials) to specific information.
If not, this article seems relevant to what you want:
http://technet.microsoft.com/en-us/library/cc966395.aspx
What about using the ASP.NET membership framework? Tie the user login with a Login call in the framework to make sure the user an authorized user. Add a "RequiresAuthentication" attribute to each of the functions you want to protect in your domain service.
Here are more details on using ASP.NET membership with Silverlight: WCF RIA Services - Authentication, Roles, and Profiles