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

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.

Related

Not able to Set Password and Enable Account using C# and admin User

Using WPF & C#, I can set all the attributes in Active Directory, but can't do the following :
1) Can't Set User Password
2) Can't Enable User
However, I can do the same thing manually!
Approach Tried:
1.
DirectoryEntry directoryEntry=
directoryEntry.Invoke("SetPassword", new object[] {myPass#x6712}); // To set password
directoryEntry.Properties["userAcountControl"].Value=0x0200; //To Enable User
2.
DirectoryEntry uEntry = new DirectoryEntry(userDn);
uEntry.Invoke("SetPassword", new object[] { password });
uEntry.Properties["LockOutTime"].Value = 0; //unlock account
3.
using (var context = new PrincipalContext( ContextType.Domain ))
{
using (var user = UserPrincipal.FindByIdentity( context, IdentityType.SamAccountName, userName ))
{
user.SetPassword( "newpassword" );
// or
user.ChangePassword( "oldPassword", "newpassword" );
user.Save();
}
}
ERROR ON PASSWORD SET: Exception has been thrown by the target invocation.
ERROR ON ENABLE USER: Access is denied.
NOTE: I'm using a Domain Admin User.
The program gives the exception in these above lines.
Please, Advice! Thanks in Advance !!
Maybe this is just a mistake in your question, but the code you show in your first example wouldn't compile because the password is not in quotes. It should be:
directoryEntry.Invoke("SetPassword", new object[] {"myPass#x6712"});
That code invokes IADsUser.SetPassword. The 'Remarks' in the documentation point to some prerequisites for it to work, namely, that it must be a secure connection. So it may have failed in setting up a secure connection. It would usually try Kerberos to do that, so something might have gone wrong there.
You can try specifically connecting via LDAPS (LDAP over SSL) by pointing it at port 636 (new DirectoryEntry("LDAP://example.com:636/CN=whatever,DC=example,DC=com")), but that requires that you trust the certificate that is served up. Sometimes it's a self-signed cert, so you would need to add the cert to the trusted certs on whichever computer you run this from.
Or, the account you are running it with does not have the 'Reset Password' permission on the account.
For enabling, the userAccountControl attribute is a bit flag, so you don't want to set it to 2, mostly because 2 (or more accurately, the second bit) means that it's disabled. So you want to unset the second bit. You would do that like this:
directoryEntry.Properties["userAcountControl"].Value =
(int) directoryEntry.Properties["userAcountControl"].Value & ~2;
Most of the time that will result in a value of 512 (NORMAL_ACCOUNT), but not necessarily. The account could have other bits set that you don't want to inadvertently unset.
You also need to call .CommitChanges() for the changes to userAcountControl to take effect:
directoryEntry.CommitChanges();

CallerId of OrganizationServiceProxy

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.

AWS Cognito - User pool xxxx does not exist

var client = new AmazonCognitoIdentityProviderClient("MYKEY", "MYSECRET", RegionEndpoint.USEast1);
var request = new AdminGetUserRequest();
request.Username = "USERNAME";
request.UserPoolId = "POOLID";
var user = client.AdminGetUserAsync(request).Result;
The key/secret are authenticating as a user with Administrator Access. For good measure, I've also given it the AmazonCognitoPowerUser policy.
The region endpoint is correct and the same as the one my user pool is in. The user pool Id is correct. The first part of the user pool ID matches the region.
I'm at a loss for where else this could possibly be going wrong. Any ideas?
Update 8/2/19
Manual CLI command:
PM> aws cognito-idp list-user-pools --region us-east-1 --max-results 10
{
"UserPools": []
}
The region is correct, so there must be some issue with permissions. Is there anything I could try tweaking on the pool, or other policies I may need to add to the user?
So, it looks like this is some sort of AWS glitch with the existing IAM user.
Having created a new user with exactly the same permissions, access works as intended both from CLI and the code in the original question.
Actually your configuration can be wrong , you downloaded awsconfiguration.json and it looks like same I know.. but this configuration can be wrong. When you examine the json you will see a field.. "CognitoUserPool": {PoolId, appclient id ..}
You need to open your user pool and create new client or control existing client information. Check your awsconfiguration.json again with this webpage's pool id, appclient id etc. Update your json... it will solve the problem.
I ran into this problem with the AWS CLI and it puzzled me too, but I learned that I needed to provide the profile name in the parameter list to get it to work. So it looked like this:
aws cognito-idp admin-get-user --profile dev-account ....
My profiles are stored on my Mac at cat ~/.aws/config| grep profile
The config file is created by an in-house custom script. This is the contents of what that file looks like.
[profile dev-account]
sso_start_url = https://yourcompanyname.awsapps.com/start#/
sso_region = us-east-1
sso_account_id = 1234567890
sso_role_name = PowerUserAccess
region = us-east-1
output = json
Also, in this folder is a "credentials" file that has some JSON for these variables: profile name, aws_access_key_id, aws_secret_access_key, aws_session_token, aws_expiration

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.

LDAP search fails on server, not in Visual Studio

I'm creating a service to search for users in LDAP. This should be fairly straightforward and probably done a thousand times, but I cannot seem to break through properly. I thought I had it, but then I deployed this to IIS and it all fell apart.
The following is setup as environment variables:
ldapController
ldapPort
adminUsername 🡒 Definitely a different user than the error reports
adminPassword
baseDn
And read in through my Startup.Configure method.
EDIT I know they are available to IIS, because I returned them in a REST endpoint.
This is my code:
// Connect to LDAP
LdapConnection conn = new LdapConnection();
conn.Connect(ldapController, ldapPort);
conn.Bind(adminUsername, adminPassword);
// Run search
LdapSearchResults lsc = conn.Search(
baseDn,
LdapConnection.SCOPE_SUB,
lFilter,
new string[] { /* lots of attributes to fetch */ },
false
);
// List out entries
var entries = new List<UserDto>();
while (lsc.hasMore() && entries.Count < 10) {
LdapEntry ent = lsc.next(); // <--- THIS FAILS!
// ...
}
return entries;
As I said, when debugging this in visual studio, it all works fine. When deployed to IIS, the error is;
Login failed for user 'DOMAIN\IIS_SERVER$'
Why? The user specified in adminUsername should be the user used to login (through conn.Bind(adminUsername, adminPassword);), right? So why does it explode stating that the IIS user is the one doing the login?
EDIT I'm using Novell.Directory.Ldap.NETStandard
EDIT The 'user' specified in the error above, is actually NOT a user at all. It is the AD registered name of the computer running IIS... If that makes any difference at all.
UPDATE After consulting with colleagues, I set up a new application pool on IIS, and tried to run the application as a specified user instead of the default passthrough. Exactly the same error message regardless of which user I set.
Try going via Network credentials that allows you to specify domain:
var networkCredential = new NetworkCredential(userName, password, domain);
conn.Bind(networkCredential);
If that does not work, specify auth type basic (not sure that the default is) before the call to bind.
conn.AuthType = AuthType.Basic;

Categories