Updating federated user's adb2c UserPrincipalName via Graph API - azure-ad-b2c

We are allowing External Azure AD users to signup and login to our application via a custom policy. This creates a shell user in our azure ad org and we use the user's email address under user profile, not the user's UPN from the external AD. If the user's email address is different from their UPN, the shell user in our adb2c org will have the email address as the UPN. We customized the custom policy to return the user attributes from the external AD together with the user attributes from the shell user in adb2c. Our application will detect if there is a change in the name or email address and will update adb2c shell user via Microsoft Graph.
When the user's email address changes, I want to update the shell user in our adb2c org. Since the email address is used as the UPN, how can I update my federated users userPrincipalName in our adb2c shell user via Graph API?
var identities = graphUser.Identities.Select(o => new ObjectIdentity
{
SignInType = o.SignInType,
Issuer = o.Issuer,
IssuerAssignedId = o.IssuerAssignedId,
ODataType = o.ODataType,
AdditionalData = o.AdditionalData
}).ToList();
var federatedIdentity = identities.FirstOrDefault(i => i.SignInType == "federated");
Both of these wont work:
federatedIdentity.IssuerAssignedId = "mynameuser#federatedAAD.org";
or
var updatedUser = new User
{
//other user attributes here
UserPrincipalName = "mynameuser#federatedAAD.org";
};
await _graphServiceClient.Users[idpId]
.Request()
.UpdateAsync(updatedUser);
Thanks in advance!

• You can update the external user identity or shell user identity in Azure AD B2C using Microsoft graph API through the HTTP response interface by using the below commands: -
‘ PATCH https://graph.microsoft.com/v1.0/users/{object id}
{"userPrincipalName":"jdoe#abc.com"} ‘
Where instead of the “jdoe#abc.com”, enter the user principal name of the already created Azure AD B2C shell user or federated user that logs in to Azure AD B2C. Since, the user identity is already created when the user logs in for the first time to use the application created, it needs to update the existing user principal name only which can be done through the above command.
• Also, Microsoft Graph seems not to allow to set userPrincipalName when creating the user for Azure B2C. It will generate the userPrincipalName as {object id}#abc.com. And then you could update the userPrincipalName. Thus, your second command script to create or update the shell user’s UPN didn’t work. As well as ensure to add the federated domain as a verified domain in Azure AD B2C for the above command and options to succeed.
Please refer the below links for more information: -
Pre-Create Federated Users in Azure B2C Using Graph
https://learn.microsoft.com/en-us/graph/api/user-update?view=graph-rest-1.0&tabs=http

Related

Change Azure B2C account password on behalf of a user

I'm trying to change the password of a user created in my Azure B2C Tenant. I'm using Microsoft.Graph C# SDK to do API calls.
First I create GraphServiceClient by providing details of my tenant:
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var clientSecretCredential = new ClientSecretCredential("tenantId", "clientId", "clientSecret", options);
_client = new GraphServiceClient(clientSecretCredential);
Then I use the built-in method of a client to change the user's password:
await _client.Users["userId"].ChangePassword(currentPassword, newPassword).Request().PostAsync();
But I get following error:
Microsoft.Graph.ServiceException: Code: Authorization_RequestDenied
Message: Access to change password operation is denied.
Is it possible to change the password on behalf of a user? I found conflicting information on this topic on the internet. If this is impossible, what is the valid approach to do this?
I have a SPA frontend app in which the user is authenticated with redirection flow. The access token is then passed to my backend to authorize the requests. Maybe I can use this token to somehow access MS Graph API and change the password?
Note: I would like to let users change their passwords without leaving my SPA application.
I tried in my environment and got below results:
Initially I tried with your code and got same error:
According to MS-DOCS change password we need Directory.AccessAsUser.All permission and it only supported for delegated (Work or school accounts).
Trying to reset the password in the B2C tenant using the Graph API its is not possible Unfortunately, because there is no Directory.AccessAsUser.All, B2C tenant does not allow this type of password reset. For B2C tenants, the Graph API includes the permission. Only offline access and openID are available as delegated rights in the B2C tenant.
You can reset the password in B2C tenant are either admin performing password reset via Azure Portal or by using Password Reset Policy and also refer this MS-Q&A for updating password in powershell and postman.
Reference:
"Upn from claims with value null is not a valid upn." - Microsoft Q&A by amanpreetsingh-msft.

