Create user using Microsoft Graph - c#

How do I create a user using Microsoft graph? For I am having issues with regards to permission failures during a save.
I do have few questions in mind.
Where will the user be created by calling create user API in graph ? Is it in Azure AD or somewhere else ?
I tried calling create user api by passing json and required headers, below is the error I get
Where exactly do I need to set the permission, I have already added permissions in the Application Registration Portal
But when API is executed it shows that I don't have enough permission.
FYI, I have registered the app using the same email id that I am using to test the APIs here https://developer.microsoft.com/en-us/graph/graph-explorer#
If I am not the admin, where exactly do I need to set or request for it ?

In order to create a User via Microsoft Graph, you need to request either Directory.ReadWrite.All or Directory.AccessAsUser.All permission.
Important: Directory.ReadWrite.All and Directory.AccessAsUser.All both require Admin Consent before you can use them. If you're using Graph Explorer then the URI you need to provide your tenant Admin will be generated for you. If you're doing this in your own application, you'll need to construct an Admin Consent URI yourself. You can find more details on this at v2 Endpoint & Admin Consent.
Once you have the proper permissions configured (and consented), you'll want to POST the following JSON body/payload to https://graph.microsoft.com/v1.0/users:
{
"accountEnabled": true,
"displayName": "displayName-value",
"mailNickname": "mailNickname-value",
"userPrincipalName": "upn-value#tenant-name.onmicrosoft.com",
"passwordProfile" : {
"forceChangePasswordNextSignIn": true,
"password": "password-value"
}
}
This will create a user with a temporary password. The user will be asked to set a new password as after as they authenticate for the first time.

Where will the user be created by calling create user API in graph ?
Is it in Azure AD or somewhere else ?
Yes, the user created is in the Azure AD.
I tried calling create user api by passing json and required headers,
below is the error I get
For your error, have you added the request body like the following, and this required admin:
Where exactly do I need to set the permission, I have already added
permissions in the Application Registration Portal
The required permissions to create application:
For the details, please read here.

Related

How should I handle in-app permissions with Azure AD SSO?

First project working with both single sign on and Azure, so maybe I'm just not doing it correctly. Before using SSO, I would generate the token myself. This allowed me to put whatever I wanted inside of the token, which I would use to determine permissions. Using react-adal with Azure AD SSO, the token is generated client side and all I get is the user identity. Following what I did in the past, I wrote a custom attribute to ensure the user has the appropriate permissions for the API call. But rather than just pulling the information from the token that is passed with every request, I have to query the permissions every time they make a request, essentially doubling the database hits.
Is there a way for me to handle roles/permissions (admin, manager, user, read-only, etc) using single sign on and application driven permissions without querying the database every time I need to check permissions?
Previous process:
User visits site > enters credentials > server authenticates, gets permissions, generates token with permissions, returns it to client > client passes token on every request > server validates and parses token > attribute checks parsed token to ensure user has necessary permission > completes request
Current process: User visits site > client authenticates with Azure AD and gets token > client passes token on every request > server gets authentication information from token > server queries database to get users permissions > attribute checks query results to ensure user has necessary permission > completes request
How can I make the current process better? Every google result I've found has only covered authentication and hasn't gone deep enough into the actual application for me to find a "best practice" or even any practice. Am I just doing it wrong?
Please take a look at the Application Roles related functionality with Azure AD to implement your custom RBAC. It should provide a good starting point for what you've mentioned, as roles collection will be available for you as part of incoming tokens from Azure AD.
Application Roles
Microsoft Documentation - Application Roles
Purpose - These roles are defined in the Application Manifest for an application that your organization is developing and that is registered in your Azure Active Directory. These roles are very specific to your application and can be used in application's code to implement Authorization logic for the authenticated users.
Sample Application (that uses this concept and does what you're looking for) -
Authorization in a web app using Azure AD application roles & role claims
Quick Explanation
1) Once you register your application with Azure AD, you can define custom roles (specific to your application) by editing the application manifest (JSON) in Azure AD.
Here's a sample JSON of what application role definition would look like:
"appRoles":
[
{
"allowedMemberTypes": [
"User"
],
"description": "Creators can create Surveys",
"displayName": "SurveyCreator",
"id": "1b4f816e-5eaf-48b9-8613-7923830595ad",
"isEnabled": true,
"value": "SurveyCreator"
},
{
"allowedMemberTypes": [
"User"
],
"description": "Administrators can manage the Surveys in their tenant",
"displayName": "SurveyAdmin",
"id": "c20e145e-5459-4a6c-a074-b942bbd4cfe1",
"isEnabled": true,
"value": "SurveyAdmin"
}
]
2) You will be able to assign these roles to Users/Groups/applications through Azure Portal or programmatically. (you could control the allowed member types for roles)
3) Now when the end users sign in to your application, the incoming Azure AD token will provide you a collection of role claims (based on whatever roles are assigned to the user) and you can take authorization decisions in your application.
if (context.User.HasClaim(ClaimTypes.Role, "Admin")) { ... }
Here is another related documentation on Microsoft Docs - Role-based and resource-based authorization
I see you have also tagged asp.net-core in your question. So if you're working with ASP.NET core application, you could possibly make use of policies as shown in Role-based authorization section of the link above.
public class SurveyCreatorRequirement : AuthorizationHandler<SurveyCreatorRequirement>, IAuthorizationRequirement
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, SurveyCreatorRequirement requirement)
{
if (context.User.HasClaim(ClaimTypes.Role, Roles.SurveyAdmin) ||
context.User.HasClaim(ClaimTypes.Role, Roles.SurveyCreator))
{
context.Succeed(requirement);
}
return Task.FromResult(0);
}
}
On a side note, I've seen cases where people chose to do some authorization logic based on which groups the users belonged to. This is just information and not something you need to do. I'm sharing some details for both, Roles and Groups in this answer, but definitely look at Application Roles first. You could even use a combination of both Roles and Groups for your Authorization strategy.
Groups
Groups can have multiple users or other groups as members. Again management of groups is possible through Azure Portal or programmatically.
NOTE: Groups are totally independent of your application, i.e. Azure AD groups can and do exist to serve a purpose of grouping members even without your application. Application Roles on the other hand are very specific to your application, they don't mean much to anyone except your application.
Sample app which makes decisions based on Groups
Authorization in a web app using Azure AD groups & group claims
Individual or Specific resource based authorization
Also know that when it gets to individual resource based authorization (and not a more generic role based authorization), then AFAIK you will need to go to your database or other persistent storage anyway because that's the only place which knows about a detailed mapping between permissions and individual objects in your system.
I have discussed about this in a related SO Post here - Resource based Authorization with Azure AD

