Код: Выделить всё
$.ajax({
type: "GET",
url: "@Url.Action("GetUser", "UserProfile", null)",
dataType: "json",
success: function (data, status, xhr) {
console.log("in AJAX");
$(".img-circle, .user-image").attr("src", data.Picture);
$("#user-menu-expanded").text(data.User.DisplayName + " - " + data.User.JobTitle);
$("#user-menu-spinner").remove();
console.log(data);
},
error: function (ex) {
console.log(ex);
}
});
Код: Выделить всё
UserProfileКод: Выделить всё
public JsonResult GetUser()
{
var model = new UserProfileViewModel();
return Json(model, JsonRequestBehavior.AllowGet);
}
Код: Выделить всё
public UserProfileViewModel()
{
var graphClient = GetAuthGraphClient();
GetPicture(graphClient);
GetUserProfile(graphClient);
}
public GraphServiceClient GetAuthGraphClient()
{
string graphResourceID = "https://graph.microsoft.com/";
return new GraphServiceClient(
new DelegateAuthenticationProvider((requestMessage) =>
{
string accessToken = GetTokenForApplication(graphResourceID);
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
return Task.FromResult(0);
}
));
}
public string GetTokenForApplication(string graphResourceID)
{
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;
string authority = "https://login.microsoftonline.com/" + tenantID;
try
{
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(authority);
var token = authenticationContext.AcquireTokenAsync(graphResourceID, clientcred).Result.AccessToken;
return token;
}
catch (Exception e)
{
// Capture error for handling outside of catch block
ErrorMessage = e.Message;
return null;
}
}
public void GetPicture(GraphServiceClient graphClient)
{
Stream photo = Task.Run(async () => { return await graphClient.Me.Photo.Content.Request().GetAsync(); }).Result;
using (var memoryStream = new MemoryStream())
{
photo.CopyTo(memoryStream);
var base64pic = Convert.ToBase64String(memoryStream.ToArray());
this.Picture = "data:image;base64," + base64pic;
HttpContext.Current.Cache.Add("Pic", this.Picture, null, DateTime.Now.AddHours(5), Cache.NoSlidingExpiration, CacheItemPriority.AboveNormal, null);
}
}
public void GetUserProfile(GraphServiceClient graphClient)
{
this.User = Task.Run(async () => { return await graphClient.Me.Request().GetAsync(); }).Result;
}
Токен доступа из журнала IIS
Журнал консоли
У меня есть два вопроса (возможно, 3):
- Что я делаю неправильно?
- Можно ли использовать токен доступа из моего Startup.Auth для создания аутентифицированного клиента Graph? Если да, то как бы я это сделал?
Код: Выделить всё
// This is the resource ID of the AAD Graph API. We'll need this to request a token to call the Graph API. string graphResourceId = "https://graph.microsoft.com"; //https://graph.windows.net public void ConfigureAuth(IAppBuilder app) { ApplicationDbContext db = new ApplicationDbContext(); app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); app.UseKentorOwinCookieSaver(); app.UseCookieAuthentication(new CookieAuthenticationOptions()); app.UseOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { ClientId = clientId, Authority = Authority, PostLogoutRedirectUri = 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 = (context) => { var code = context.Code; ClientCredential credential = new ClientCredential(clientId, appKey); string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value; AuthenticationContext authContext = new AuthenticationContext(Authority, new ADALTokenCache(signedInUserID)); AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode( code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId); HttpContext.Current.Cache.Add("Token", result.AccessToken, null, DateTime.Now.AddHours(5), Cache.NoSlidingExpiration, CacheItemPriority.AboveNormal, null); return Task.FromResult(0); } } }); }
Код: Выделить всё
public string GetTokenForApplication(string graphResourceID)
{
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;
string authority = "https://login.microsoftonline.com/" + tenantID;
try
{
// 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(Startup.Authority, new ADALTokenCache(userObjectID));
var result = authenticationContext.AcquireTokenSilent(graphResourceID, clientcred, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
return result.AccessToken;
}
catch (Exception e)
{
// Capture error for handling outside of catch block
ErrorMessage = e.Message;
return null;
}
}
Благодаря @Fei Xue я понял проблему… вроде. Это устраняет мою проблему при локальном запуске, но мне по-прежнему не удается автоматически получить токен при публикации в моем рабочем приложении. Когда я впервые создавал приложение, я включил аутентификацию «Рабочая/школьная» (Azure AD). Это создало локальный контекст БД, который использовался для кэша токенов ADAL. При разработке приложения я создал еще один контекст БД для базы данных SQL Azure, которую я создал для приложения. Мне пришлось обновить файл AdalTokenCache.cs, чтобы отразить контекст БД моего приложения и новую модель. Я обновил строку:
Код: Выделить всё
private ApplicationDbContext db = new ApplicationDbContext();
Код: Выделить всё
private UserTokenCache Cache;
Код: Выделить всё
private UserTokenCach Cache;
Затем я просто использовал метод AcquireToken, который появился OOB в контроллере UserProfile, чтобы получить токен. Вот как это выглядело в итоге (Примечание: я также обновил строки в файле start.auth с частного на общедоступные, чтобы можно было использовать их в своей модели представления):
Код: Выделить всё
public string GetTokenForApplication(string graphResourceID)
{
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;
string authority = "https://login.microsoftonline.com/" + tenantID;
try
{
// get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc)
ClientCredential clientcred = new ClientCredential(Startup.clientId, Startup.appKey);
// initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database
AuthenticationContext authenticationContext = new AuthenticationContext(Startup.Authority, new ADALTokenCache(signedInUserID));
var result = authenticationContext.AcquireTokenSilent(graphResourceID, clientcred, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
return result.AccessToken;
}
catch (Exception e)
{
// Capture error for handling outside of catch block
ErrorMessage = e.Message;
return null;
}
}
Подробнее здесь: https://stackoverflow.com/questions/447 ... vc-web-app
Мобильная версия