When using extensions in the Graph API:
graphUser = graphClient.Users.Request().AddAsync(graphUser).Result;
OpenTypeExtension newExtension = new OpenTypeExtension()
{
ExtensionName = "CustomName",
AdditionalData = new Dictionary<string, object>
{ { "CustomID", user.CustomID }
}
};
graphClient.Users[graphUser.UserPrincipalName]
.Extensions
.Request()
.AddAsync(newExtension)
.Wait();
I randomly get these errors:
Code: AccessDenied
Message: Access Denied
Sometimes it works, sometimes it doesn't. I can't seem to find a correlation.
When I step trough the code in the debugger it works more often then if I run it without interruption. But if I add a sleep between the lines (to account for processing delay), it doesn't fix the issue.
The application has all the required rights to access the API.
The issue isn't solely in the POST, but also on the GET as illustrated in the code sample below which results in the same error.
User user = graphClient.Users[userName]
.Request()
.GetAsync()
.Result;
user.Extensions = graphClient.Users[userName]
.Extensions
.Request()
.GetAsync()
.Result;
Does anyone have experience with this issue? Thanks in advance!
EDIT:
I figured out that once the errors start showing, the user needs to be deleted. Errors on one user don't necessarily mean errors on another user.
EDIT 2:
I also posted this as an issue on GitHub. Here you can find more information about this problem. It's now labeled as a bug.
It turns out that the User Principal Name is a cached reference.
Since I was running tests, meaning recreating the same test user a lot, the reference UPN was pointing to the old user object resulting in the Access Denied errors.
The issue can be avoided by using the Id of the object, like this:
graphClient.Users[graphUser.Id]
.Extensions
.Request()
.AddAsync(newExtension)
.Wait();
I believe the team is going to fix the reference bug, but I can't speak for them of course. In either case I would recommend using the Id attribute to be sure.
Based on the test, when we create a new user in Azure Active Directory, it seems that there is some delay we can operate for that user. Even the user is returned successfully when I using the Graph to filter the user, it still may failed when I add the extension to that user.
For this issue, I added a line of addition code to make the current thread sleep and then it works.
var userPrincipalName = "userPrincipalName8#adfei.onmicrosoft.com";
var graphUser = new User() { AccountEnabled = true, MailNickname = "MailNickname", UserPrincipalName = userPrincipalName, DisplayName = "userPrincipalName", PasswordProfile = new PasswordProfile() { Password = "islkdifde123!", ForceChangePasswordNextSignIn = false } };
graphUser = graphClient.Users.Request().AddAsync(graphUser).Result;
OpenTypeExtension newExtension = new OpenTypeExtension()
{
ExtensionName = "CustomName",
AdditionalData = new Dictionary<string, object>
{
{ "CustomID", "abc" }
}
};
Thread.Sleep(4000);
graphClient.Users[graphUser.UserPrincipalName]
.Extensions
.Request()
.AddAsync(newExtension)
.Wait();
However the detailed error message for this issue should be code=ResourceNotFound,message=User not found. Please check whether the error is same and this workaround is helpful.
Related
The c# code (below) is what I am testing with. Getting by permissions, etc. Get List Item test is working. There AddAsync method with the following payload in the ListItem object below is getting the invalid argument. The Title, Start Time and End Time are required fields. I am unable to find anything specific on event list date formats for MS graph. I am using the ListItem object but not sure what is the bad argument in it. Any help is appreciated. Please advise. TIA
_scopes = new[] { "https://graph.microsoft.com/.default" };
// using Azure.Identity;
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var clientSecretCredential = new ClientSecretCredential(
_graphSettings.TenantId, _graphSettings.ClientId, _graphSettings.ClientSecret, options);
_graphClient = new GraphServiceClient(clientSecretCredential, _scopes);
var listItem = new ListItem
{
Fields = new FieldValueSet
{
AdditionalData = new Dictionary<string, object>()
{
{"Title", "MS Graph API Test"},
{"Description", "Proof of Concept Test"},
{"Location", "East Club" },
{"Start Time", "2022–06–28T09:00:00" },
{"End Time", "2022–06–28T15:00:00" }
}
}
};
await _graphClient.Sites["{_graphSettings.SharepointSiteId}"].Lists["{_graphSettings.EventListId}"].Items
.Request()
.AddAsync(listItem);
Before trying it programmatically, try working on the Microsoft
Graph Explorer
Please make sure you are giving Microsoft graph api permissions to
write to the sharepoint site before operation.
give Sites.ReadWrite.All Application permission , if it is user make sure Sites.ReadWrite.All delegated permission is given.
Also make sure to grant permsissions for the same.
Check if Content_Type needs to be given in request headers.
try without giving start and end date.
Note:Please recheck with the siteId and ListId
Reference: listitem-create | microsoft docs
I want to get incremental changes from Active Directory using C# and for that I am trying to build a solution as mentioned in the following article (using DirSync Control).
https://learn.microsoft.com/en-us/windows/win32/ad/polling-for-changes-using-the-dirsync-control
However, I am facing following problems:
When using following code, I am getting exception that The user has insufficient access rights. The user is part of administrators group.
What more permission needs to be given to that account? And how?
LdapConnection connection = new LdapConnection("adfs.fed.zzz.com");
connection.SessionOptions.ProtocolVersion = 3;
connection.Credential = new System.Net.NetworkCredential("adfsfed\\username", "password");
connection.AuthType = AuthType.Basic;
connection.Bind();
var filter = "(&(objectClass=*))";
var searchRequest = new SearchRequest("", filter, SearchScope.Subtree, properties);
DirSyncRequestControl dirSyncRC = new DirSyncRequestControl(null, DirectorySynchronizationOptions.None);
searchRequest.Controls.Add(dirSyncRC);
var response = connection.SendRequest(searchRequest) as SearchResponse;
If I am using below code, then I am not getting any exception but getting empty result in cookie.
String[] properties = { "objectGUID", "sAMAccountName", "displayName", "mail", "member" };
String filter = "(|(objectClass=group)(objectClass=user))";
DirectorySearcher directorySearcher = new DirectorySearcher(myLdapConnection, filter, properties);
var dSynch = new DirectorySynchronization(System.DirectoryServices.DirectorySynchronizationOptions.None);
directorySearcher.DirectorySynchronization = dSynch;
directorySearcher.SearchScope = System.DirectoryServices.SearchScope.Subtree;
var results = directorySearcher.FindAll();
var cookie = dSynch.GetDirectorySynchronizationCookie();
Considerations:
I have only one Domain Controller
I am system admin. So, I can assign appropriate permissions to the user.
Please help.
• Your user ID will need the "Replicating Directory Changes" permission and should be a member of ‘Domain Administrators’ group to use the DirSync LDAP control extension. But please note that it pretty much can read anything in the directory partition, regardless of standard permissions. Though they cannot change anything.
However - you may have some attributes that are sensitive in your directory. Please refer the powershell script in the below link and execute it with the user ID after giving appropriate permissions using C#. It is a dirsync code that will retrieve even attributes like ‘userAccountControl, userparameters, msexchuseraccountcontrol, pwdlastset, unicodePwd (BLANK, So no hashed domain password is returned), lockouttime, accountexpires, unixuserpassword(Its Hash is returned).
http://dloder.blogspot.com/2012/01/powershell-dirsync-sample.html
Based on the response given by #KartikBhiwapurkar-MT, I figured out the bug.
The error The user has insufficient access rights is completely misleading (User had already Replicating Directory Changes rights and was part of Domain Administrators group). The error was happening in System.DirectoryServices.Protocols is that I was passing out "" as first parameter (distinguishedName)
new SearchRequest("", filter, SearchScope.Subtree, properties);
but it should have been passed as
new SearchRequest("DC=adfs,DC=fed,DC=zzz,DC=com", filter, SearchScope.Subtree, properties);
I was getting empty cookie in System.DirectoryServices because of bug in latest nuget package (6.0.0). At the time of writing this answer, the bug is still open.
Reference to bug
I get the following error when Updating a user using Microsoft Graph Beta. Permissions should not be an issue as I'm using the following permissions: user.readwrite.all, directory.readwrite.all. Also, HireDate is of type DateTimeOffSet that I'm getting by converting local DateTime to DateTimeOffSet. So, that should not be an issue either. Question: What could be the cause of the error and how can it be fixed?
Error:
Microsoft.Graph.ServiceException
HResult=0x80131500
Message=Code: BadRequest
Message: The request is currently not supported on the targeted entity set
Inner error:
AdditionalData:
date: 2020-08-31T13:59:10
request-id: 4b62576f-6572-414c-b9ef-07ea9a61c101
ClientRequestId: 4b62576f-6572-414c-b9ef-07ea9a61c101
Code:
private async void DataGridUserUpdateButton_Click(object sender, RoutedEventArgs e)
{
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
User user = (sender as Button).DataContext as User;
string id = user.UserPrincipalName;
var user = new User
{
Department = "IT",
DisplayName = "Bob Doe",
HireDate = new DateTime(2020, 8, 31, 2, 30, 0),
JobTitle = "IT Manager"
};
await graphClient.Users[sId]
.Request()
.UpdateAsync(user);
}
According to some test, I met the same issue as yours. I test it in code with both client_credential grant flow and username/password grant flow(and add enough permissions) but none of them succeeded. Then I test it in graph explorer but also failed. It seems the property hireDate can't be updated success.
For a wordaround, I found another property maybe you can use, you can use employeeHireDate. I already test to update this property, it works fine. This property just exists when we use beta graph api and we can't find it neither in v1.0 user properties nor in beta user properties document.
To update employeeHireDate in code, please refer to the code below:
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var user = new User
{
AdditionalData = new Dictionary<string, object>()
{
{"employeeHireDate", "2019-01-01T00:00:00Z"}
}
};
await graphClient.Users["userId"]
.Request()
.UpdateAsync(user);
By the way, you need to pay attention to the properties in beta version because it may be changed in future.
==================================Update==================================
As of now, we can update the hire date(employee hire date) property through Graph API
Patch https://graph.microsoft.com/beta/users/userid
{"employeeHireDate":"2020-01-02T00:00:00Z"}
Please refer to this issue which is already raised in Github and UserVoice
This is the data that is being send by alexa to my skills backend. In the backend code I would like to test if the session is new or not and based on this information I would like to produce a different output. I try to access the session.new, but I don't know how and I could now find anything about it online so far.
const { attributesManager } = handlerInput;
const requestAttributes = attributesManager.getRequestAttributes();
requestAttributes.session.new
//this leads to the error "cannot read property new of undefined"
const { attributesManager } = handlerInput;
const requestAttributes = attributesManager.getSessionAttributes();
sessionAttributes.session.new
//this leads to the same error
I finally found out that this is not possible using the AttributesManager because this only allows access to request, session and permanent attributes. But session.new is not part of those. If you want to check if the Alexa session is new you have to use the so called RequestEnvelopeUtils.
Using those you can access if the session is new or not by using the following statement.
(Alexa.isNewSession(handlerInput.requestEnvelope))
I'm trying to create a user with the DNN 7 services framework. I've taken my working code from my custom registration module and modified to work within a DNN webapi function.
When I get to the UserController.CreateUser call in the code below I receive a
"\"There was an error generating the XML document.\""
exception. My user makes it into the aspnet_Users table and the DNN users table but does not make it into the DNN userportals table. Any ideas would be appreciated.
private void CreateUser()
{
//Update DisplayName to conform to Format
UpdateDisplayName();
User.Membership.Approved = PortalSettings.UserRegistration == (int)Globals.PortalRegistrationType.PublicRegistration;
var user = User;
CreateStatus = UserController.CreateUser(ref user);
I finally found the issue. I was not setting the portal ID for my new users and DNN was excepting out when it was adding them to a portal. All it took was User.PortalId = 0 before the CreateUser call.
I have found by trial and error that the minimum needed to create a viable DNN user is:
UserInfo uiNewUser = new UserInfo();
uiNewUser.Username = "<myUsername>";
uiNewUser.Displayname = "<myDisplayname>";
uiNewUser.Email = "<myUserEmail>";
UserMembership newMembership = new UserMembership(uiNewUser);
newMembership.Password = "<myUserPassword>";
uiNewUser.Membership = newMembership;
uiNewUser.PortalID = <myPortalID>;
DotNetNuke.Security.Membership.UserCreateStatus uStatus;
uStatus = DotNetNuke.Security.Membership.MembershipProvider.Instance().CreateUser(ref uiNewUser);
RoleInfo newRole = RoleController.Instance.GetRoleByName(uiNewUser.PortalID, "Registered Users");
RoleController.Instance.AddUserRole(uiNewUser.PortalID, uiNewUser.UserID, newRole.RoleID, (RoleStatus)1, false, DateTime.MinValue, DateTime.MaxValue);
If any of these are missed out, parts of the user are created in the database, but the user may not be visible in the Admin list of users, or an Exception may be generated. Other details can be added later.