CallerId of OrganizationServiceProxy - c#

I am making a external service which will create a record in Order entity of Dynamics 365 with the default field(e.g: created by and some default fields) will be named after the user who wants to create.
For that I tried using the CallerId property on the OrganizationServiceProxy class. I am setting the CallerId property by the user of CRM who is actually wanting to create a record. But I’m only able to create record if the user of crm has System Administrator role.
Some block of code is added for better understanding:
public void Get(Guid userId)
{
var proxy = new OrganizationServiceProxy(new Uri(c.ServiceUri), null, crmCredentials, null);
proxy.EnableProxyTypes();
var context = new OrganizationContext(proxy);
// now setting caller id
proxy.CallerId = userId;
// generating order entity
var t = new SalesOrder();
t.Name = "Demo";
.....
...
.
context.AddObject(t);
context.SaveChanges(); // getting exceptions for normal user on save changes
}
Now my question is how to overcome the exception if the user of crm is not privileged with System Administrator role.

Verify if any of the security role assigned to that “normal user” has create privilege granted on minimum user level (orange pie) for “Order” entity (sales order) under “Sales” tab. I guess not.
Give that privilege & verify the same code execution.

Your code works fine as long as the user that you are setting as CallerId has the Sales Manager Security Role. The user you are logging in with must also have at least a Sales Manager Security Role and the Act on Behalf of Another User privilege that can be found under Business Management tab.

Related

ASP.NET Boilerplate Allow Self-Provisioning Tenant Registration

so im trying to create a SaaS application with ASP.NET Boilerplate, and i come into some problem as follows:
As i observe the framework, i noted that the "RegisterAsync" function in UserRegistrationManager create user based on the currently active tenant. It means if i currently log in on tenant '1', then when i register new user, the new user will have tenantId '1'. On the other hand, when i currently not logged in, if i register a new user, the app will show exception 'cannot register host user'.
public async Task<User> RegisterAsync(string name, string surname, string emailAddress, string phoneNumber, string userName, string plainPassword, bool isEmailConfirmed)
{
CheckForTenant();
var tenant = await GetActiveTenantAsync();
var user = new User
{
TenantId = tenant.Id,
Name = name,
Surname = surname,
EmailAddress = emailAddress,
PhoneNumber = phoneNumber,
IsActive = true,
UserName = userName,
IsEmailConfirmed = isEmailConfirmed,
Roles = new List<UserRole>()
};
return user;
}
private void CheckForTenant()
{
if (!AbpSession.TenantId.HasValue)
{
throw new InvalidOperationException("Can not register host users!");
}
}
The application that i want to build requires the function for new user to be able to sign up along with free trial and then paid subscription. So i think that the new user should be able to create tenant by themself. So if the new user register, they will be forced to create new tenant before they can do any other thing in the app.
The problem is that the tenantId column in User table cannot be null, so i can register without tenant. Im thinking of assign all newly created user to 'Default' tenant at first, but i think that this was not the best practices.
Is there any way to overcome this problem or any references about that? Thanks in advance!
Based on my empirical SaaS Application development experience, a typical Self-Signup flow in Multi-Tenant applications would be like the one given below
User opts to self-signin
Allow the user to pick a subscription plan (most likely a trial plan)
Get the Company Name (tenant name) as part of the signup flow
Create a new tenant that has the subscription (2)
Add the signup user as the administrator for that tenant
In case of a trial plan, set up the suitable request handler to keep validating if the tenant has crossed the subscribed number of trial days, in that case, force redirect to payment page or signout
If the user has opted to Signup for a paid subscription (during signup), after provisioning the tenant go to the payment page. Once payment succeeds, capture the transactionid and allow the user to login and use the application.
The flow that you wanted to be using is straightforward
Build a custom self-signup process, obtain the company name (Tenant Name)
Also capture the emailid of the user that is performing the sign-up
Create the tenant based on info from (1)
Set the administrator for the tenant based on the info from (2)
All your API calls should be working fine.
Note
Have a separate Self-Signup Service like (TenantSelfRegistrationService) so that you can allow anonymous access to that service.
In terms of security, set captcha and set rate-limits or CSRF Tokens etc to enforce security in the signup process.
Hope this clarifies
I looked at the code and the documentation and I think you should never allow an unknown user to create new tenants. This should happen by a person who has the correct authorization to create tenants. This is a user that exists in the host tenant.
You as admin in the host tenant need to create tenant for somebody else and add them as admin for that tenant.
Registering users is then done through the normal way with the register webpage running for that tenant.
How to do that, I leave to you to figure out with the documentation of boilerplate itself! Documentation

Strange problem with authentication on IBMMQ, it takes the running user ID

