在asp.net核心项目中获取Azure活动目录组

34

我使用Visual Studio 2015创建了一个新项目,并启用了针对Azure Active Directory的工作和学校帐户的身份验证。以下是生成的配置函数:

app.UseStaticFiles();
app.UseCookieAuthentication();
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
    ClientId = Configuration["Authentication:AzureAd:ClientId"],
    ClientSecret = Configuration["Authentication:AzureAd:ClientSecret"],
    Authority = Configuration["Authentication:AzureAd:AADInstance"] + Configuration["Authentication:AzureAd:TenantId"],
    CallbackPath = Configuration["Authentication:AzureAd:CallbackPath"],
    ResponseType = OpenIdConnectResponseType.CodeIdToken
});

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

这里是尝试获取用户组的基本动作代码:

public async Task<IActionResult> Index()
{
    var client = new HttpClient();
    var uri = "https://graph.windows.net/myorganization/users/{user_id}/$links/memberOf?api-version=1.6";

    var response = await client.GetAsync(uri);
    if (response.Content != null)
    {
        ViewData["response"] = await response.Content.ReadAsStringAsync();
    }

    return View();
}    

我需要做些什么来使用或更改这个代码,以确保我能够获取用户组?目前的响应是:

{  
   "odata.error":{  
      "code":"Authentication_MissingOrMalformed",
      "message":{  
         "lang":"en",
         "value":"Access Token missing or malformed."
      },
      "values":null
   }
}

嗨,Kiran,你在这个问题方面有什么想法吗?我遇到了完全相同的问题。谢谢! - Easton James Harvey
Kiran,如果你喜欢我的回答,请选择它。谢谢。 - Easton James Harvey
检查您的索引方法,您正在创建一个HttpClient()实例并设置URL。但是,在调用GetAsync()之前,您从未设置Authorization标头。尝试阅读有关Events和UseOpenIdConnectAuthentication的OnTokenValidated方法,这应该有助于您获取访问令牌,并可能导致解决方案。 - Sai Puli
1
不确定这是否符合您的要求,但在我看来,使用Graph获取角色和组比起来要容易得多。我创建了一个使用Azure AD的.Net Core应用程序,该应用程序从现场公司AD中获取数据。可以在AD上管理角色/用户,然后将其推送到Azure AD,并且应用程序定义的角色就是应用程序将使用的角色。https://learn.microsoft.com/en-us/azure/architecture/multitenant-identity/app-roles - Daniel Jackson
2个回答

2
我花了最近两天的时间来解决这个问题,终于搞定了。Azure AD是一个不断发展的目标,而且由于ASPNETCORE仍在成熟阶段,大部分关于如何访问Azure AD Graph的文档都已经过时了。所以现在你需要这样做才能访问Azure AD Graph。
  1. 记录应用程序的客户端ID
  2. 在Azure Active Directory中注册您的应用程序
  3. 在该注册中生成一个密钥,并记下它(只有在创建后立即查看才能看到)
  4. 记录您的'租户名称'(也可以使用租户ID)
然后,您将使用上述信息生成访问令牌,然后使用该令牌调用Graph。
public async void GetUsers()
    {
        // Get OAuth token using client credentials 
        string tenantName = "your-tenant-name.onmicrosoft.com";
        string authString = "https://login.microsoftonline.com/" + tenantName;
        AuthenticationContext authenticationContext = new AuthenticationContext(authString, false);
        // Config for OAuth client credentials  
        string clientId = "your-client-id";
        string key = "your-AzureAD-App-Key";
        ClientCredential clientCred = new ClientCredential(clientId, key);
        string resource = "https://graph.windows.net";
        AuthenticationResult authenticationResult;
        try
        {
            authenticationResult = await authenticationContext.AcquireTokenAsync(resource, clientCred);
        }
        catch(Exception ex)
        {
            throw new Exception(ex.Message, ex.InnerException);
        }

        var client = new HttpClient();
        var request = new HttpRequestMessage(System.Net.Http.HttpMethod.Get, "https://graph.windows.net/your-tenant-name.onmicrosoft.com/users?api-version=1.6");
        request.Headers.Authorization =
          new AuthenticationHeaderValue("Bearer", authenticationResult.AccessToken);
        var response = await client.SendAsync(request);
        var content = await response.Content.ReadAsStringAsync();
    }

你可能会遇到一个非常棘手的问题,就是当你收到“Authorization_Request_Denied”或“Insufficient_Permissions”错误时。许多论坛都在讨论这个问题。解决方法是运行一个PowerShell命令,为你在Azure AD中注册的应用程序授予“管理员”权限。

请求MS Graph API时出现“Authorization Request Denied - Insufficient privileges to complete the operation”

你需要运行的PowerShell命令是:

Connect-MsolService
$ClientIdWebApp = '{your_AD_application_client_id}'
$webApp = Get-MsolServicePrincipal –AppPrincipalId $ClientIdWebApp
#use Add-MsolRoleMember to add it to "Company Administrator" role).
Add-MsolRoleMember -RoleName "Company Administrator" -RoleMemberType ServicePrincipal -RoleMemberObjectId $webApp.ObjectId

希望这可以帮到你。如果你认为需要进一步改进,请告诉我。

1
您不需要将服务主体添加到公司管理员角色中。它只需要“读取所有组委派权限/读取目录数据应用程序权限”。如果您收到该错误,则意味着未获得管理员同意或未请求权限。 - juunas
谢谢你的贡献,@juunas。这个答案更多地涉及到额外信息之上的所有内容。与你上面的智慧相反,我已经给了应用程序“读取所有组委派权限/读取目录数据应用程序权限”,但它仍然没有足够的权限。只有在我应用了上面推荐的额外解决方案后,它才终于返回了我的请求。我希望我的答案能帮助那些遇到同样问题的人。 - Easton James Harvey
2
我已经使用这些权限实现了这样一个应用程序。通常将主体作为最高管理员角色是不明智的,因为此时主体实际上可以重置任何用户的密码。 - juunas

1
代码使用Graph客户端会更简单。
var serviceRoot = new Uri(@"https://graph.windows.net/"+ tenantID);
var activeDirectoryClient = new ActiveDirectoryClient(serviceRoot,
    () => Task.FromResult(authenticationResult.AccessToken));

// Fetch more user details from the Graph
var user = await activeDirectoryClient.Users.GetByObjectId(userObjectID).ExecuteAsync();
// fetch all groups (DG + SG) and roles transitively for the user
var userGroups = await user.GetMemberObjectsAsync(securityEnabledOnly: false);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接