C# 如何使用MVC对Microsoft graph进行REST Api调用?
我试图对MicrosoftGraph进行RESTAPI调用,以获取我的组织用户。我用邮递员打了一个成功的电话。但是,我无法使用c代码成功地进行相同的调用。在使用JWT解码器进行调查时,我得到的令牌与使用postman得到的令牌不同。我一定错过了什么。我正在使用MVC5和.NET4.6C# 如何使用MVC对Microsoft graph进行REST Api调用?,c#,azure,oauth-2.0,azure-active-directory,microsoft-graph-api,C#,Azure,Oauth 2.0,Azure Active Directory,Microsoft Graph Api,我试图对MicrosoftGraph进行RESTAPI调用,以获取我的组织用户。我用邮递员打了一个成功的电话。但是,我无法使用c代码成功地进行相同的调用。在使用JWT解码器进行调查时,我得到的令牌与使用postman得到的令牌不同。我一定错过了什么。我正在使用MVC5和.NET4.6 public static async Task<AuthenticationResult> GetGraphAccessTokenAsync(string tenant, string cli
public static async Task<AuthenticationResult> GetGraphAccessTokenAsync(string tenant, string clientId, string clientKey)
{
var authority = string.Format("https://login.microsoftonline.com/{0}", tenant);
var resource = "https://graph.microsoft.com";
AuthenticationContext authenticationContext = new AuthenticationContext(authority);
var clientCredential = new ClientCredential(clientId, clientKey);
var result = await authenticationContext.AcquireTokenAsync(resource, clientCredential);
return result;
}
公共静态异步任务GetGraphAccessTokenAsync(字符串租户、字符串clientId、字符串clientKey)
{
var authority=string.Format(“https://login.microsoftonline.com/{0},租户);
变量资源=”https://graph.microsoft.com";
AuthenticationContext AuthenticationContext=新的AuthenticationContext(授权);
var clientCredential=新的clientCredential(clientId,clientKey);
var result=await authenticationContext.AcquireTokenAsync(资源,clientCredential);
返回结果;
}
原因:
使用不同的流来获取令牌,结果将不同。对于授权码流,它将获得包含upn和作用域的委托访问令牌。对于客户端凭据流,它将获得一个基本(来自应用程序权限)访问令牌。
当您使用授权代码流时:您将获得访问令牌和id令牌,其中还包含用户的upn和作用域,如下所示:
{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/f62479de-8353-4507-aaf3-6a52320f641c/",
"iat": 1521565239,
"nbf": 1521565239,
"exp": 1521569139,
"app_displayname": "MicrosoftGraphClient",
"appid": "2024c60c-fe49-4ca0-80e8-94132f56d7c4",
"family_name": "Yang",
"given_name": "Wayne",
"name": "Wayne Yang",
"unique_name": "wayneyang@contoso.onmicrosoft.com",
...
"tid": "f62472de-8358-4507-aaf3-6a52320f641c",
}
{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/f62479de-8353-4507-aaf3-6a52320f641c/",
"iat": 1521555934,
"nbf": 1521555934,
"exp": 1521559834,
"app_displayname": "MicrosoftGraphClient",
"appid": "2024c60c-fe49-4ca0-80e8-94132f56d7c4",
"roles": [
"Directory.Read.All",
"User.Read.All",
...
"Mail.ReadWrite",
],
"tid": "f62471de-8358-4907-aaf3-6a52320f741c",
}
当您使用客户端凭据流时:您将获得访问令牌,而无需usre的upn和作用域,如下所示:
{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/f62479de-8353-4507-aaf3-6a52320f641c/",
"iat": 1521565239,
"nbf": 1521565239,
"exp": 1521569139,
"app_displayname": "MicrosoftGraphClient",
"appid": "2024c60c-fe49-4ca0-80e8-94132f56d7c4",
"family_name": "Yang",
"given_name": "Wayne",
"name": "Wayne Yang",
"unique_name": "wayneyang@contoso.onmicrosoft.com",
...
"tid": "f62472de-8358-4507-aaf3-6a52320f641c",
}
{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/f62479de-8353-4507-aaf3-6a52320f641c/",
"iat": 1521555934,
"nbf": 1521555934,
"exp": 1521559834,
"app_displayname": "MicrosoftGraphClient",
"appid": "2024c60c-fe49-4ca0-80e8-94132f56d7c4",
"roles": [
"Directory.Read.All",
"User.Read.All",
...
"Mail.ReadWrite",
],
"tid": "f62471de-8358-4907-aaf3-6a52320f741c",
}
解决方案:
您可以在代码中使用授权代码授权流。但是,由于您希望调用MicrosoftGraphAPI,我建议您使用v2端点,而不是ADAL。因为如果使用ADAL,可能会导致一些问题,例如凭证缓存被清除
有关.NET 4.6 MVC应用程序,请参阅。此示例将UseOpenIdConnectAuthentication
与授权代码授权流一起使用:
public partial class Startup
{
// The appId is used by the application to uniquely identify itself to Azure AD.
// The appSecret is the application's password.
// The redirectUri is where users are redirected after sign in and consent.
// The graphScopes are the Microsoft Graph permission scopes that are used by this sample: User.Read Mail.Send
private static string appId = ConfigurationManager.AppSettings["ida:AppId"];
private static string appSecret = ConfigurationManager.AppSettings["ida:AppSecret"];
private static string redirectUri = ConfigurationManager.AppSettings["ida:RedirectUri"];
private static string graphScopes = ConfigurationManager.AppSettings["ida:GraphScopes"];
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
// The `Authority` represents the Microsoft v2.0 authentication and authorization service.
// The `Scope` describes the permissions that your app will need. See https://azure.microsoft.com/documentation/articles/active-directory-v2-scopes/
ClientId = appId,
Authority = "https://login.microsoftonline.com/common/v2.0",
PostLogoutRedirectUri = redirectUri,
RedirectUri = redirectUri,
Scope = "openid email profile offline_access " + graphScopes,
TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
// In a real application you would use IssuerValidator for additional checks,
// like making sure the user's organization has signed up for your app.
// IssuerValidator = (issuer, token, tvp) =>
// {
// if (MyCustomTenantValidation(issuer))
// return issuer;
// else
// throw new SecurityTokenInvalidIssuerException("Invalid issuer");
// },
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = async (context) =>
{
var code = context.Code;
string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
TokenCache userTokenCache = new SessionTokenCache(signedInUserID,
context.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase).GetMsalCacheInstance();
ConfidentialClientApplication cca = new ConfidentialClientApplication(
appId,
redirectUri,
new ClientCredential(appSecret),
userTokenCache,
null);
string[] scopes = graphScopes.Split(new char[] { ' ' });
AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, scopes);
},
AuthenticationFailed = (context) =>
{
context.HandleResponse();
context.Response.Redirect("/Error?message=" + context.Exception.Message);
return Task.FromResult(0);
}
}
});
}
}
此外,您可以参考以实现您的场景。您能告诉我令牌之间的区别是什么吗?你可以在这个问题中发布它。我使用postman获得的一个有我所有的凭据和范围(如“User.Read”),但是,我通过c#code获得的一个没有我的任何凭据,它只有应用程序名称、应用程序Id和一些其他信息。我想对访问该应用程序的任何人进行身份验证,并授予AAD authenticated userHi@Mike访问权限,你是说你通过C#code获得的令牌没有
角色
和aio
声明?它有“aio”声明,但没有“scp”和我的凭据(如我的givenName、电子邮件…)。当您使用客户端凭据流获取具有v1端点的Microsoft graph的令牌时,访问令牌将不包含您的凭据。您是否使用邮递员获取带有客户端凭据的令牌流?嗨@Mike,这个答案有用吗?