I've got a strange problem when I perform a push of a message in a queue. I've configured my application to read userid/password from app.config. when the message is put on the queue I got the username of the user that has run the application and it's the one of the .config file.
The code I use to create the MQQueueManager is
private static readonly Lazy<MQQueueManager> lazy =
new Lazy<MQQueueManager>(() =>
{
var properties = new Hashtable();
var container = ContainerWrapper.Container;
IConfiguration configuration = container.GetInstance<IConfiguration>();
properties.Add(MQC.HOST_NAME_PROPERTY, configuration.GetValue<string>("HOST_NAME_PROPERTY"));
properties.Add(MQC.PORT_PROPERTY, configuration.GetValue<int>("PORT_PROPERTY"));
properties.Add(MQC.USER_ID_PROPERTY, configuration.GetValue<string>("USER_ID_PROPERTY"));
properties.Add(MQC.PASSWORD_PROPERTY, configuration.GetValue<string>("PASSWORD_PROPERTY"));
properties.Add(MQC.CHANNEL_PROPERTY, configuration.GetValue<string>("CHANNEL_PROPERTY"));
MQQueueManager queueManager = new MQQueueManager(configuration.GetValue<string>("QUEUE_MANAGER_NAME"), properties);
return queueManager;
});
Am I missing something?
Thanks in advance
In order for your connection to run as the user ID and password provided on the connect, you must configure the queue manager to check the user ID and password and also you must configure the queue manager to adopt the validated user ID.
DISPLAY QMGR CONNAUTH
The value in the CONNAUTH field is the name of an AUTHINFO object. If it is blank, user ID and password checking is not enabled. Set it to an appropriate object name.
ALTER QMGR CONNAUTH(SYSTEM.DEFAULT.AUTHINFO.IDPWOS)
Now look at the attributes of it.
DISPLAY AUTHINFO(name-from-connauth) ALL
If ADOPTCTK is set to NO, the the user ID will not be adopted as the connection's user ID, and so will not be seen in the message context.
ALTER AUTHINFO(name-from-connauth) AUTHTYPE(IDPWOS) ADOPTCTX(YES)
If you had to make any alterations, you must now issue this command.
REFRESH SECURITY TYPE(CONNAUTH)
You probably need to add another line to your properties.
Try (from memory so you will need to find the correct constant)
USE_MQCSP_USERNAME_PASSWORD This should be a boolean and should be set to yes....
Add this to your properties, then create the queue manager with those properties.

Add 2fa authenticator to user

I have been trying to work out how to enable 2f login with Google Authentication in my Identity server 4 application.
2fa works fine with both email and phone.
if i check
var userFactors = await _userManager.GetValidTwoFactorProvidersAsync(user);
it has two email and phone. I am assuming that this would be the two factor providers that have been set up for this user.
Now if i check _usermanager again there is a field called tokenproviders. Which appears to contain default, email, phone, and authenticator. I assume these are the ones that Asp .net identity is configured to deal with.
I have worked out how to create the secret needed to genreate the QR code for the authecator app. As well has how to build the QR code and to test the code
var code = _userManager.GenerateNewAuthenticatorKey();
var qr = AuthencatorHelper.GetQrCodeGoogleUrl("bob", code, "My Company");
var user = await _signInManager.TwoFactorAuthenticatorSignInAsync(codeFromAppToTestWith, true, false);
if (user == null)
{
return View("Error");
}
Now the problem. I have gone though every method I can find on the user trying to work out how to add another token provider to the user.
How do I assign a new token provider to the user and supply the secret code needed to create the authentication codes?? I am not even seeing any tables in the database setup to handle this information. email and phone number are there and there is a column for 2faenabled. But nothing about authenticator.
I am currently looking into creating a custom usermanager and adding a field onto the application user. I was really hoping someone had a better idea.
From what I can see, you are generating a new authenticator key each time the user needs to configure an authenticator app:
var code = _userManager.GenerateNewAuthenticatorKey();
You should be aware that using GenerateNewAuthenticatorCodeAsync will not persist the key, and thus will not be useful for 2FA.
Instead, you need to generate and persist the key in the underlying storage, if it not already created:
var key = await _userManager.GetAuthenticatorKeyAsync(user); // get the key
if (string.IsNullOrEmpty(key))
{
// if no key exists, generate one and persist it
await _userManager.ResetAuthenticatorKeyAsync(user);
// get the key we just created
key = await _userManager.GetAuthenticatorKeyAsync(user);
}
Which will generate the key if not already done and persist it in the database (or any storage configured for Identity).
Without persisting the key inside the storage, the AuthenticatorTokenProvider will never be able to generate tokens, and will not be available when calling GetValidTwoFactorProvidersAsync.

What is the best way to get the value of what user is logged in?

