How to get/set custom Azure Active Directory B2C user attributes in ASP.NET MVC? - c#

I have added a custom Organization field as a User Attribute in my Azure Active Directory B2C tenant, like so:
I am using the Microsoft Graph .NET Client Library to manage users in Azure Active Directory B2C and would like to use something similar to the following code to set the user's custom Organization field and the user's built-in Email Addresses field.
await graphClient.Users[user.Id].Request().UpdateAsync(new User()
{
Email Addresses = new StringCollection("myemail#mydomain.com")
Organization = "Microsoft"
});
Two questions:
How do I set a Built-in field, like the Email Addresses?
How do I set a Custom field, like Organization?
This documentation shows how to create a custom attribute but does not tell how to access or use that attribute using the Graph Client.
This documentation shows how to create custom attributes and edit the Relying Party (RP) file.
Is there an easier way? And what is the graphClient code to then get/set these custom user attributes?

It is a bit confusing about whether the Microsoft Graph API, and hence the Microsoft Graph Client, supports the extension properties that are registered with an Azure AD B2C tenant.
When I query a user object using the Azure AD Graph API, then the custom attributes (e.g. "CreatedTime") are returned.
https://graph.windows.net/{tenant}/users/{objectId}
returns:
{
"odata.metadata": "https://graph.windows.net/{tenant}/$metadata#directoryObjects/Microsoft.DirectoryServices.User/#Element",
"odata.type": "Microsoft.DirectoryServices.User",
"objectType": "User",
...
"extension_917ef9adff534c858b0a683b6e6ec0f3_CreatedTime": 1518602039
}
When I query the same object using the Microsoft Graph API, then the custom attributes aren't returned.
https://graph.microsoft.com/v1.0/users/{id}/extensions
returns:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('{id}')/extensions",
"value": []
}
Unless you receive a better answer, then I suggest you use the Azure AD Graph API, and optionally the Azure AD Graph Client, to get and set the extension properties for the Azure AD B2C users.
Examples of getting and setting the extension properties for users can be found at Announcing Azure AD Graph API Client Library 2.0

You are able to do this with the Micorsoft Graph API SDK.
See this example, UserService.CreateUserWithCustomAttribute() https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/master/4-WebApp-your-API/4-2-B2C
To update a custom property:
var updateUser = new User();
updateUser.AdditionalData = new Dictionary<string, object>();
updateUser.AdditionalData["extension_{app id}_{property name}"] = "new value";
var result = await graphClient.Users["{id}"].Request().UpdateAsync(updateUser);
The {app id} in the code above is the id of the app created by default with the name b2c-extensions-app. Do not modify. Used by AADB2C for storing user data. However the "-" are all removed.

In addition to Aaron Hoffman's answer on how to set a custom attribute I use the following snippet to get my attribute:
var graphClient = new GraphServiceClient(authenticationProvider)
{
BaseUrl = "https://graph.microsoft.com/beta"
};
var user = await graphClient
.Users["{id}"]
.Request()
.GetAsync();
var field = user.AdditionalData["extension_{app id}_{property name}"];

So first step is to find in your custom policy:
<TechnicalProfile Id="AAD-Common">...<Item Key="ClientId">57ff56e7-40a0-43fd-a9a3-8d6c1544bcf4a</Item>
Custom attributes are named extension_attributename.
To get it trough graphql you will require it like this extension_{client id of the app NO DASHES responasble for storing extensions }_{attributename}
e.g. extension_57ff56e740a043fda9a38d6c1544bcf4a_mycoolattribute as you can see this is done also in the code:
https://github.com/Azure-Samples/ms-identity-dotnetcore-b2c-account-management/blob/master/src/Helpers/B2cCustomAttributeHelper.cs#L7-L20
example for graph call: https://graph.microsoft.com/v1.0/users/3545c38b-3f6b-4a4b-8820-e7f954a86e1e?$select=extension_57ff56e740a043fda9a38d6c1544bcf4a_mycoolattribute
https://graph.microsoft.com/v1.0/users/{user-objectid}?$select=extension_57ff56e740a043fda9a38d6c1544bcf4a_mycoolattribute,extension_57ff56e740a043fda9a38d6c1544bcf4a_myotherattribute,etc

Related

Add B2B external user to Azure AD without sending invitation email C#

