Is there a way to identify whether the logged in account is local account or active directory account on OS X? If yes, how can we retrieve the domain name?
You can create a CBUserIdentity for the user from their username:
CBUserIdentity* identity = [CBUserIdentity identityWithName:NSUserName() authority:[CBIdentityAuthority defaultIdentityAuthority]];
Then, you can obtain that user identity's authority:
CBIdentityAuthority* authority = identity.authority;
Then, you can see if that is the local authority (the alternative is the managed authority):
if ([authority isEqual:[CBIdentityAuthority localIdentityAuthority])
{
// user is local
}
else
{
// user is managed
}
The authority has a localizedName property, but that's not likely to include the domain name, I don't think. I don't know how to get that.
Update:
This is an approach using the Open Directory API:
ODSession* session = [ODSession defaultSession];
ODNode* node = [ODNode nodeWithSession:session type:kODNodeTypeAuthentication error:NULL];
ODQuery* query = [ODQuery queryWithNode:node forRecordTypes:kODRecordTypeUsers attribute:kODAttributeTypeRecordName matchType:kODMatchEqualTo queryValues:NSUserName() returnAttributes:kODAttributeTypeStandardOnly maximumResults:0 error:NULL];
NSArray* results = [query resultsAllowingPartial:NO error:NULL];
ODRecord* record = results.firstObject;
At this point, you can query the record for some of its attributes. One that may be of interest might be kODAttributeTypeMetaNodeLocation:
NSArray* attributes = [record valuesForAttribute:kODAttributeTypeMetaNodeLocation error:NULL];
NSString* attribute = attributes.firstObject;
For a local account, the meta node location should be "/Local/Default". I tested with an LDAP account and that gave ""/LDAPv3/my.ldap.server.example.com". I don't have an Active Directory account to test with.
Alternatively, you can try kODAttributeTypeMetaRecordName. For a local account, that returned nil. For an LDAP account, it gave the fully distinguished name: "uid=ken,ou=People,dc=example,dc=com". Again, I don't know what it would do for an Active Directory account.
You can log the record to see other attributes that are available. That will show the attribute keys as string values. You can look here to try to find a symbolic constant for the one(s) of interest, or check /System/Library/Frameworks/OpenDirectory.framework/Frameworks/CFOpenDirectory.framework/Headers/CFOpenDirectoryConstants.h for some which aren't documented.
Once you find what you really care about, you can maybe simplify the query by requesting just those instead of kODAttributeTypeStandardOnly. Also, you should consider running the query asynchronously rather than synchronously as I did in my example code.
For me the code:
NSMutableString *userDataDirectory = [[NSMutableString alloc] initWithString:NSHomeDirectory()];
NSLog(#"%#", userDataDirectory);
prints: /Users/jwlaughton
Is this what you're looking for?
Related
I am debugging confirmation email flow when signing up a new User in Asp.Net Core web application with Identity Server 4.
Since I had already signed up with my actual email, to reuse it, I modified the UserName and Email in AspNetUsers table using SQL Update to some random value.
Now when I am signing up with the original email again. I am getting a duplicate user error
result = await _userManager.CreateAsync(user, model.Password);
I have already:
Cleared browser cache.
Closed local IIS Express
Restarted Visual Studio.
Used_userManager.DeleteAsync() after updating the UserName and Email back to original values but this gives an Microsoft.AspNetCore.Identity.IdentityError with description Optimistic concurrency failure, object has been modified.
On running this query on Sql Server
select * from INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME in ( 'UserName' , 'Email')
I get the following:
I know that this is not a good practice to mess with backend, but this is development environment and I could continue my work with another email.
I would request readers to help in understanding how the User could be safely scorched to be able to reuse the email.
Appreciate your time
I agree with Kyle's comment and to further speed up your debug process you should note that if you use gmail to do this you can debug this process using one email.
from google/gmails perspective myaccount#gmail.com == my.acount#gmail.com == m.y.a.c.c.ount#gmail.com etc etc just try it out, google disregards all period characters in the email. you can enumerate/exhaust ~2^8 emails (in this example) if you just enumerate through the local-part of the e-mail address. but from your applications side, myaccount#gmail.com is not the same as my.account#gmail.com, ie they are different user accounts. Basically you can use one email to test out this feature of yours without having to delete the user.
Here is how I did it and finally got passed the pesky "concurrency failure" error message... This works in ASP.NET CORE 2.2
Obtain the user object through the FindByName method first.
Remove the user from their assigned Role (in this case I hard coded "Admin" because that is the role I'm interested in but fill in your own), then delete the user.
//Delete user.
//Obtain the user object through the FindByName method first.
//Remove the user from their assigned Role, then delete the user.
var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
ApplicationUser delAppUser = new ApplicationUser
{
Email = "SomeEmailForindividualAdminUser",
UserName = "SomeUsernameindividualAdminUser"
};
Task <ApplicationUser> taskGetUserAppUser = userManager.FindByNameAsync(delAppUser.UserName);
taskGetUserAppUser.Wait();
Task<IdentityResult> taskRemoveFromRoleAppUser = userManager.RemoveFromRoleAsync(taskGetUserAppUser.Result, "Admin");
taskRemoveFromRoleAppUser.Wait();
Task<IdentityResult> taskDeleteAppUser = userManager.DeleteAsync(taskGetUserAppUser.Result);
taskDeleteAppUser.Wait();
I can't figure out the proper syntax to open another user's OneDrive folder. What am I doing wrong? The parameter is supposed to be "ID", but is that a user ID/name, a drive ID - what? Below is some pseudo-code, based on the OneDrive API Browser sample.
I get this error: "The provided drive id appears to be malformed, or does not represent a valid drive."
private async Task LoadUserDriveTest()
{
Item folder;
var expandValue = "thumbnails,children";
folder =
await oneDriveClient
.Drives[$"user_mydomain_onmicrosoft_com"]
.Root
.Request()
.Expand(expandValue)
.GetAsync();
//Code: invalidRequest
//Message: The provided drive id appears to be malformed, or does not represent a valid drive.
}
For a drive identifier, you can use any of these:
User's UPN address (usera#mydomain.onmicrosoft.com)
User's object ID in AAD (guid)
DriveID previously obtained by other means (say, by having a shared item return a parentReference property with a driveID).
You'd think I would have documented that here, but apparently I need to do some more writing.
We use Apache Shiro to authenticate and authorize users using our active directory.
Authenticating the user and mapping groups works just fine using the following config:
adRealm = org.apache.shiro.realm.activedirectory.ActiveDirectoryRealm
adRealm.searchBase = "OU=MYORGANIZATION,DC=MYDOMAIN,DC=COM"
adRealm.groupRolesMap = "CN=SOMEREADGROUP":"read","CN=SOMEMODIFYGROUP":"modify","CN=SOMEADMINGROUP":"admin"
adRealm.url = ldaps://my.ad.url:636
adRealm.systemUsername= systemuser
adRealm.systemPassword= secret
adRealm.principalSuffix= #myorganization.mydomain.com
I can authenticate in Shiro using the following lines:
String user = "someuser";
String password = "somepassword";
Subject currentUser = SecurityUtils.getSubject ();
if (!currentUser.isAuthenticated ()){
UsernamePasswordToken token = new UsernamePasswordToken (user,
password);
token.setRememberMe (true);
currentUser.login (token);
}
We now want to get more user information from our ActiveDirectory. How can I do that using Apache Shiro? I was not able to find anything about it in the documentation.
In the source code of ActiveDirectoryRealm I found this line:
NamingEnumeration answer = ldapContext.search(searchBase, searchFilter, searchArguments, searchCtls);
So the first part of the answer is clear: use the ldapContext to search something in it. But how can I retrieve the LdapContext?
It depends on what you are trying to do. Are you just trying to reuse the context to run a query for something other then authentication or authorization? Or are you trying to change the behavior of the query in the AD realm?
If the latter, you would need to extend the ActiveDirectoryRealm and override the queryForAuthorizationInfo() method.
Are you implementing something that is custom for your environment?
(updated)
A couple things:
The realm has access to the LdapContext in the two touch points: queryForAuthenticationInfo() and queryForAuthorizationInfo(), so if you extend the AD realm or AbstractLdapRealm you should already have it. You could change the query to return other info and add the extra info to your Principal. Then you have access to that info directly from your Subject object.
Your realms, are not required to be singletons.
If you want to do some other sort of user management (email all users with a given role, create a user, etc). Then you could create a LdapContextFactory in your shiro.ini, and use the same instance for multiple objects.
[main]
...
ldapContextFactory = org.apache.shiro.realm.ldap.JndiLdapContextFactory
ldapContextFactory.systemUsername = foobar
ldapContextFactory.systemPassword = barfoo
adRealm = org.apache.shiro.realm.activedirectory.ActiveDirectoryRealm
adRealm.ldapContextFactory = $ldapContextFactory
...
myObject = com.biz.myco.MyObject
myObject.ldapContextFactory = $ldapContextFactory
This would work well if myObject is interacting with other Shiro components, (responding to events, etc), but less so if you need access to it from another framework. You could work around this by some sort of static initialization that builds creates the ldapContextFactory, but in my opinion, this is where the sweet spot of using the shiro.ini ends, and where using Guice or Spring shines.
I have been trying to setup gerrit to work with LDAP authentication. I read documentation numerous time some link do not work to the examples documentation pulled from tuleap on subject comes up with different solutions and explanations I have found three different configurations for ldap.inc from tuleap this is very confusing lacking explanation too.
So i am stuck with this problem. I have spent hours reading and trying to sort this out. Can someone tell me what am I doing wrong? here is my
ldap.inc
<?php
// LDAP server(s) to query for more information on Tuleap users and
// for authentication.
// You may use a comma-separated list if there are several servers available
// (leave blank to disable LDAP lookup).
// To specify secure LDAP servers, use 'ldaps://servername'
$sys_ldap_server = 'techhub.lt';
// To enable LDAP information on Tuleap users, also define the DN
// (distinguised name) to use in LDAP queries.
// The ldap filter is the filter to use to query the LDAP directory
// (%name% are substituted with the value from the user table)
$sys_ldap_dn = 'dc=techhub,dc=lt';
// For LDAP systems that do not accept anonymous binding, define here
// a valid DN and password:
$sys_ldap_bind_dn = "cn=admin,dc=techhub,dc=lt";
$sys_ldap_bind_passwd = "pass";
// LDAP authentication:
// Tuleap only supports authentication with a attempt to bind with LDAP server
// with a DN and a password.
// As the DN is usually long (eduid=1234,ou=people,dc=tuleap,dc=com) people
// usually authenticate themself with a login. So we need to first look
// for the DN that correspond to the given login and once found attempt to bind
// with the given password.
// In order to autenticate successfully users you need to properly
// User login (authentication 1st step)
$sys_ldap_uid = 'uid';
// User unique identifier. It's probably not the uid (or login) because it
// may change. This is a value that never change whatever happens to the
// user (even after deletion). It correspond to ldap_id field in user table
// in database.
// (authentication 2st step)
$sys_ldap_eduid = 'eduid';
// User common name
$sys_ldap_cn = 'cn';
// User email address
$sys_ldap_mail = 'mail';
// Specific DN to look for people
// You may use more than one DN separated by ; if you want to use several branches.
// Example : 'ou=People, dc=st, dc=com ; ou=Extranet, dc=st, dc=com'
$sys_ldap_people_dn = 'ou=people,dc=techhub,dc=lt';
// Filter used to look for user. It should cover a wide selection of
// fields because it's aim to find a user whatever it's given (email, name,
// login, etc).
$sys_ldap_search_user='(|(uid=%words%)(cn=%words%)(mail=%words%))';
// By default tooltip search is using ($sys_ldap_cn=%words%*) search filter (Hardcoded)
// You can change for a more sophisticated search
// $sys_ldap_tooltip_search_user='(&(|(sn=%words%*)(givenName=%words%*)(uid=%words%*))(!(givenName=BoiteVocale))(uid=*))';
// By default tooltip search attrs are $sys_ldap_cn and $sys_ldap_uid (Hardcoded)
// You can choose the attributes the search will retrieve
// $sys_ldap_tooltip_search_attrs='uid;sn;givenName';
// On account creation, what it the default user status (A, R, ...)
$sys_ldap_default_user_status = 'A';
// Enable LDAP based authentication for SVN by default for new projects
$sys_ldap_svn_auth = 1;
// Enable LDAP daily synchronization
$sys_ldap_daily_sync = 1;
// Enable usage of LDAP for people management. For instance autocompletion on
// user list, automatic creation of users not already referenced in the forge.
$sys_ldap_user_management = 1;
// Enable ldap group management.
// This allows to mirror a LDAP group defined in LDAP directory within the forge
// Doesn't work yet with only works with OpenLDAP compatible directories yet.
$sys_ldap_grp_enabled = 1;
// Specific DN where the user groups are
$sys_ldap_grp_dn = 'ou=groups,dc=techhub,dc=lt';
// Field that reprsent group name
$sys_ldap_grp_cn = 'cn';
// Field that indicate the membership of a user in a group
$sys_ldap_grp_member = 'uniquemember';
?>
AND gerrit.conf
[gerrit]
basePath = git
canonicalWebUrl = http://techhub.lt:2401/
[database]
type = H2
database = db/ReviewDB
[sendemail]
smtpServer = localhost
[container]
user = root
javaHome = /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.45.x86_64/jre
[sshd]
listenAddress = *:29418
[httpd]
listenUrl = http://*:2401/
[cache]
directory = cache
[auth]
type = LDAP
[ldap]
server = ldap://techhub.lt
accountBase = ou=people,dc=cro,dc=techhub,dc=lt
groupBase = ou=group,dc=cro,dc=techhub,dc=lt
accountFullName = cn
That's 2 different problems.
Do you manage to authenticate with LDAP accounts on gerrit ?
If yes, I think the problem comes from "$sys_ldap_eduid = 'eduid';" parameter in tuleap ldap config. This attribute should be the unique identifier of one's account in ldap (either you have such an attribute of you can use 'uid' as a fallback.
I'm using the GoogleDrive Objective-C SDK, and I'm running into an issue. I want to build up a path -> ID mapping structure, so I ask Drive for a list of all of a users files. Normally this works fine. But, in cases where users have very large amounts of files, the server returns an internal error. I can fix this by setting the maxResults property on my GTLQueryDrive to a lower number. When I do that, everything works as expected, EXCEPT that the nextPageToken (and nextLink) property of the GTLDriveFileList is nil. I believe I need this nextPageToken to continue grabbing file information. I have tried setting the fields property on my query to nil, to a string that includes nextPageToken, and to a string that does not include nextPageToken. The nextPageToken property appears to be nil in all cases. Is there something I am missing? Thanks!
Adding answer based on comment chain.
Here's a little sample that you can experiment with.
driveService.shouldFetchNextPages = YES;
GTLQueryDrive *query = [GTLQueryDrive queryForFilesList];
query.maxResults = 5;
// queryTicket can be used to track the status of the request.
[driveService executeQuery:query
completionHandler:^(GTLServiceTicket *ticket, GTLDriveFileList *files,
NSError *error) {
if (files) {
NSLog(#"Have response %#", files.items);
NSLog(#"Token %#", files.nextPageToken);
NSLog(#"Count %d", files.items.count);
}
}];
With shouldFetchNextPages set to YES, the result will not contain a nextPageToken. Instead, assuming you have more than 5 files (based on maxResults) you'll still get the full list, along with a message in the log file that will look something along the lines of:
Executing drive.files.list required fetching 4 pages; use a query with a larger maxResults for faster results
If you set shouldFetchNextPages to NO, the result will be capped at 5 results in this case, and nextPageToken will have a valid token for getting the next page in the result set.