Azure Graph API can't create localaccount without domain in userPrincipalAccount

I am creating users using the Azure Graph API (using Microsoft.Graph;), and I am seeing issues when I try to add local account users. I want to be able to create an account where the user can log in with a username, such as "jimmy" and not have to specify a domain. I am able to do this with the Azure Portal, but not with Graph API.
When I add users through Graph API, the issue is with the userPrincipalName. I must include a userPrincipalName, and userPrincipalName must include a domain. Conversely, when I create a user account with Azure Portal, I do not specify a userPrincipalName, and the userPrincipalName is created automatically with the format being objectid#mydomain.onmicrosoft.com.
In summary, I want to be able to use the graph API to create a user who can log in as "Jimmy" as I can with the Azure Portal, but I am only able to create a user who can log in as jimmy#mydomain.onmicrosoft.com.
You could generate a GUID and set the UPN to "guid#domain.onmicrosoft.com"? If that's what the portal does, shouldn't it be fine for your app too? If you specify an identity for the user with the username type, they should be able to log in with that.
So you can set the user's identities to something like:
{
"identities": [{
"signInType": "userName",
"issuer": "mydomain.onmicrosoft.com",
"issuerAssignedId": "jimmy"
}]
}
And the UPN can be the generated one with the GUID.
Reference: https://learn.microsoft.com/en-us/graph/api/resources/objectidentity?view=graph-rest-1.0

Custom claim missing from saml response with Azure AD

I am using Azure AD as identity provider for Okta, with SAML2 protocol. I am able to login just fine. However, I want to send the user's phonenumber from Azure AD to Okta, but Im having problems.
I tried following this guide to add a custom claim, and I added one with these values:
Name: mobilePhone
Value: user.telephonenumber (the only one related to phonenumber I could find)
Namespace: http://schemas.xmlsoap.org/ws/2005/05/identity/claims
I have also added my phonenumber on my profile (Home > Company > Users - All Users > Me - profile) in Azure Active Directory. However, when I login and check the SAML response using my extension, the claim for mobilePhone is nowhere to be found. Why is it missing? Chances are I added my phonenumber on the wrong places, but shouldnt there be an empty claim somewhere?

Error when obtaining token

I'm trying the sample code NativeClient-Headless-DotNet.sln against my B2C tenant.
When I attempt to execute the command:
result = authContext.AcquireTokenAsync(todoListResourceId, clientId, uc).Result;
using an existing username and password, I get this exception:
InnerException = {"unknown_user_type: Unknown User Type"}
As far as I know, I've set-up all the values correctly in Web and App config (I'm using the same values that I use in my Graph API project, which works OK).
Any ideas why this should happen?
Are accounts created with:
userType.type = "userName";
found by this method?
Currently, Azure AD B2C doesn't have any direct support for this.
However, work to support for the Resource Owner Password Credentials flow in Azure AD B2C is in-progress.
This new feature will enable a desktop application to collect a user credential and POST it to the B2C tenant for validation.

Grant an existing B2C app access to graph API

