IdentityServer3 Custom UserService with custom repository - dependency-injection

Based on the EntityFramework and CustomUserService samples, I'm trying to authenticate users against a separate user database.
In the factory, I'm registering the service like this:
factory.UserService = new Registration<IUserService>(resolver => new CustomUserService());
However, if I want to use multiple user databases, how can I inject the repository or the connection string that I want to use?
The goal is have different clients getting authorization to use resources (like API) from the same authorization server, but point to different user repository. So, identity server would use a database where clients, scopes, redirect URIs, etxc, would be set. But to authenticate a user, I would like to use different database, depending on the client.
Is there any way of doing this?
Thanks

We had a very similar problem and solved it by using the tenant on the acr_values i.e. on the call to /connect/token, we passed in the following in addition to username, password etc:
acr_values=tenant:YourTenantString
YourTenantString will identify the database environment and from there, inside your user service you can extract it via:
var dbid = context.SignInMessage.Tenant;
from dbid we are able to get the connection string from config

Related

QBWebConnector for multi-tenant DB

I want to use the QBWebConnector for an app that has multi-tenant DB. It means I need to know the tenant when my app receives data from QBWebConnector to populate the DB correctly.
I am using a PHP kit from consolibytes.
What are my options here?
I see that the functions which are called for building and receiving XML request have params like $user and $extra.
The $user is the user which is used by QBWebConnector to authenticate with the SOAP server.
So should I create multiple QWC files for each tenant as a user and use that to identify the tenant?
And what is this $extra in the param? Should I use that? If then how?
I also see we have callback options and hooks when we create QuickBooks_WebConnector_Server. I am not sure the use of them but can they be used in any way?
Thanks for taking the time to help me.
So should I create multiple QWC files for each tenant as a user and use that to identify the tenant?
Each tenant in your application should have their own username, and thus their own .QWC file.
If your application has multiple users per tenant, you do not need a .QWC file per user. You need a .QWC file per tenant.
And what is this $extra in the param? Should I use that?
The $extra param is for passing additional data to your callback functions. It has nothing to do with tenancy or authentication, so don't use it for that.
I also see we have callback options and hooks when we create QuickBooks_WebConnector_Server. I am not sure the use of them but can they be used in any way?
They can be used, but not for tenancy or authentication.

Loopback passport login