I have a Windows form application that users can log into. The application is alone and doesn't connect with anything or anyone.
Besides creating a global variable, how could I have an easily accesible variable to check the current users permissions?
A not so kosher way of doing things is just pass the ID of the userType in the Form constructor and according to that, .Enable = false; buttons they don't have permissions to use.
Thanks!
If you want the id of the currently logged on Windows user (ie. the user that the application is running as), there are two ways of getting it:
By putting AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal); in your startup, you can use Thread.CurrentPrincipal to get the user's security principal.
You can use WindowsIdentity.GetCurrent() to get the current user's identity. You can then create a security principal using new WindowsPrincipal(identity).
Both of these are equivalent, and will get you a security principal that has an IsInRole method that can be used to check permissions.
Use the WindowsIdentity class for getting the users Identity, found under System.Security.Principal.WindowsIdentity.
WindowsIdentity current = WindowsIdentity.GetCurrent();
Console.WriteLine("Name:" + current.Name);
Use the WindowsPrincipal class for getting the users Roles, found under System.Security.Principal.WindowsPrincipal.
WindowsIdentity current = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(current);
if (principal.IsInRole("your_role_here")
{
Console.WriteLine("Is a member of your role");
}

Authentication, Authorization, User and Role Management and general Security in .NET

I need to know how to go about implementing general security for a C# application. What options do I have in this regard? I would prefer to use an existing framework if it meets my needs - I don't want to re-invent the wheel.
My requirements are as follows:
the usual username/password authentication
managing of users - assign permissions to users
managing of roles - assign users to roles, assign permissions to roles
authorization of users based on their username and role
I am looking for a free / open-source framework/library that has been time-tesed and used by the .Net community.
My application takes a client/server approach, with the server running as a windows service, connecting to a SQL Server database. Communication between client and server will be through WCF.
One other thing that is important is that I need to be able to assign specific users or roles permissions to View/Update/Delete a specific entity, whether it be a Customer, or Product etc. For e.g. Jack can view a certain 3 of 10 customers, but only update the details of customers Microsoft, Yahoo and Google, and can only delete Yahoo.
For coarse-grained security, you might find the inbuilt principal code useful; the user object (and their roles) are controlled in .NET by the "principal", but usefully the runtime itself can enforce this.
The implementation of a principal can be implementation-defined, and you can usually inject your own; for example in WCF.
To see the runtime enforcing coarse access (i.e. which functionality can be accessed, but not limited to which specific data):
static class Roles {
public const string Administrator = "ADMIN";
}
static class Program {
static void Main() {
Thread.CurrentPrincipal = new GenericPrincipal(
new GenericIdentity("Fred"), new string[] { Roles.Administrator });
DeleteDatabase(); // fine
Thread.CurrentPrincipal = new GenericPrincipal(
new GenericIdentity("Barney"), new string[] { });
DeleteDatabase(); // boom
}
[PrincipalPermission(SecurityAction.Demand, Role = Roles.Administrator)]
public static void DeleteDatabase()
{
Console.WriteLine(
Thread.CurrentPrincipal.Identity.Name + " has deleted the database...");
}
}
However, this doesn't help with the fine-grained access (i.e. "Fred can access customer A but not customer B").
Additional; Of course, for fine-grained, you can simply check the required roles at runtime, by checking IsInRole on the principal:
static void EnforceRole(string role)
{
if (string.IsNullOrEmpty(role)) { return; } // assume anon OK
IPrincipal principal = Thread.CurrentPrincipal;
if (principal == null || !principal.IsInRole(role))
{
throw new SecurityException("Access denied to role: " + role);
}
}
public static User GetUser(string id)
{
User user = Repository.GetUser(id);
EnforceRole(user.AccessRole);
return user;
}
You can also write your own principal / identity objects that do lazy tests / caching of the roles, rather than having to know them all up-front:
class CustomPrincipal : IPrincipal, IIdentity
{
private string cn;
public CustomPrincipal(string cn)
{
if (string.IsNullOrEmpty(cn)) throw new ArgumentNullException("cn");
this.cn = cn;
}
// perhaps not ideal, but serves as an example
readonly Dictionary<string, bool> roleCache =
new Dictionary<string, bool>();
public override string ToString() { return cn; }
bool IIdentity.IsAuthenticated { get { return true; } }
string IIdentity.AuthenticationType { get { return "iris scan"; } }
string IIdentity.Name { get { return cn; } }
IIdentity IPrincipal.Identity { get { return this; } }
bool IPrincipal.IsInRole(string role)
{
if (string.IsNullOrEmpty(role)) return true; // assume anon OK
lock (roleCache)
{
bool value;
if (!roleCache.TryGetValue(role, out value)) {
value = RoleHasAccess(cn, role);
roleCache.Add(role, value);
}
return value;
}
}
private static bool RoleHasAccess(string cn, string role)
{
//TODO: talk to your own security store
}
}
my answer is probably dependent upon the answer to this question: Is this an Enterprise application which lives within a network with Active Directory?
IF the answer is yes, then these are the steps I would provide:
1) Create Global Groups for your application, in my case, I had a APPUSER group and an APPADMIN group.
2) Have your SQL Server be able to be accessed in MIXED AUTHENTICATION mode, and then assign your APPUSER group(s) as the SQL SERVER LOGIN to your database with the appropriate CRUD rights to your DB(s), and ensure that you access the SQL SERVER with Trusted Connection = True in your connection string.
At this point, your AD store will be responsible for authentication. Since, you're accessing the application via a TRUSTED CONNECTION, it will pass the identity of whatever account is running the application to the SQL Server.
Now, for AUTHORIZATION (i.e. telling your application what the logged in user is allowed to do) it's a simple matter of querying AD for a list of groups which the logged in user is a member of. Then check for the appropriate group names and build your UI based upon membership this way.
The way my applications work are thus:
Launching the application, credentials are based upon the logged-in user, this is the primary aspect of authentication (i.e. they can log in therefore they exist)
I Get all Groups For the Windows Identity in question
I check for the Standard USER Group -- if this group does not exist for the Windows Identity in question, then that's an authentication FAIL
I check for ADMIN User Group -- With this existing in the user's groups, I modify the UI to allow access to administration components
Display the UI
I then have either a PRINCIPLE object with the determined rights/etc on it, or I utilize GLOBAL variables that I can access to determine the appropriate UI while building my forms (i.e. if my user is not a member of the ADMIN group, then I'd hide all the DELETE buttons).
Why do I suggest this?
It's a matter of deployment.
It has been my experience that most Enterprise Applications are deployed by Network Engineers rather than programmers--therefore, having Authentication/Authorization to be the responsibility of AD makes sense, as that is where the Network guys go when you discuss Authentication/Authorization.
Additionally, during the creation of new users for the network, a Network Engineer (or whoever is responsible for creating new network users) is more apt to remember to perform group assignments while they are IN AD than the fact that they have to go into a dozen applications to parse out assignments of authorization.
Doing this helps with the maze of permissions and rights that new hires need to be granted or those leaving the company need to be denied and it maintains authentication and authorization in the central repository where it belongs (i.e. in AD # the Domain Controller level).
Look into ASP.NET's Membership Providers. I don't think the out of box SQLMembershipProvider will work in your case but it's easy enough to roll your own provider.
I would take a look at something like CSLA.net: Expert C# 2008 Business Objects
It should provide everything you require.
WCF have rich security related functionality provides both authorization and authentication.
In details here:
http://msdn.microsoft.com/en-us/library/ms735093.aspx
I think you are looking at a few separate problems here--it is no accident most security systems separate authentication and authorization.
For authentication, the bigger question is logistical. Or, is there a logical place for these users to live, be it locally to the application, in Active Directory, some other LDAP store or even in some other application. Exactly where is pretty immaterial--we just need to be able to solidly identify users and preferably make that task someone else's problem. End of the day you really just need a unique identifier and the comfort that Bob from Accounting is actually Bob from Accounting.
Authorization is the more interesting part of the problem here. I think, if it is truly fine-grained, you really want to manage this wholly within your application, no matter where the users come from. Marc Gravell really hit on a good way to model at least some of this--use some custom implementation of IPrincipal and PrincipalPermission to manage things is a very clean way to get started. Beyond that you can use techniques like this one to make more complex authorization decisions in a rather clean manner.
I would use the term - 'RBAC' (Role based Access Control system) as the Solution to all your requirements.
I would not go in much detail for explaining 'RBAC' here, rather I would briefly describe it as:
It basically contains 3 features.
1) Authentication - It confirms the user's identity. Usually it is done via user accounts and passwords or credentials.
2) Authorization - It defines what user can do and cannot do in an application. Ex. ‘Modifying order’ is allowed but ‘creating new order’ is not allowed.
3) Auditing of user actions on applications. - It keeps track of user's actions on applications, as well as who has granted which access to which users?
you can check RBAC on wiki here.
https://en.wikipedia.org/wiki/Role-based_access_control
Now, regarding answer to your requirements - one of the possible solution is to extend ASP.NET membership as per your needs.
And regarding, some ready to use framework , I would recommend VisualGuard for which I work, you should check this, It does all the things what you need very easily, and what is most important is, It manages all your users, roles, permissions, and applications via Central Administration Console, and for defining permissions, administrators do not require developer's knowledge, i.e he/she can create restrictions on activities via UI.
you can also check this article to have more understanding on permission and role based system.
http://www.visual-guard.com/EN/net-powerbuilder-application-security-authentication-permission-access-control-rbac-articles/dotnet-security-article-ressources/role-based-access-control-source_soforum.html

Categories