We are using azure b2b for inviting the external users to access our applications in the Tenant. For inviting
For new users, we are sending the b2b invite(using c# Code with customized mail format), upon acceptance users are able to access the application.
For bulk user without sending email to user, there is an option in the azure, i.e to download the excel template and filling the details in the excel with column [sendEmail] values True or False
Now I want to add the user to the azure ad without sending the email using C# code. Can anyone suggest to achieve the requirement?
You could use the Graph in order to create B2B users without invitation.
Reference : https://learn.microsoft.com/en-us/graph/api/resources/invitation?view=graph-rest-1.0
POST https://graph.microsoft.com/v1.0/invitations
{
"invitedUserEmailAddress": "guestuser#sampledomain.com",
"inviteRedirectUrl": "https://sample.com",
"sendInvitationMessage": false,
}
You could probably experiment the same action and see whether it meets your requirement in the graph explorer :
https://developer.microsoft.com/en-us/graph/graph-explorer
Having said that, Now you can use the GRAPH C# SDK in order to achieve your requirement using the above request
Ref:https://learn.microsoft.com/en-us/graph/sdks/sdks-overview
To add a External user without the email using GraphClient using C# would be like below :
public static void CreateB2BUser()
{
try
{
var invitation = new Invitation
{
SendInvitationMessage = false,
InvitedUserEmailAddress = "user#sample.com",
InvitedUserType = "Member",
InviteRedirectUrl = "https://sampledomain.com",
InvitedUserDisplayName = "Sample User",
};
graphClient.Invitations.Request().AddAsync(invitation);
}
catch (ServiceException ex)
{
Console.WriteLine($"Error Creating User : {ex.Message}")
}
}
This article can help you to get a quickstart with the authentication and creation of the GraphClient.

BOX: Add Collaboration to a folder using AppUser user token

I am building an integration between my organization back-end systems and BOX.
One of the scenarios is that when certain event is happening inside my organization there is a need to create a folder in BOX and add collaboration objects to that folder (connect groups to the folder).
I have no problem to create the folder but when trying to create the collaboration I am getting the following error:
Box.V2.Exceptions.BoxException: Bearer realm="Service", error="insufficient_scope", error_description="The request requires higher privileges than provided by the access token."
I am using BOX SDK for .Net to interact with BOX.
The application I created in BOX is assigned to use AppUser User Type and I provided all the scopes that BOX allows me (All scopes except "Manage enterprise" which is disabled).
The code that fails is (C#):
var privateKey = File.ReadAllText(Settings.JwtPrivateKeyFile);
var boxConfig = new BoxConfig(Settings.ClientID, Settings.ClientSecret, Settings.EnterpriseID, privateKey, Settings.JwtPrivateKeyPassword, Settings.JwtPublicKeyID);
var jwt = BoxJWTAuth(boxConfig);
var token = jwt.AdminToken();
var client = jwt.AdminClient(token);
var addRequest = new BoxCollaborationRequest(){
Item = new BoxRequestEntity() {
Id = folderId,
Type = BoxType.folder
},
AccessibleBy = new BoxCollaborationUserRequest(){
Type = BoxType.#group,
Id = groupId
},
Role = "viewer"
};
var api = client.CollaborationsManager;
var task = api.AddCollaborationAsync(addRequest);
task.Wait();
When running this code but replacing the Admin Token with Developer Token generated from the Box Applicaiton Edit Page it works.
Any help is appreciated
OK, I had long discussion with BOX Technical team and here is the conclusion: Using AppUser is not the right choice for my scenario because it is limited only to the folders it creates. There is no way to bypass it.
The solution is:
1. Configure the Application to use standard user
2. Create User with administrative rights that will be used by the API to do activities in BOX. I named this user "API User"
3. Follow the oAuth 2 tutorial to generate access token and refresh token that the API .Net application can use instead of generating token for the AppUser. the oAuth 2 tutorial can be found at https://www.box.com/blog/get-box-access-tokens-in-2-quick-steps/
If the app user is a member of the group(s) you want to be able to access the folder then you shouldn't need to set up a collaboration, the users should just have access.

How to Update Account in StripeApi using C#?

I am trying to update Account in Stripe Api using Stripe.netlibrary ,using StripeAccountService and storing it in StripeAccountclass which i made by myself to store the result returned by API :
var accountService = new StripeAccountService("secretKey in string");
StripeRequestOptions option = new StripeRequestOptions();
option.StripeConnectAccountId = "AccountId to update";
StripeAccount x = accountService.Get(option);
x.Email = "Local#local.com";
//Then i do not know how to save changes back to api now.
But StripeAccountService class has no Update method define. How I can perform update on the Account.
I am using this library. Stripe api does have an update method too here.
Stripe.net does not support managed accounts: "Managed Accounts are a valuable service as well, but they are not available in Stripe.net yet." https://github.com/jaymedavis/stripe.net#stripe-connect
Stripe.net doesnot support Managed account but it can be done using following approach it is for update account.
I won't be able to give code but can provide the correct approach, it is tested.
https://api.stripe.com/v1/account
is the Url for updating stripe account.
Now you need to add two header and a body you can try WebRequest or httpclient class.
The reason i am unable to provide code because i did not do any research in adding multiple headers and a body.
so it would look something like this
Header
Property value
Authorization bearer "SecretKey"
Stripe-Account "acct_16uR8kKN01245679"
Body
Property value
email "test#test.com"
support_phone "555-867-5309"
You can see complete property list here. i picked few for demonstration purpose only.
Then save the response in any variable and it is done.

How to get user name, email, etc. from MobileServiceUser?

After a lot of digging around I've got my WPF application signing users in via Azure Mobile Service. My Mobile Service is connected to an Azure Active Directory that I have set up. However, when I log the user in with MobileServiceClient.LoginAsync(...) the MobileServiceUser UserId is in an unreadable hash it seems. For example it looks like: "Aad:X3pvh6mmo2AgTyHdCA3Hwn6uBy91rXXXXXXXXXX". What exactly is this?
I'd like to grab the user's display name to use but I can't figure out how.
That is the userID of Azure Active Directory. You need to create a service to expose your AAD info through a service and retrieve the additional information using the access token you get from your user.
First:
ServiceUser user = this.User as ServiceUser;
var identities = await user.GetIdentitiesAsync();
var aad = identities.OfType<AzureActiveDirectoryCredentials>().FirstOrDefault();
var aadAccessToken = aad.AccessToken;
var aadObjectId = aad.ObjectId;
This will give you the access token and objectID , then you need to query the information through AAD graphy API.
https://msdn.microsoft.com/library/azure/dn151678.aspx
Look at the sample request part. You should provide the query with the access token you got and objectId.
Here is an alternative approach, after reading http://justazure.com/azure-active-directory-part-2-building-web-applications-azure-ad/ scroll to the section on Identity in .Net it talks how claims are a standard part of the framework. So once you get the credentials object like provided by #beast
var aad = identities.OfType<AzureActiveDirectoryCredentials>().FirstOrDefault();
You can actually grab a dictionary with the various properties. Examples of some the properties can be found at https://msdn.microsoft.com/en-us/library/system.identitymodel.claims.claimtypes(v=vs.110).aspx
So from there you can do the following:
if (aad != null)
{
var d = aad.Claims;
var email = d[ClaimTypes.Email];
}
I did this to pull the user id which was cross referenced in a table. FYI I am using App Service, but I believe the credentials object is the same in Mobile Service

Facebook C# SDK and Access Token

I'd like to be able to authenticate myself (my profile, not just my app) on my own web application using the Facebook C# SDK. Using the Graph API, I can get an access token, but that token does not seem to work properly with the Facebook C# as it seems to be stateless.
The error that is thrown is:
(OAuthException) An active access token must be used to query information about the current user.
I've poked around the Facebook C# SDK and documentation and most of the info I'm seeing is to redirect users to a login page which is not what I'm looking for.
Does anyone have a good sample of auto-logging in myself so I can pull up my own information?
TIA
When you say "yourself" do you mean the app or your actual facebook user?
If it's just your app, you can get an access token by POSTing to this URL:
https://graph.facebook.com/oauth/access_token?grant_type=client_credentials&client_id=APP_ID_HERE&client_secret=APP_SECRET_HERE
You can use this access token to perform actions on behalf of your users if they have authorized your app to do so.
I had the same problem where the access token didn't include the session part. Please check out my answer to this similar question - exchange code for token facebook-c#-sdk.
Here's a sample from my Home controller
[CanvasAuthorize]
public ActionResult Index()
{
var app = new FacebookClient(new Authorizer().Session.AccessToken);
dynamic me = app.Get("me");
ViewBag.Firstname = me.first_name;
ViewBag.Lastname = me.last_name;
return View();
}
Edit
Now I understand the question better. What about this?
var auth = new Authorizer(FacebookContext.Current.AppId, FacebookContext.Current.AppSecret, HttpContext);
auth.Authorize();
From the documentation:
public bool Authorize()
Member of Facebook.Web.Authorizer
Summary:
Authorizes the user if the user is not logged in or the application does not have all the sepcified permissions.
Returns:
Return true if the user is authenticated and the application has all the specified permissions.
I dont know if this will work for you:
using Facebook.Web;
using Facebook;
using System.Dynamic;
var auth = new CanvasAuthorizer { Permissions = new[] { "user_about_me"} };
if (auth.Authorize())
{
}
and include this in the aspx:
<input type="hidden" name="signed_request" value="<%: Request.Params["signed_request"]%>"/>
good luck !!

Categories