BOX: Add Collaboration to a folder using AppUser user token - c#

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.

Related

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

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

How to pass credentials to use ResourceManagementClient to get all resources from azure resource group c#?

I have install nuget Microsoft.Azure.Management.ResourceManager and have following code to get all existing resources based on Resource Group Name
var resouceManagementClient = new ResourceManagementClient(credentials) { SubscriptionId = "mySubscriptionId" };
var listResources =
resouceManagementClient.ResourceGroups.ListResources("Demo-ResourceGroup");
I'm not sure from where I can get credentials parameter value.
I do not have Azure Active Directory access , I think its must , can
we bypass azure AD?.
In my azure portal I have create a Resource Group - Demo-ResourceGroup
and have many resources created.
I want only list of all existing resources using c# code.
One way is by grabbing an access token from Azure AD and passing it in to a TokenCredentials class.
var authContext = new AuthenticationContext(string.Format("https://login.windows.net/{0}", tenantId));
var credential = new ClientCredential(applicationId, password);
AuthenticationResult token = authContext.AcquireTokenAsync("https://management.core.windows.net/", credential).Result;
var credentials = new TokenCredentials(token.AccessToken);
The set of credentials you use to request the acces token (in this case clientId/secret) will determine whether the application has the appropriate rights to enumerate the resources. This is a good MS docs page on how to register your application with AAD. In the example above, applicationId and password come from the application registration in AAD
Microsoft has a page describing other ways you can get tokens from AAD.

Enroll new user in 2-Step verification through the Google API

We are using Google API to create new google accounts (users and their emails).
New requirement is that we should support 2-Step authentication enabled in admin.google.com (for sub-organization) and we need to enforce the rule.
Now comes the problem: If we create new user in this sub-org it will try to enforce 2-Step authentication and, as it is not setup, user will not be able to login to set it up. And admin cannot setup 2-step verification for the user.
Even more... I need to be able to setup users 2-step verification through the API.
Does workaround for this exist, or does anyone have any idea how to do it?
Any suggestions are welcome,
thanks
UPDATE 1
Thanks to Jay Lee's answer I am expanding a bit with working C# code using Google.Apis.Admin.Directory.directory_v1 SDK
private string GenerateVerificationCode(string userKey)
{
var _service = new DirectoryService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = _applicationName,
});
var generateVerificationCodesRequest = _service.VerificationCodes.Generate(userKey);
generateVerificationCodesRequest.Execute();
var verificationCodesRequest = _service.VerificationCodes.List(userKey);
var verificationCodes = verificationCodesRequest.Execute();
var verificationCode = verificationCodes.Items[0].VerificationCodeValue;
return verificationCode;
}
You can:
Make sure user is created in an OU where 2SV is forced. Set the orgUnitPath attribute when calling users.create()
Call VerificationCodes.generate() for the new user to create backup codes to get backup 2SV codes for the user.
Share the backup codes with the new user along with their password and instructions for first login and setup of 2SV.
User will be able to pass 2SV with the backup codes for first login. Then they can setup normal 2SV via SMS or app. You'll want to provide new users with a good set of detailed instructions for this process as it does complicate onboarding but it means they are secure on day one.

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

Google Apis v3 in ASP.Net - "Unauthorized client or scope in request"

Maybe I am simply not getting "it", with "it" being the overall setup needed to make this work.
I have a website that scrapes other sites for sporting events. I want to automatically create Google Calendar events from the results, so I want to give my Web Application Read/Write access on a Calendar in my GMail account.
I have been trying to wrap my head around this for a week now, but I can't get it to work and it is crushing my self-esteem as a developer.
The way I "understand" it is that I need a Google API v3 Service Account, because I don't need an API key for a particular user. Or do I need a Simple API key (instead of oAuth)?
Anyways, I went with the Service Account.
In my HomeController I am trying to GET a Calendar so I know it all works.
public void Calendar()
{
string serviceAccountEmail = "...#developer.gserviceaccount.com";
var certificate = new X509Certificate2(
Server.MapPath("~") + #"\App_Data\key.p12",
"notasecret",
X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential =
new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[]
{
CalendarService.Scope.Calendar
},
User = "MY-GMAIL-EMAIL" // Is this correct?
}
.FromCertificate(certificate));
BaseClientService.Initializer initializer = new BaseClientService.Initializer();
initializer.HttpClientInitializer = credential;
initializer.ApplicationName = "CALENDAR NAME"; // Correct?
var service = new CalendarService(initializer);
var list = service.CalendarList.List().Execute().Items; // Exception :-(
}
The error I am getting:
An exception of type 'Google.Apis.Auth.OAuth2.Responses.TokenResponseException' occurred in Google.Apis.dll but was not handled in user code
Additional information: Error:"unauthorized_client", Description:"Unauthorized client or scope in request.", Uri:""
So I tried a bunch of things in Google Calendar, like making it public, adding the service account email as a READ/WRITE user.
What do I need to do to authorize my Web Application so it can create events on my behalf?
I have done this with the service account in a similar post. I changed a bit of my code and got it working to list my calendars by switching a few things around. I can create events as well. I didn't add a user as you have done in the initializer, and under application name, it is the name of the application in the dev console. Make sure you name your application. Make sure your service account is shared with your account.
I slightly changed the list part of your code to this in mine and got back the my list of calendars.
var list = service.CalendarList.List();
var listex = list.Execute();
Check out my example at Google API Calender v3 Event Insert via Service Account using Asp.Net MVC

Categories