我正在尝试使用JWT access token中从groups:src1
接收到的_claims_sources
端点值从Graph API中获取广告组。
我的客户端正在使用客户端凭据,并且可以获取广告中所有用户和组的信息。
这是我的设置方式:
private async Task<IList<Group>> GetUserGroupsAsync(string endpoint)
{
// Endpoint is from the claims in a previous OIDC request
// Setup a client if it does not exist
PrepareGraphApiClient();
// I can fetch my groups using the methods in the client
// var groupPage = await graphServiceClient.Me.MemberOf.Request().GetAsync();
// This is where I would like to use the resource URL received from the
// claims I receive in a previous OIDC request
var groupPageFromUrl = ???
...
}
private void PrepareGraphApiClient()
{
if (graphServiceClient != null) return;
try
{
AuthenticationContext authority = new AuthenticationContext(oidcOptions.Authority);
ClientCredential clientCredential = new ClientCredential(oidcOptions.ClientId, oidcOptions.ClientSecret);
var graphApiResource = "https://graph.microsoft.com";
AuthenticationResult authenticationResult = authority.AcquireTokenAsync(graphApiResource, clientCredential).Result;
graphServiceClient = new GraphServiceClient(new DelegateAuthenticationProvider(
async requestMessage =>
{
// Add token to outgoing requests
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", authenticationResult.AccessToken);
}));
}
catch (Exception ex)
{
logger.LogDebug($"Could not create the graph client {ex}");
throw;
}
}
我可以在GraphServiceClient中使用声明中的资源URL,还是必须设置HttpClient进行请求?
答案 0 :(得分:1)
_claim_sources.src1
中标识的终结点用于Azure AD Graph,因此您使用的令牌必须用于Azure AD Graph API(https://graph.windows.net
),而不用于Microsoft Graph(https://graph.microsoft.com
)。这也意味着您不能使用Microsoft Graph SDK,因为API的请求和响应本质上是不同的。
您有两个选择:
(推荐)使用以下事实:仅给出端点指示您必须进行查找,并使用Microsoft Graph SDK对Microsoft Graph进行等效调用:
var memberOfIds = await graphServiceClient
.Users[userObjectId] # from the 'oid' in access token
.GetMemberObjects(securityEnabledOnly: true) # true if groupMembershipClaims is "SecurityGroup", false if it's "All"
.Request()
.PostAsync();
使用给定的端点,并使用(例如)HttpClient建立对Microsoft Graph的请求。一个简短的例子:
using (var client = new HttpClient())
{
# Always get the token right before you use it. ADAL will take care of getting a new one
# if needed, or using an existing cached token if not.
authenticationResult =
authority.AcquireTokenAsync("https://graph.windows.net", clientCredential)
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
# Make the API request to Azure AD Graph. Note we have to include the api-version and
# the request body.
HttpResponseMessage response = await client.PostAsync(
$"{src}?api-version=1.6", new StringContent(
"{'securityEnabledOnly': true}", # true if groupMembershipClaims is "SecurityGroup", false if it's "All"
UnicodeEncoding.UTF8,
"application/json"));
if (response.IsSuccessStatusCode)
{
# Note we're deserializing as if it were a Microsoft Graph response to getMemberObjects,
# rather than an Azure AD Graph response. Though it works, this is somewhat risky, and
# it would be more correct to explicitly define the form of an Azure AD Graph response.
var memberOfIds = JsonConvert.DeserializeObject<DirectoryObjectGetMemberObjectsCollectionResponse>(
await response.Content.ReadAsStringAsync()).Value;
}
}
作为旁注,我注意到您正在调用获取您提供给Microsoft Graph库的DelegateAuthenticationProvider
的令牌外部。您应该将AcquireTokenAsync
调用放在内部,以便它为每个Microsoft Graph请求检索一个新的令牌。库(ADAL)将负责使用缓存的令牌(如果可用)或发出新的令牌请求(如果没有可用或可用的令牌已过期)。像这样:
graphServiceClient = new GraphServiceClient(new DelegateAuthenticationProvider(
async requestMessage =>
{
// Get fresh token
AuthenticationResult authenticationResult =
await authority.AcquireTokenAsync(graphApiResource, clientCredential);
// Add token to outgoing requests
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", authenticationResult.AccessToken);
}));