Нашей универсальной ОС Windows App однопользовательский клиент использует Web API ASP.NET 2 в качестве прокси-сервера для однократная подписка на различные API-интерфейсы Microsoft Office 365. Мы используем Active Directory для аутентификации сервера и от имени модели единого входа на нашем сервере для обмена токенами для API Office 365.
Проблема:
Мы обновили объем разрешений на Azure для Office 365 API, и пользователь не будет предложено разрешить разрешение на новую область видимости, не является новая область появляется на новых маркеров. Что необходимо сделать для ОБНАРУЖЕНИЯ и РАЗРЕШЕНИЯ наших пользователей для авторизации новых областей разрешений?
Дополнительные детали:
- Наш сервер размещен в MSFT Azure App Services. Я понимаю, что манифест в Azure автогенерируется и не нуждается в обновлении вручную, чтобы отразить обновленную область полномочий?
- Когда пользователь впервые регистрируется в приложении UWP, они согласны с разрешениями на единую регистрацию, связанными с сервером (например, Mail.ReadWrite и т. Д.), Который отлично работает. Тем не менее, пользовательское приглашение пользователя не появляется снова, даже после того, как я удалил как клиентские, так и серверные приложения из своего списка с согласия на приложения с помощью
- Мы используем библиотеки клиентов
WebTokenRequest
и , чтобы получить токен для сервер. Я также попытался использоватьWebAuthenticationBroker
(что не является правильным методом для нашей архитектуры входа) и библиотеки ADAL в нашем клиенте. Ни одна из этих библиотек не запрашивает обновленное разрешение. - Я также попытался добавить
wtf.Properties.Add("prompt", "consent");
к нашемуWebTokenRequest
, чтобы заставить пользователя повторно одобрить разрешения. Это не работает. - Я также попытался перезапустить службу приложений в Azure. Это ничего не делает.
ОБНОВЛЕНО 11/10/16: Ниже соответствующий код я вытащил из нашего приложения архитектуры, которая может помочь. Кроме того, наш сервер использует ADAL версию 2.24.304111323.
В нашем UWP приложения:
public class AppAuth
{
WebTokenRequestResult result;
WebAccount acc;
async Task<WebTokenRequestResult> GetTokenAsync(WebTokenRequestPromptType promptType = WebTokenRequestPromptType.Default)
{
var wtr = new WebTokenRequest(
provider: "https://login.windows.net",
scope: "",
clientId: appClientId,
promptType: promptType
);
wtr.Properties.Add("authority", "https://login.windows.net");
wtr.Properties.Add("resource", azureWebsiteUrl);
if (promptType != WebTokenRequestPromptType.ForceAuthentication)
{
result = (acc == null) ?
await WebAuthenticationCoreManager.GetTokenSilentlyAsync(wtr) :
await WebAuthenticationCoreManager.GetTokenSilentlyAsync(wtr, acc);
}
if (promptType == WebTokenRequestPromptType.ForceAuthentication ||
result?.ResponseStatus == WebTokenRequestStatus.UserInteractionRequired)
{
result = (acc == null) ?
await WebAuthenticationCoreManager.RequestTokenAsync(wtr) :
await WebAuthenticationCoreManager.RequestTokenAsync(wtr, acc);
}
return result;
}
}
В нашем сервере:
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
TokenValidationParameters = new TokenValidationParameters
{
SaveSigninToken = true,
ValidateIssuer = false,
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"]
}
});
}
}
public class TokenChange
{
protected AdUser _user;
private UserAssertion _assertion;
private static string _aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
private static string _tenant = ConfigurationManager.AppSettings["ida:Tenant"];
private static string _clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private static string _appKey = ConfigurationManager.AppSettings["ida:AppKey"];
private string _accessToken;
public AuthenticationResult AuthResult { get; set; }
public AdalException AuthException { get; set; }
private string _emailAddress;
private HttpClient _httpClient;
public bool Authenticate()
{
_accessToken = null;
if (ClaimsPrincipal.Current.Identity.IsAuthenticated)
{
var bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext
as System.IdentityModel.Tokens.BootstrapContext;
if (bootstrapContext != null)
{
Claim subject = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier);
var upn = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn);
var email = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email);
var userName = upn != null ? upn.Value : email?.Value;
_emailAddress = ClaimsPrincipal.Current.Identity.Name;
var userNameClaim = ClaimsPrincipal.Current.FindFirst("name");
_fullName = userNameClaim != null ? userNameClaim.Value : String.Empty;
_accessToken = bootstrapContext.Token;
_assertion = new UserAssertion(_accessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName);
}
}
return _accessToken != null;
}
public bool GetAccess(string apiResource)
{
bool gotAccess = false;
AuthResult = null;
AuthException = null;
if (_accessToken != null || Authenticate())
{
ClientCredential clientCred = new ClientCredential(_clientId, _appKey);
string authority = String.Format(CultureInfo.InvariantCulture, _aadInstance, _tenant);
AuthenticationContext authContext = new AuthenticationContext(authority);
bool retry = false;
int retryCount = 0;
do
{
retry = false;
try
{
AuthResult = authContext.AcquireToken(apiResource, clientCred, _assertion);
}
catch (AdalException ex)
{
AuthException = ex;
if (ex.ErrorCode == "temporarily_unavailable")
{
retry = true;
retryCount++;
Thread.Sleep(500);
}
else
{
throw (ex);
}
}
} while ((retry == true) && (retryCount < 1));
if (AuthResult != null && AuthResult.AccessToken != null)
{
gotAccess = true;
}
}
return gotAccess;
}
Сначала это кажется немного спамным, но я не помещаю его как таковой, потому что он явно содержит вопрос программирования и, кажется, ничего не продвигает. Я бы посоветовал отредактировать его, чтобы он выглядел менее спам. – RamenChef