Access 'PasswordNeverExpires' property in Azure AD via C# - azure-ad-graph-api

I have the below code C# which works great for querying Azure AD but I need to also read in the property 'PasswordNeverExpires' as shown in the below screenshot. I cannot see the property on the full MS list here - https://learn.microsoft.com/en-us/graph/api/resources/user?view=graph-rest-1.0 - only a 'passwordPolicies' property which returns "DisablePasswordExpiration" for all our users which doesn't tally up with the results shown in AD manager. I can see plenty of powershell scripts, for example here - https://serverfault.com/questions/730189/powershell-find-all-users-with-password-never-expires - which mention a 'passwordNeverExpires' property but this only appears blank when I run my C# script.
string Url = $"{config.ApiUrl}v1.0/users?$select=userPrincipalName,lastPasswordChangeDateTime,PasswordNeverExpires,passwordNeverExpires";
do {
string JSON = await apiCaller.CallWebApiAndProcessResultASync(Url, result.AccessToken, Display);
Url = AADR.OdataNextLink;
} while (AADR.OdataNextLink != null);

The powershell scripts you found in this post is for AD rather than AAD. So it doesn't work for AAD. There is not a property named PasswordNeverExpires in AAD Module.
PowerShell Script:
You can use the following PowerShell cmdlet to see if a single user's password is set to never expire (reference here):
Get-AzureADUser -ObjectId <user id or UPN> | Select-Object UserprincipalName,#{
N="PasswordNeverExpires";E={$_.PasswordPolicies -contains "DisablePasswordExpiration"}
}
The cmdlet aliases PasswordPolicies -contains "DisablePasswordExpiration" to a new property PasswordNeverExpires.
To see the Password never expires setting for all users, run the following cmdlet:
Get-AzureADUser -All $true | Select-Object UserprincipalName,#{
N="PasswordNeverExpires";E={$_.PasswordPolicies -contains "DisablePasswordExpiration"}
}
Microsoft Graph:
Since there is no PasswordNeverExpires property in MS Graph user resource type, you should just query the passwordPolicies property using MS Graph.
GET https://graph.microsoft.com/v1.0/users?$select=userPrincipalName,lastPasswordChangeDateTime,passwordPolicies
Then you will get "passwordPolicies": "DisablePasswordExpiration" in the response. Use your own code logic to handle it (define a PasswordNeverExpires and set it to true).

Related

Request_UnsupportedQuery while trying to get list of specific users

I'm using PowerShell to connect to Azure AD. I need to get a list of specific users whose accounts are not in a particular team.
To enter my tenant, I used cmdlet Connect-AzureAD. To get users I have to use the cmdlet Get-AzureADUser. I'm using -Filter along with it to get a list of those specific users.
I'm using a cmdlet like this:
Get-AzureADUser -Filter "Team ne 'Development' "
But I'm getting an error like this:
Get-AzureADUser : Error occured while executing GetUsers
Code: Request_UnsupportedQuery
HttpStatusCode : BadRequest
HttpStatusDescription: BadRequest
HttpResponseStatus: Completed
What am I doing wrong? Can anyone help me out
I tested in my environment. I also got same error.
This error usually occurs because depending on PowerShell version, Get-AzureADUser won’t support ne(not equal to) operator and Team attribute with Filter statement.
Instead of Team attribute, you can make use of Department.
Only the following operators are supported by Get-AzureADUser filter parameter based on version.
eq - equals to
and - including both
or - either first or second
startswith - String starts with
To filter the list of users by eq operator worked.
Get-AzureADUser -Filter "Department eq 'IT"
The output will be like this:
Please check below workarounds if they are helpful.
You can try using and operator by including all departments other than "Development".
Otherwise, you can update the versions and try again.

Powershell Set-ADUser userCertificate parameter type error