I have an existing B2C app that I want to give graph access to.
I set this up previously but now want to replicate it but everything i can find is for new apps. I ysed the older graph but i think the article I used has been moved as everything is talking about the new Graph api
Is there a specific article for this, also if anyone has seen an article that describes the process from moving from Azure graph to Microsoft Graph (the new version) for a B2C app that would be great
Thanks
Register the application for the Graph API
In addition to registering the application in the B2C directory,
we must also create an application registration for the graph API.
The three key/id values you will need are the tenantId, ObjectId,
and AppPrincipalId.
To get the tenantId, log into the azure ad b2c directory in the new portal.
https://portal.azure.com/
Be sure you have the correct directory selected after you login
(top right corner).
Click on the help button (a question mark inside a circle) near the
top right corner of the page. In the menu that appears, click the
"Show diagnostics" option. This will display a JSON formatted output in
a new popup/window. Look for the "tenants" array and find the entry
with the display name of the directory you wish to register with the
application. The "id" attribute of that entry is the tenantId.
Example:
{
"clientSessionStartDate": {
//stuff will be here ...
},
//
// more shtuff you don't care about will be here ...
//
"tenants": [
{
"id": "SomeUUIDwithlike36charactersSometime",
"domainName": "yourtenantname.onmicrosoft.com",
"displayName": "displanynameoftenant",
"isSignedInTenant": true
},
// ... snippity lemon
]
// ... snip some more
}
You will also need a unique application Secret and AppPrincipalId to be
generated for the new application.
Also, to set the correct permissions for the application, you will need
its "ObjectId".
The process for registering the application and generating those values
is more complicated, and requires a special module for PowerShell
and the online login module to be downloaded and installed.
Also, be sure you have the latest version of PowerShell installed for
your system, or you will not be able to use the azure module.
Sign-In assistant: https://www.microsoft.com/en-us/download/details.aspx?id=41950
Azure AD PowerShell Module: http://go.microsoft.com/fwlink/p/?linkid=236297
Create the application registration with PowerShell
This next section is an almost verbatim copy-paste fo the documentation.
https://azure.microsoft.com/en-us/documentation/articles/active-directory-b2c-devquickstarts-graph-dotnet/
After you install the PowerShell module, open PowerShell and connect to
your B2C tenant.
> $msolcred = Get-Credential
After you run Get-Credential, you will be prompted for
a user name and password, Enter the user name and password
of your B2C tenant administrator account.
> Connect-MsolService -credential $msolcred
Before you create your application, you need to generate a new client
secret. Your application will use the client secret to authenticate to
Azure AD and to acquire access tokens. You can generate a valid secret
in PowerShell:
> $bytes = New-Object Byte[] 32
> $rand = [System.Security.Cryptography.RandomNumberGenerator]::Create()
> $rand.GetBytes($bytes)
> $rand.Dispose()
> $newClientSecret = [System.Convert]::ToBase64String($bytes)
> $newClientSecret
The final command should print your new client secret. Copy it somewhere safe. You'll need it later. Now you can create your application by providing the new client secret as a credential for the app:
> New-MsolServicePrincipal -DisplayName "My New B2C Graph API App" -Type password -Value $newClientSecret
Example output:
DisplayName : My New B2C Graph API App
ServicePrincipalNames : {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
ObjectId : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
AppPrincipalId : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
TrustedForDelegation : False
AccountEnabled : True
Addresses : {}
KeyType : Password
KeyId : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
StartDate : 1/1/2017 1:33:09 AM
EndDate : 1/1/2017 1:33:09 AM
Usage : Verify
If you successfully create the application, it should print out
properties of the application like the ones above, but with a mix of alpha-numeric characters. You'll need both
ObjectId and AppPrincipalId, so copy those values, too.
You will also need the tenant ID of the B2C directory.
After you create an application in your B2C tenant, you need to assign
it the permissions it needs to perform user CRUD operations. Assign the
application three roles: directory readers (to read users), directory
writers (to create and update users), and a user account administrator
(to delete users). These roles have well-known identifiers, so you can
replace the -RoleMemberObjectId parameter with ObjectId from above and
run the following commands. To see the list of all directory roles,
try running Get-MsolRole.
> Add-MsolRoleMember -RoleObjectId 88d8e3e3-8f55-4a1e-953a-9b9898b8876b -RoleMemberObjectId <Your-ObjectId> -RoleMemberType servicePrincipal
> Add-MsolRoleMember -RoleObjectId 9360feb5-f418-4baa-8175-e2a00bac4301 -RoleMemberObjectId <Your-ObjectId> -RoleMemberType servicePrincipal
> Add-MsolRoleMember -RoleObjectId fe930be7-5e62-47db-91af-98c3a49a38b1 -RoleMemberObjectId <Your-ObjectId> -RoleMemberType servicePrincipal
You now have an application that has permission to create, read,
update, and delete users from your B2C tenant.
I totally forgot this great answer exists and this is how you do it
Authorize By Group in Azure Active Directory B2C

Resources