My AzureAD - registered application doesn't have the rights to do anything ...?

I'm writing a c# program right now that tries to authenticate with Azure to make a generic http request. I finally got the code working and I wanted to test the features but for every request I make I get the following error code in response:
{"error":{"code": "AuthorizationFailed", "message":"The client "(id of the app I registered in AzureAD)" with object id "(same value as before)" does not have authorization to perform action 'Microsoft.Authorization/roleAssignments/read' over scope '/subscriptions/(mysubscriptionid)'."}}.
The thing is ... The account I use to set everything up is a global admin. I checked every permission box in AzureAD I could find...
(that's 8 Application Permissions and 9 Delegated permissions in the Windows Azure Active Directory API and 1 delegated Permission in the Windows Azure Service Management API, though I don't know why there aren't more possible permissions for Azure Service Management)
the relevant code is rather basic but it works so I don't feel like I need post it, I'll just say that I obtain the Token using Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenAsync() with
authorityUri = "https://login.windows.net/(mytenantid)",
string resourceUri = "https://management.azure.com/";
AuthenticationContext authContext = new AuthenticationContext(authorityUri);
var res = authContext.AcquireTokenAsync(resourceUri, new
ClientCredential(clientId,clientSecret));
return res.Result;
and make the Request to
https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/roleAssignments?api-version=2016-03-01&$filter=atScope()
(as an example, this one is supposed to call the roles).
Tried several different types of GET Requests to different URIs, all give similar errors.
I'm thinking it might not be an issue with the code but a setting in the AzurePortal but everything I found there seems set up right (or rather "universal access").
According to your description, you forget to grant your service principal. You could add it on Azure Portal. You could grant Contributor or Owner role to it.
Please refer to this link:Assign application to role.

Microsoft Graph - Get MemberOf

I'm trying to access the groups a user is a member of using the Microsoft Graph API.
I'm facing an issue because I think my permissions are set correctly, however, when I sign into the app, I get the message :
AADSTS90093: Calling principal cannot consent due to lack of permissions.
The weird thing is that I'm only asking for this permission scope :
public static String[] ClientScope = { "User.Read", "User.ReadBasic.All", "Group.Read.All"};
What makes me confused is that if I sign in the Microsoft Graph explorer and go to https://graph.microsoft.com/v1.0/me/memberOf ,
I get the correct results.
I got an admin to consent to the permissions I'm asking in the scope of course.
Has anyone encountered that issue ?
Any idea how I should correct that ?
The memberOf API requires one of the following scopes:
Directory.Read.All
Directory.ReadWrite.All
Directory.AccessAsUser.All
Regardless of which of these scopes you choose, they all will require administrative consent before a regular user can authorize them. To do this, you'll first need to have them go through the “Admin Consent” workflow. This workflow requires an administrator but once complete any users of your application will have “admin consent” to the restricted scope.
For example, you would normally you would then authenticate users by redirecting them to
https://login.microsoftonline.com/common/oauth2/authorize?<your params>.
Since this scope requires an Admin however, you fist need to obtain consent by first having an Admin authenticate by redirecting them to
https://login.microsoftonline.com/common/adminconsent?<yours params>.
Once an Admin grants consent, normal users will be able to use OAUTH to authenticate.

invalid_grant - type = password: user or admin has not consented to use the application

I am getting a consent error when trying to obtain a token. Because of our application, we can't show an interactive dialog to give consent.
"AADSTS65001: The user or administrator has not consented to use the
application with ID <'my native client app id'>. Send an
interactive authorization request for this user and resource.
AuthenticationContext ctx = new AuthenticationContext(
string.Format("https://login.microsoftonline.com/{0}","mytenant.onmicrosoft.com"));
UserPasswordCredential cred = new UserPasswordCredential("login#mytenant.onmicrosoft.com", "Password");
var result = ctx.AcquireTokenAsync("my api uri", "my native client id", cred);
We are using the grant_type=password and client_id is a Native app id, and resource is the Web API app URI.
Permissions-wise, from the client app, a delegated permission has been given to access the api app and have also tried setting oauth2AllowImplicitFlow : true in the manifest.
All applications have been created in the new preview Azure AD section of the new portal (portal.azure.com)
Unfortunately if your application needs access to certain resources like the Graph API, you will need to prompt for consent at least one time.
Even if your app doesn't have an interactive login experience, you should be able to prompt this once to unblock your scenario in your tenant.
Use the following URL:
https://login.microsoftonline.com/<TenantID>/oauth2/authorize?client_id=<AppID>&response_type=code&redirect_uri=<RedirectURI>&resource=<ResourceURI>&prompt=admin_consent
You can see here we have just simply generated the login URL which would be generated as part of an interactive login experience. You will need to fill out your own specific data like Reply URL, App ID, Resource URI, etc...
Note that we added a final query string at the end where we are forcing a "consent" prompt. This should be done by an Administrator, who would be able to consent on behalf of the whole tenant. Once you have done that, the username/password flow should start working for you.
Also, as an additional note, implicit grant flow has nothing to do with consent.
Please read this section in the OAuth 2 spec:
https://www.rfc-editor.org/rfc/rfc6749#section-1.3.2
You should only use this setting if you are creating a single-page application with something like JavaScript; Otherwise, there are significant security concerns with this setting on applications that should not have it.

Facebook Graph API "/userid/feed" returning Blank

I'm using Facebook C# SDK and I can't seem to get feed data back using Graph API.
I've obtained the following extended permissions from the user:
scope=offline_access,publish_stream,publish_checkins,create_event,read_stream,user_about_me,user_events,user_hometown,user_location,user_photos,read_friendlists,read_requests,user_checkins,user_relationships,user_online_presence,user_notes,user_likes,user_work_history
I have an access token for offline access.
I'm able to retrieve userid/friends information without a hitch, but can't seem to get feed data.
I get the following returned:
{
"data": [
]
}
I obtained the token with type="client_cred" if that makes a difference. The process runs with user offline, so I'm not using the "me" alias.
Can someone give some direction on what I'm doing wrong?
A token obtained with type=client_cred means "the application on behalf of itself", rather than "the application on behalf of a specific user". This means that it can only see stuff that's visible to all users. If you want to grab information on behalf of a particular user, you need to use that user's access token that you acquired. Since you asked for offline_access, when you acquire an access token for a user, that token won't expire quickly, and you can keep it around in a database.
FB.init({
appId : 'YOUR APP ID',
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
Once you add this code. Facebook sets a cookie on you domain. The name of the cookie would be fbs_YourAppId .
You can read the cookie and get the access_token.
Alternately you can use a method provided by the Facebook Api Connect.js file to get the feed if the user is logged in.
FB.Api(). Please refer to http://developers.facebook.com/docs/reference/javascript/fb.api/ to know more about the method.
Happy coding :)

Categories