I have a script, which essentially does the following:
$user = Get-ADUser $someUserName -Server $someCertServer -Properties *
$user.userCertificate |% { Set-ADUser $someUserName -Certificates #{Add=$_} }
It copies the cert data from a cert-server to the default server. $user.userCertificate is of type Microsoft.ActiveDirectory.Management.ADPropertyValueCollection and $user.userCertificate[0] is of type System.Byte[]. According to the docs, I can pass a Byte[] and be good to go. By using the foreach operator in the above script, I get the Byte[].
However, Powershell fails with the error message
the parameter certificates requires all values in the collection to be of the same type
(and underlines the #{Add=$_}; the message might not be 100% accurate, since I had to translate it to English). Because of the foreach operator, there is only one type: a Byte[]. What does that error message mean and how can I shove the certificate into the ADUser object?
I also tried to convert the Byte[] to a certificate object, however it ended up with the same error message:
$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($user.userCertificate[0])
Set-ADUser $someUserName -Certificates #{Add=$cert}
The very first issue I see is that you are calling on the wrong property for your example to work.
$user.userCertificate | ForEach-Object { Set-ADUser $someUserName -Certificates #{Add=$_}}
While there is a property called userCertificate on that object that contains an collection of [byte[]]. For that code to work the way you want it to you should be using Certificates. Certificates is an collection of Security.Cryptography.X509Certificates.X509Certificate
So making that change I was able to add another users certificate to my own account.
$certUser = Get-Aduser "someGuy" -Properties certificates
$certUser.Certificates | %{ Set-ADUser "ME" -Certificates #{Add=$_}}
Note: It is a better practice to only request the properties you need from AD. Using -properties * is a waste of effort and needless resources
While this exact scenario is not covered there is a nice write-up on the MSDN Blogs about dealing with certs.
Cert as a byte array
Now that we know userCertificate is a collection of byte arrays maybe we can look into how to use that.
I was having issues using the byte array with the certificate parameter for Set-Aduser even though it is supposed to support it. I got the error
Set-ADUser : Cannot validate argument on parameter 'Certificates'. Values in the argument collection should be of Type: 'System.Security.Cryptography.X509Certificates.X509Certificate'
I did get this to work but I had to cast the byte array as a cert object first which was redundant considering this appear to be what the Certificates property already is.
$certUser.Usercertificate | ForEach-Object{
Set-ADUser "ME" -certificate #{Add=[System.Security.Cryptography.X509Certificates.X509Certificate]$_}
}

Create AD Object - Not Exchange

I am currently trying to create an Active Directory contact object in a specific OU in our Active Directory. I am not looking at using Exchange PowerShell. I would like to do this via normal PowerShell directly in to AD.
I have looked online and found that I can create a contact using the below command, this creates it in a specific OU.
New-ADObject -Name SaraDavisSGTContact3 -Type contact -Path "OU=SGTestOU,OU=Contacts,DC=example,DC=Example,DC=local"
How would I also get it to add other attributes such as mail (email address), first name, surname, etc.? I tried -Mail example.com, etc., but this didn't work.
Please bear in mind I will eventually try and get this to read from a CSV to do in bulk, so the simplier the code the better.
Use the -OtherAttributes Parameter to add additional attributes.
See New-ADObject MSDN Documentation
New-ADObject -name SaraDavisSGTContact3 -Type Contact -path "OU=SGTestOU,OU=Contacts,DC=example,DC=Example,DC=local" -OtherAttributes #{
'mail'="sara#gmail.com";
'proxyAddresses'="sara#gmail.com";
'givenName'="Sara";
'sn'="Davis";
'displayname'="Sara Davis"
}

How to get LDAP displayname and email id using Msbuild?

I got communitytasks to send mail. But in subject itself if i add display name of LDAP user, I would know who is taking build.
Following Code in Powershell would give me mail id and displayname
$searcher = [adsisearcher]"(samaccountname=$env:USERNAME)"
$mailid= $searcher.FindOne().Properties.mail
$DispName= $searcher.FindOne().Properties.displayname
Is there any way to get mail id and displayname in Msbuild or is it better to call powershell commands through inline task?
In MSBuild you can refer to environment variables as if they were defined properties, so taking the name of the user is as simple as writing $(USERNAME).

Powershell: Setting PsCredentials to $Null for username and $Null for password

How can I create a $Null username and $Null password PScredentials object?
According to this article, the null PSCredential causes Powershell to use Windows Authentication, which seems a much easier way to run scripts in a domain setting. Unfortunatelly I cant seem to figure out where/how he's setting it to Null:
http://blogs.msdn.com/b/dvespa/archive/2010/02/22/how-to-use-windows-authentication-with-the-pscredential-class.aspx
Other resources:
This answer specified $Null for password, but wont allow $Null username.
Create PSCredential without a password
Thank you.
Why do you need a $null PSCredential object ?
According to the documentation
-Credential <PSCredential>
Specifies a user account that has permission to perform this action. The default is the current user.
It means tha if you just don't use this parameter you will use Windows Authentication.
Edited :
So in Powershell if you want a null credential you just have to specify it :
test :
Get-WmiObject Win32_Process -Credential
Get-WmiObject Win32_Process -Credential $null
and
Get-WmiObject Win32_Process -Credential (Get-Credential)
The constant [PSCredential]::Empty (aka [System.Management.Automation.PSCredential]::Empty) gives you a valid object of type PSCredential but with both username and password set to null.
However, that is not the current user's credentials; rather it means "no credentials". There may be logic in the function you're calling for this to be a moot point (i.e. where the function's the logic says to use the current security context when $credentials -eq [PSCredential]::Empty), but in some contexts this same value may be used for other purposes (e.g. to say you want to use anonymous authentication).
You cannot get the current user's credentials without prompting for them or explicitly assigning them in some other way; otherwise this would present a security risk
#create a credential object for demo purposes.
#Imagine that instead of this line we were saying `$credential = Get-CurrentUserCredential`
#(you have to imagine this, since no such function exists).
$credential = [PSCredential]::new('myUsername', ('superSecretPassword' | ConvertTo-SecureString -AsPlainText -Force))
#we can now see this user's password;
#someone malicious could have this script run under the current user's
#profile & have this information reported back to them.
$credential.GetNetworkCredential().Password
If you want to run something as the current user, you already are (i.e. hence them being the current user); so you don't need to get their credentials.
That said, there are cases where it would be nice to have their credentials; e.g. if accessing a resource which doesn't use the current user context / needs explicit credentials. In such cases you have to either prompt for credentials (Get-Credential $env:username), or read them from some resource (see https://stackoverflow.com/a/6240319/361842).
There's a really thorough explanation of credentials here: http://duffney.io/AddCredentialsToPowerShellFunctions; definitely worth a read.