I want to use Loopback passport to login to my app via a third party. However, rather than having anyone successfully authenticating with the third party, I want to be able to only allow those accounts with an email already configured as a user access (i.e. I want to whitelist people from this provider).
Is this possible? Almost all the examples I have seen with Loopback passport and OAuth and similar strategies more generally seem to assume that I am happy to have every Google / Facebook user access my application, whereas that is not my case.
The loopback-example-passport repository extends a few base models (User, AccessToken, UserIdentity and UserCredential).
You can create a new file /common/models/user-identity.js, which can listen for when new identities are created. In there try something like this:
module.exports = function(userIdentity) {
userIdentity.observe('before save', function(context, next) {
if (context.instance) {
console.log(context.instance.profile._json);
}
}
}
Within context.instance.profile._json, you can observe the details of the newly created user, modify their details or remove it if needed.
I have dived into third-party auth few weeks ago and realized that existing documentation and loopback-example-passport is not enough to read in my case. For example, existing loopback-component-passport is unable to work with custom User models.
I think you can perform operation hook on your UserIdentity model and compare email from UserIdentity.profile.emails array and User model emails with find() and filter.

How can I disable Authorization header cache in Ruby On Rails API?

I have developed a stateless RESTful API in Ruby On Rails. The way it works is that when you log in you receive a token, that you then use as an Authorization header to make requests.
There are two different roles available in the API: an Admin role and a Client role.
What I have done is add some role constraints to the routes so I can have the same endpoint pointing to different methods in the controller based on the specific role, like so (from config/routes.rb):
get '/courses', to: 'courses#admin_index', constraints: admin_constraints
get '/courses', to: 'courses#client_index', constraints: client_constraints.
The constraints are implemented like this:
admin_constraints = RoleRouteConstraint.new(User::ROLES[:admin])
client_constraints = RoleRouteConstraint.new(User::ROLES[:client])
Where the RoleRouteConstraint retrieves the user that the Authorization header token belongs to, checks it's role and returns true if the role matches the constructor parameter.
The problem is that when I switch roles, Rails somehow caches my Authorization header from the previous role. Meaning that after I log in in the admin panel (as an admin), interact with the interface, and then go into the client interface, perform some actions, the API will keep my role as a client. If I then try to perform admin-specific actions, like so:
put '/courses/:id', to: 'courses#update', constraints: admin_constraints
I will not be able, since the API thinks I'm still logged in as a client. The thing is that it will work if I restart my rails server. Locally I'm using POW and in staging/production I'm using apache2. So if I perform a Rails restart and repeat the request as an admin, then it will work.
Anyone have any ideas please?

Using Spring Security authorization with context-specific authorities

We need to add access control to our application, making sure that every command is performed by a user who has the proper authorities for the given domain objects. We are already using Spring Security 4.0 for authentication and intend to use it for authorization as well.
What makes this complex is the way that authorities are granted to a given user. In our problem space, a User can found several Companies and hire other Users, making them Employees. Each User can be an Employee of several Companies. Some authorities can be granted to a User directly (e.g. canResetOtherUserPassword); other authorities can also be granted by a Company to an Employee based on their Role in the Company (e.g. canOpenProject, canRenameProject). When performing Company-independent commands, User-specific authorities must be checked by the service layer. When performing Company-specific commands (e.g. open a project for a company, rename an existing project), Employee-specific authorities must be checked.
Now let's consider these last two commands, which would have the following service signatures:
long openProject(long companyId, String title)
void renameProject(long projectId, String title)
To control access for the 1st method, the authorization component could retrieve the acting User through the thread-local SecurityContext.authentication, retrieve the Company using the companyId parameter, retrieve the Employee corresponding to the current User, then match Employee-specific authorities against the required canOpenProject authority.
To control access for the 2nd method, the authorization component could again retrieve the acting User through the Thread-local SecurityContext.authentication, retrieve the Project using the projectId, retrieve the owner Company through project.ownerCompanyId, retrieve the Employee corresponding to the current User, then match Employee-specific authorities against the required canRenameProject.
Clearly, this can be done using procedural code, as I just described. We would prefer to use a declarative approach similar to the #PreAuthorize interceptor that Spring Security already offers, and obviously to write as little code as possible. We just don't know where to start.
Any ideas?
Thanks in advance!
You can implement UserDetails (org.springframework.security.core.userdetails.UserDetails) or just extend a default implementation of UserDetails, like User (org.springframework.security.core.userdetails.User) ---> CustomUserDetails with additional attributes like company (with getters).
finally : use simply #PreAuthorize("principal.company.companyId == #companyId")
Reference : Spring Security 3.1 chapter 10 (you need to go back to chapter 3 for UserDetails implementation)
It was very useful for me !

How to manually validate user in ASP.NET MVC Internet Application template

I'm new to web security so I don't want to implement my own. I plan to use SimpleMembership via the VS2012 template for an ASP.NET MVC Internet Application. The problem is that I need to pass the data via a Web API.
I plan to use basic authentication for my Web API, so I just need to pass username/pass in the http headers. I can intercept the message using Thinktecure.IdentityModel. Here's an example that uses ASP.NET Membership:
authConfig.AddBasicAuthentication((userName, password) =>
Membership.ValidateUser(userName, password));
I can replace Membership.ValidateUser with my own bool function. I've successfully queried my custom database with username/password and everything worked fine. However, I'm using the template's user database because I DON'T want to store string (or even encoded) passwords.
I am unclear on how to manually validate the credentials using the SimpleMembership's database. I can grab a UserProfile, but can't figure out how to check the profile's password.
UserProfile user = context.UserProfiles.Find(1);
==OUTPUT==
user
UserId: 1
UserName: "bob"
Do you know how I can check if an inputted password matches that of an existing user?
Thanks for your help!
Why you are not using Membership.ValidateUser? This is not restricted to just ASP.NET Membership assuming you have your [InitializeSimpleMembership] (here) attribute in the correct places or have executed the logic inside it yourself elsewhere, and you have the correct references to WebMatrix etc you can still just call Membership.ValidateUser and it will use SimpleMemberships Validate user.
If you wanted to go to the database yourself, and assuming you are using hashed password etc then this article is probably going to help as you are going to need to hash your inputed password before selecting it out, the rest of which is just writing some EF or (any other db access method) to select from the User table where the username and hashed passwords match. But I can think of no obvious reason to do this as Membership.ValidateUser will do all this for you.

Resources