我在Azure上有一个托管应用程序。在SiteMaster页面(母版页)中,我试图获取所有用户的AD组,因为我的应用程序是基于角色的应用程序,其中每个用户都属于Azure组,每个组都可以执行某些功能。
页面加载事件中的代码如下所示:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div class="div1">
<ul>
<li>Line 1</li>
</ul>
<ul>
<li>Line 1</li>
<li>Line 2</li>
</ul>
<ul>
<li>Line 1</li>
<li>Line 2</li>
<li>Line 3</li>
</ul>
</div>
</div>
请注意,我正在调用实际带来用户所属的所有组的函数'GetUserData()'。该函数的代码如下:
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();
}
}
'GetUserData()'函数正在调用另一个名为'GetTokenForApplication()'的函数,该函数负责获取Azure的令牌表单。上一个函数的源代码如下:
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;
}
在某些我不知道的情况下会发生此错误,当它发生时,它不会影响所有用户。有些用户仍然可以进入而不会出现此错误。任何关于为什么会发生这种情况的建议或想法,以及如何解决这样的错误?
这是我的Stack Trace:
Failed to acquire token silently. Call method AcquireToken
谢谢!
答案 0 :(得分:1)
AcquireTokenSilentAsync会尝试各种方式来获取有效的令牌,而不会提示您进行交互式身份验证请求。如果它不能(通过缓存或刷新令牌),那么它将生成异常。
您可以抓住this exception并决定提示进行交互式身份验证或无提示失败,并要求最终用户稍后登录,具体取决于您的应用逻辑。 Here是此互动调用的参考文档。
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);
}
Here是一个很棒的代码示例.NET MVC应用程序,它向您展示如何使用ADAL。
答案 1 :(得分:0)
AFAIK,当您尝试以静默方式获取令牌(调用AcquireTokenSilentAsync以获取accessToken)时,它将从TokenCache获取令牌或静默使用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身份验证过程。