无法静默获取令牌 - Microsoft Graph API 获取用户的 outlook 组
Failed to acquire token silently - Microsoft Graph API to obtain a user’s outlook groups
我正在尝试访问 Microsoft Graph API 以获取用户的 outlook 组。
这是检索访问令牌的代码:
public static async Task<string> GetGraphAccessTokenAsync()
{
string AzureAdGraphResourceURL = "https://graph.microsoft.com/";
string signedInUserUniqueName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
var userObjectId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
var clientCredential = new ClientCredential(SettingsHelper.ClientId, SettingsHelper.AppKey);
var userIdentifier = new UserIdentifier(userObjectId, UserIdentifierType.UniqueId);
AuthenticationContext authContext = new AuthenticationContext(
SettingsHelper.Authority, new ADALTokenCache(signedInUserUniqueName));
var result = await authContext.AcquireTokenSilentAsync(AzureAdGraphResourceURL, clientCredential, userIdentifier);
return result.AccessToken;
}
该方法使用如下设置助手:
public class SettingsHelper
{
private static string _clientId = ConfigurationManager.AppSettings["ida:ClientID"];
private static string _appKey = ConfigurationManager.AppSettings["ida:Password"];
private static string _tenantId = ConfigurationManager.AppSettings["ida:TenantID"];
private static string _authorizationUri = "https://login.windows.net";
private static string _authority = "https://login.windows.net/{0}/";
private static string _graphResourceId = "https://graph.windows.net";
public static string ClientId
{
get
{
return _clientId;
}
}
public static string AppKey
{
get
{
return _appKey;
}
}
public static string TenantId
{
get
{
return _tenantId;
}
}
public static string AuthorizationUri
{
get
{
return _authorizationUri;
}
}
public static string Authority
{
get
{
return String.Format(_authority, _tenantId);
}
}
public static string AADGraphResourceId
{
get
{
return _graphResourceId;
}
}
}
这是我得到的错误:
无法静默获取令牌。调用方法 AcquireToken
异常详情:
Microsoft.IdentityModel.Clients.ActiveDirectory.AdalSilentTokenAcquisitionException : Failed to acquire token silently. Call method AcquireToken
错误专门出现在这一行:
var result = await authContext.AcquireTokenSilentAsync(AzureAdGraphResourceURL, clientCredential, userIdentifier);
我已经检查以确保 UserIdentifier 与缓存中的值相匹配,但它似乎仍然拒绝令牌。关于我可能哪里出错的任何想法?
首先,确保使用 Microsoft graph 端点(实际上您使用的是 Active directory 端点)
private static readonly string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private static readonly string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
private static readonly string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
private static readonly string tenantId = ConfigurationManager.AppSettings["ida:TenantId"];
private static readonly string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];
private static readonly string graphResourceId = "https://graph.microsoft.com";
private static readonly Uri graphEndpointId = new Uri("https://graph.microsoft.com/v1.0/");
在进行静音呼叫之前,您必须通过检索代码进行 classic 呼叫。我假设您在 MVC 应用程序中。
这是我的 Startup.Auth.cs 代码:
public void ConfigureAuth(IAppBuilder app)
{
ApplicationDbContext db = new ApplicationDbContext();
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = AuthenticationHelper.ClientId,
Authority = AuthenticationHelper.AadInstance + AuthenticationHelper.TenantId,
PostLogoutRedirectUri = AuthenticationHelper.PostLogoutRedirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications()
{
// If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
AuthorizationCodeReceived =async (context) =>
{
var code = context.Code;
string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
try
{
var result = await AuthenticationHelper.GetAccessTokenByCodeAsync(signedInUserID, code);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
//throw;
}
}
}
});
}
这是我在 AuthenticationHelper class 中使用的代码:
public async static Task<AuthenticationResult> GetAccessTokenByCodeAsync(string signedInUserID, string code)
{
ClientCredential credential = new ClientCredential(clientId, appKey);
AuthenticationContext authContext = new AuthenticationContext(AadInstance + TenantId, new ADALTokenCache(signedInUserID));
AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(
code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId);
return result;
}
然后,每次我需要向图表发出请求时,这里是我用来获取令牌的代码:
public async static Task<string> GetTokenForApplicationAsync()
{
string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
// get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc)
ClientCredential clientcred = new ClientCredential(clientId, appKey);
// initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database
AuthenticationContext authenticationContext = new AuthenticationContext(AadInstance + TenantId, new ADALTokenCache(signedInUserID));
AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenSilentAsync(GraphResourceId, clientcred, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
return authenticationResult.AccessToken;
}
其他需要注意的事情:确保您的 tenantId 是租户的 guid。出于某种原因,有时,如果您使用您的租户名称,adal 会有所不同并可能引发此类错误。
我正在尝试访问 Microsoft Graph API 以获取用户的 outlook 组。
这是检索访问令牌的代码:
public static async Task<string> GetGraphAccessTokenAsync()
{
string AzureAdGraphResourceURL = "https://graph.microsoft.com/";
string signedInUserUniqueName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
var userObjectId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
var clientCredential = new ClientCredential(SettingsHelper.ClientId, SettingsHelper.AppKey);
var userIdentifier = new UserIdentifier(userObjectId, UserIdentifierType.UniqueId);
AuthenticationContext authContext = new AuthenticationContext(
SettingsHelper.Authority, new ADALTokenCache(signedInUserUniqueName));
var result = await authContext.AcquireTokenSilentAsync(AzureAdGraphResourceURL, clientCredential, userIdentifier);
return result.AccessToken;
}
该方法使用如下设置助手:
public class SettingsHelper
{
private static string _clientId = ConfigurationManager.AppSettings["ida:ClientID"];
private static string _appKey = ConfigurationManager.AppSettings["ida:Password"];
private static string _tenantId = ConfigurationManager.AppSettings["ida:TenantID"];
private static string _authorizationUri = "https://login.windows.net";
private static string _authority = "https://login.windows.net/{0}/";
private static string _graphResourceId = "https://graph.windows.net";
public static string ClientId
{
get
{
return _clientId;
}
}
public static string AppKey
{
get
{
return _appKey;
}
}
public static string TenantId
{
get
{
return _tenantId;
}
}
public static string AuthorizationUri
{
get
{
return _authorizationUri;
}
}
public static string Authority
{
get
{
return String.Format(_authority, _tenantId);
}
}
public static string AADGraphResourceId
{
get
{
return _graphResourceId;
}
}
}
这是我得到的错误: 无法静默获取令牌。调用方法 AcquireToken
异常详情:
Microsoft.IdentityModel.Clients.ActiveDirectory.AdalSilentTokenAcquisitionException : Failed to acquire token silently. Call method AcquireToken
错误专门出现在这一行:
var result = await authContext.AcquireTokenSilentAsync(AzureAdGraphResourceURL, clientCredential, userIdentifier);
我已经检查以确保 UserIdentifier 与缓存中的值相匹配,但它似乎仍然拒绝令牌。关于我可能哪里出错的任何想法?
首先,确保使用 Microsoft graph 端点(实际上您使用的是 Active directory 端点)
private static readonly string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private static readonly string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
private static readonly string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
private static readonly string tenantId = ConfigurationManager.AppSettings["ida:TenantId"];
private static readonly string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];
private static readonly string graphResourceId = "https://graph.microsoft.com";
private static readonly Uri graphEndpointId = new Uri("https://graph.microsoft.com/v1.0/");
在进行静音呼叫之前,您必须通过检索代码进行 classic 呼叫。我假设您在 MVC 应用程序中。 这是我的 Startup.Auth.cs 代码:
public void ConfigureAuth(IAppBuilder app)
{
ApplicationDbContext db = new ApplicationDbContext();
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = AuthenticationHelper.ClientId,
Authority = AuthenticationHelper.AadInstance + AuthenticationHelper.TenantId,
PostLogoutRedirectUri = AuthenticationHelper.PostLogoutRedirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications()
{
// If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
AuthorizationCodeReceived =async (context) =>
{
var code = context.Code;
string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
try
{
var result = await AuthenticationHelper.GetAccessTokenByCodeAsync(signedInUserID, code);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
//throw;
}
}
}
});
}
这是我在 AuthenticationHelper class 中使用的代码:
public async static Task<AuthenticationResult> GetAccessTokenByCodeAsync(string signedInUserID, string code)
{
ClientCredential credential = new ClientCredential(clientId, appKey);
AuthenticationContext authContext = new AuthenticationContext(AadInstance + TenantId, new ADALTokenCache(signedInUserID));
AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(
code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId);
return result;
}
然后,每次我需要向图表发出请求时,这里是我用来获取令牌的代码:
public async static Task<string> GetTokenForApplicationAsync()
{
string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
// get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc)
ClientCredential clientcred = new ClientCredential(clientId, appKey);
// initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database
AuthenticationContext authenticationContext = new AuthenticationContext(AadInstance + TenantId, new ADALTokenCache(signedInUserID));
AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenSilentAsync(GraphResourceId, clientcred, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
return authenticationResult.AccessToken;
}
其他需要注意的事情:确保您的 tenantId 是租户的 guid。出于某种原因,有时,如果您使用您的租户名称,adal 会有所不同并可能引发此类错误。