多租户Azure移动应用程序服务呼叫因401.71失败
在此之前,我是Azure编程和Azure广告认证的新手,我一直在遵循我在各个网站(包括MS)找到的教程,以达到这一目的。我正在使用Xcode v7.2、iOS版本1.2.4的ADAL、Visual Studio 2015更新1和Azure应用程序服务工具v2.8.1 我有一个现有的本机iOS应用程序,我需要能够通过它对多个Azure Active Directory实例用户进行身份验证。这些用户包括内部用户和外部用户(注册我们服务的客户)。为此,我在实验中实现了以下高级体系结构: 本机客户端应用程序(iOS/obj-c)->ADAL iOS库->(Azure AD身份验证)->Azure移动应用程序(服务层) iOS应用程序利用ADAL iOS库获取访问令牌,用于调用Azure移动应用程序项目中的授权Web API服务 我能够对来自两个租户(内部Azure AD和外部Azure AD)的用户进行身份验证,但只有与服务(内部)位于同一租户中的用户才能调用经过身份验证的API。我从外部租户使用的测试用户帐户设置为全局管理员,在进行身份验证时,我会在本机应用程序中看到相应的同意视图。然后,我可以点击同意,并收到一个访问令牌。然而,当使用该令牌调用测试API时,我得到了一个401。服务器上Azure移动应用程序的详细日志显示以下消息(以下所有URL均为https,我只是没有代表将其发布为https): MobileApp的代码——这应该是股票,由Azure Mobile App项目模板生成:多租户Azure移动应用程序服务呼叫因401.71失败,azure,azure-active-directory,adal,azure-mobile-services,Azure,Azure Active Directory,Adal,Azure Mobile Services,在此之前,我是Azure编程和Azure广告认证的新手,我一直在遵循我在各个网站(包括MS)找到的教程,以达到这一目的。我正在使用Xcode v7.2、iOS版本1.2.4的ADAL、Visual Studio 2015更新1和Azure应用程序服务工具v2.8.1 我有一个现有的本机iOS应用程序,我需要能够通过它对多个Azure Active Directory实例用户进行身份验证。这些用户包括内部用户和外部用户(注册我们服务的客户)。为此,我在实验中实现了以下高级体系结构: 本机客户端应用
// Startup.MobileApp.cs
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.Entity;
using System.Web.Http;
using Microsoft.Azure.Mobile.Server;
using Microsoft.Azure.Mobile.Server.Authentication;
using Microsoft.Azure.Mobile.Server.Config;
using MyAzureMobileApp.DataObjects;
using MyAzureMobileApp.Models;
using Owin;
namespace MyAzureMobileApp
{
public partial class Startup
{
public static void ConfigureMobileApp(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
new MobileAppConfiguration()
.UseDefaultConfiguration()
.ApplyTo(config);
// Use Entity Framework Code First to create database tables based on your DbContext
Database.SetInitializer(new MobileServiceInitializer());
MobileAppSettingsDictionary settings = config.GetMobileAppSettingsProvider().GetMobileAppSettings();
if (string.IsNullOrEmpty(settings.HostName))
{
app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions
{
// This middleware is intended to be used locally for debugging. By default, HostName will
// only have a value when running in an App Service application.
SigningKey = ConfigurationManager.AppSettings["SigningKey"],
ValidAudiences = new[] { ConfigurationManager.AppSettings["ValidAudience"] },
ValidIssuers = new[] { ConfigurationManager.AppSettings["ValidIssuer"] },
TokenHandler = config.GetAppServiceTokenHandler()
});
}
app.UseWebApi(config);
}
}
public class MobileServiceInitializer : CreateDatabaseIfNotExists<MobileServiceContext>
{
protected override void Seed(MobileServiceContext context)
{
List<TodoItem> todoItems = new List<TodoItem>
{
new TodoItem { Id = Guid.NewGuid().ToString(), Text = "First item", Complete = false },
new TodoItem { Id = Guid.NewGuid().ToString(), Text = "Second item", Complete = false }
};
foreach (TodoItem todoItem in todoItems)
{
context.Set<TodoItem>().Add(todoItem);
}
base.Seed(context);
}
}
}
服务实现:
using System.Web.Http;
using Microsoft.Azure.Mobile.Server.Config;
namespace MyAzureMobileApp.Controllers
{
// Use the MobileAppController attribute for each ApiController you want to use
// from your mobile clients
[MobileAppController]
// Use the MobileAppController attribute for each ApiController you want to use
// from your mobile clients
[Authorize]
public class ValuesController : ApiController
{
// GET api/values
public string Get()
{
return "GET returned: Hello World!";
}
// POST api/values
public string Post()
{
return "POST returned: Hello World!";
}
}
}
和web.config中的my appSettings部分:
<appSettings>
<add key="PreserveLoginUrl" value="true" />
<!-- Use these settings for local development. After publishing to your
Mobile App, these settings will be overridden by the values specified
in the portal. -->
<add key="MS_SigningKey" value="Overridden by portal settings" />
<add key="EMA_RuntimeUrl" value="Overridden by portal settings" />
<!-- When using this setting, be sure to add matching Notification Hubs connection
string in the connectionStrings section with the name "MS_NotificationHubConnectionString". -->
<add key="MS_NotificationHubName" value="Overridden by portal settings" />
<add key="ida:ClientId" value="-- MyAzureMobileApp App ID from Azure AD --" />
<add key="ida:Tenant" value="InternalTestAD.onmicrosoft.com" />
<add key="ida:Audience" value="https://InternalTestAD.onmicrosoft.com/MyAzureMobileApp" />
<add key="ida:Password" value="-- password value removed --" />
</appSettings>
除了作为WindowsAzureActiveDirectoryBeareAuthenticationOptions中TokenValidationParameters集合的属性外,我看不到指定有效令牌颁发者的位置
根据我对代码的理解,我应该禁用颁发者验证,但我已尝试在此处添加外部Azure AD STS URL。不幸的是,它似乎没有任何效果
有人知道这段代码是否因为某种原因被忽略或重写了吗?我是否错过了其他设置来完全禁用颁发者验证,或指定有效颁发者的列表
我当然可以按要求提供更多信息,但我不确定还有什么相关信息
谢谢 我相信我已经找到了我的验证逻辑被忽略的原因。在Azure App Services中设置我的web api站点时,我通过在“身份验证/授权”>“Azure Active Directory设置”刀片中填充颁发者URL文本框来指定主要租户颁发者URL。事实证明,当您有多个发卡机构时(如在我的多租户场景中)您应该将此字段留空 JWT将针对您在该文本框中提供的发行人进行验证,这是非常合理的。对我来说,不那么直观的是,当您有多个发行人时,应该将其留空。也许微软可以把它添加到上面的信息泡沫中?或者提供一些允许多个颁发者URL的机制
希望这能为其他人在这个问题上节省一些时间。只想指出,如果您已经配置了身份验证,并且设置了主租户颁发者URL,然后关闭了这种类型的身份验证,API仍然会从中读取。清除这个字段对我来说很有效,尽管我从未想过会这样,因为我不再使用广告认证
// Startup.Auth.cs
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IdentityModel.Tokens;
using System.Linq;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.ActiveDirectory;
using Owin;
namespace MyAzureMobileApp
{
public partial class Startup
{
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = new TokenValidationParameters()
{
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"],
ValidateIssuer = false
}
});
}
}
}
using System.Web.Http;
using Microsoft.Azure.Mobile.Server.Config;
namespace MyAzureMobileApp.Controllers
{
// Use the MobileAppController attribute for each ApiController you want to use
// from your mobile clients
[MobileAppController]
// Use the MobileAppController attribute for each ApiController you want to use
// from your mobile clients
[Authorize]
public class ValuesController : ApiController
{
// GET api/values
public string Get()
{
return "GET returned: Hello World!";
}
// POST api/values
public string Post()
{
return "POST returned: Hello World!";
}
}
}
<appSettings>
<add key="PreserveLoginUrl" value="true" />
<!-- Use these settings for local development. After publishing to your
Mobile App, these settings will be overridden by the values specified
in the portal. -->
<add key="MS_SigningKey" value="Overridden by portal settings" />
<add key="EMA_RuntimeUrl" value="Overridden by portal settings" />
<!-- When using this setting, be sure to add matching Notification Hubs connection
string in the connectionStrings section with the name "MS_NotificationHubConnectionString". -->
<add key="MS_NotificationHubName" value="Overridden by portal settings" />
<add key="ida:ClientId" value="-- MyAzureMobileApp App ID from Azure AD --" />
<add key="ida:Tenant" value="InternalTestAD.onmicrosoft.com" />
<add key="ida:Audience" value="https://InternalTestAD.onmicrosoft.com/MyAzureMobileApp" />
<add key="ida:Password" value="-- password value removed --" />
</appSettings>