C# AcquireTokenSilent无法以静默方式获取令牌吗?
我在Azure上有一个托管应用程序。在SiteMaster页(母版页)中,我尝试获取所有用户的广告组,因为我的应用程序是基于角色的应用程序,其中每个用户都属于Azure组,每个组都可以执行某些功能 页面加载事件中的代码如下所示:C# AcquireTokenSilent无法以静默方式获取令牌吗?,c#,asp.net,azure,token,adal,C#,Asp.net,Azure,Token,Adal,我在Azure上有一个托管应用程序。在SiteMaster页(母版页)中,我尝试获取所有用户的广告组,因为我的应用程序是基于角色的应用程序,其中每个用户都属于Azure组,每个组都可以执行某些功能 页面加载事件中的代码如下所示: private static string clientId = ConfigurationManager.AppSettings["ida:ClientID"]; private static string appKey = ConfigurationManager.
private static string clientId = ConfigurationManager.AppSettings["ida:ClientID"];
private static string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
private static string graphResourceId = "https://graph.windows.net";
protected void Page_Load(object sender, EventArgs e)
{
if (Request.IsAuthenticated)
{
IList<string> groups = GetUserData();
}
}
public IList<string> GetUserData()
{
string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
Uri servicePointUri = new Uri(graphResourceId);
Uri serviceRoot = new Uri(servicePointUri, tenantID);
ActiveDirectoryClient activeDirectoryClient = new ActiveDirectoryClient(serviceRoot,
async () => await GetTokenForApplication());
IList<string> groupMembership = new List<string>();
// use the token for querying the graph to get the user details
IUser user = activeDirectoryClient.Users
.Where(u => u.ObjectId.Equals(userObjectID))
.ExecuteAsync().Result.CurrentPage.ToList().First();
var userFetcher = (IUserFetcher)user;
requestor = user.DisplayName;
IPagedCollection<IDirectoryObject> pagedCollection = userFetcher.MemberOf.ExecuteAsync().Result;
do
{
List<IDirectoryObject> directoryObjects = pagedCollection.CurrentPage.ToList();
foreach (IDirectoryObject directoryObject in directoryObjects)
{
if (directoryObject is Group)
{
var group = directoryObject as Group;
groupMembership.Add(group.DisplayName);
}
}
pagedCollection = pagedCollection.GetNextPageAsync().Result;
} while (pagedCollection != null);
return groupMembership;
}
protected async Task<string> GetTokenForApplication()
{
string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").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 EF DB
AuthenticationContext authenticationContext = new AuthenticationContext(aadInstance + tenantID, new ADALTokenCache(signedInUserID));
AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenSilentAsync(graphResourceId, clientcred, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
return authenticationResult.AccessToken;
}
谢谢 AFAIK,当您尝试以静默方式获取令牌(调用AcquireTokenSilentAsync以获取accessToken)时,它将从令牌缓存中获取令牌,或以静默方式使用refreshToken。如果访问令牌和刷新令牌过期,您可能会获得AdalSilentTokenAcquisitionException。您必须捕获AdalSilentTokenAcquisitionException异常:
try
{
AuthenticationContext authenticationContext = new AuthenticationContext(aadInstance + tenantID, new ADALTokenCache(signedInUserID));
AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenSilentAsync(graphResourceId, clientcred, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
return authenticationResult.AccessToken;
}
catch (AdalSilentTokenAcquisitionException)
{
//told or force the user to reauthentificate.
return null;
}
在异常句柄中,您可以告诉用户重新身份验证或直接执行OAuth身份验证过程。将尽一切可能在不提示交互式身份验证请求的情况下为您获取有效令牌。如果不能(通过缓存或刷新令牌),则将生成异常
您可以捕获并决定提示进行交互式身份验证,或者静默失败,并根据您的应用程序逻辑要求最终用户稍后登录。是此交互式呼叫的参考文档
AuthenticationResult result;
try
{
result = await authContext.AcquireTokenSilentAsync(resourceId, clientId);
}
catch (AdalException ex)
{
if (ex.ErrorCode == "failed_to_acquire_token_silently")
{
// There are no tokens in the cache.
result = await authContext.AcquireTokenAsync(resourceId, clientId, redirectUri, new PlatformParameters(PromptBehavior.Always));
}
else
{
// An unexpected error occurred.
string message = ex.Message;
if (ex.InnerException != null)
{
message += "Inner Exception : " + ex.InnerException.Message;
}
MessageBox.Show(message);
}
是一个很棒的代码示例.NETMVC应用程序,它向您展示了如何使用ADAL 请编辑您的问题并仅将所有堆栈跟踪放在那里。谢谢。@GauravMantri我在问题中添加了堆栈跟踪谢谢@DanielDobalian的回答。我也有同样的想法。如果没有令牌,我如何让应用程序强制用户重新登录?签出行
result=wait authContext.AcquireTokenAsync(resourceId、clientId、redirectUri、new PlatformParameters(PromptBehavior.Always))代码>。这将强制执行交互身份验证请求。代码示例似乎过时了,它都是关于Owin的,而不是对AcquireToken的单个引用。@Wolfzoon很好,该示例都是Owin OIDC,一个显示OWIN+ADAL行为的代码示例。我尝试了这种方法,并以匿名方式打开,但它不适用于我为您提供答案。是否有类似的内容,而不是通知用户重新授权,它应该使用可用参数生成新的令牌?重新授权需要用户名/密码,对吗?浏览器也不能帮你点击登录按钮,甚至记住用户名和密码,这是出于安全考虑
AuthenticationResult result;
try
{
result = await authContext.AcquireTokenSilentAsync(resourceId, clientId);
}
catch (AdalException ex)
{
if (ex.ErrorCode == "failed_to_acquire_token_silently")
{
// There are no tokens in the cache.
result = await authContext.AcquireTokenAsync(resourceId, clientId, redirectUri, new PlatformParameters(PromptBehavior.Always));
}
else
{
// An unexpected error occurred.
string message = ex.Message;
if (ex.InnerException != null)
{
message += "Inner Exception : " + ex.InnerException.Message;
}
MessageBox.Show(message);
}