我们有一个使用社交网络身份验证的Azure移动应用程序。尝试使用自定义令牌处理程序将用户角色添加为声明。
当在localhost上运行时,这一切都有效 - 令牌处理程序中添加了令牌,并且在调用AuthorizationAttribute OnAuthorization方法时它们可用。具有指定角色的授权属性按预期工作。
但是当运行Azure时 - 会添加声明,但是当调用OnAuthorization方法时,自定义角色声明就会消失。
以下是代码:
启动/配置类
public class OwinStartup
{
public void Configuration(IAppBuilder app)
{
var config = GlobalConfiguration.Configuration;
new MobileAppConfiguration()
.AddPushNotifications()
.ApplyTo(config);
MobileAppSettingsDictionary settings = config.GetMobileAppSettingsProvider().
GetMobileAppSettings();
app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions()
{
SigningKey = ConfigurationManager.AppSettings["authSigningKey"],
ValidAudiences = new[] { ConfigurationManager.AppSettings["authAudience"] },
ValidIssuers = new[] { ConfigurationManager.AppSettings["authIssuer"] },
TokenHandler = new AppServiceTokenHandlerWithCustomClaims(config)
});
//Authenticate stage handler in OWIN Pipeline
app.Use((context, next) =>
{
return next.Invoke();
});
app.UseStageMarker(PipelineStage.Authenticate);
}
添加角色声明的令牌处理程序
public class AppServiceTokenHandlerWithCustomClaims : AppServiceTokenHandler
{
public AppServiceTokenHandlerWithCustomClaims(HttpConfiguration config)
: base(config)
{
}
public override bool TryValidateLoginToken(
string token,
string signingKey,
IEnumerable<string> validAudiences,
IEnumerable<string> validIssuers,
out ClaimsPrincipal claimsPrincipal)
{
var validated = base.TryValidateLoginToken(token, signingKey, validAudiences, validIssuers, out claimsPrincipal);
if (validated)
{
string sid = claimsPrincipal.FindFirst(ClaimTypes.NameIdentifier).Value;
var roleProvider = UnityConfig.Container.Resolve<IRoleProvider>("RoleProvider");
var roles = roleProvider.GetUserRolesBySid(sid);
foreach (var role in roles)
{
((ClaimsIdentity)claimsPrincipal.Identity).AddClaim(new Claim(ClaimTypes.Role, role));
}
}
return validated;
}
}
角色声明 身份声明集合中的角色声明示例
{http://schemas.microsoft.com/ws/2008/06/identity/claims/role: admin}
在Web Api控制器上授权属性
[Authorize(Roles = "admin")]
对具有指定了一个或多个角色的Authorize属性的端点的每次调用都会失败(401)
在Azure中运行时,不确定声明的内容是剥离还是未在Identity中持久存在。
感谢 迈克尔
答案 0 :(得分:1)
请注意有关使用其他声明的自定义身份验证的信息。您需要使用原始令牌调用自定义API,检查令牌的有效性,然后生成带有所需声明的新令牌(zumo令牌)。然后,您可以将这些声明用于所需的任何内容。
答案 1 :(得分:0)
根据this blog post,您的一些选择可能是错误的。 AppSettings仅设置为本地调试,并且不适用于Azure。
试试这个:
public void Configuration(IAppBuilder app)
{
var config = GlobalConfiguration.Configuration;
new MobileAppConfiguration()
.AddPushNotifications()
.ApplyTo(config);
MobileAppSettingsDictionary settings = config
.GetMobileAppSettingsProvider()
.GetMobileAppSettings();
// Local Debugging
if (string.IsNullOrEmpty(settings.HostName))
{
app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions()
{
SigningKey = ConfigurationManager.AppSettings["authSigningKey"],
ValidAudiences = new[] { ConfigurationManager.AppSettings["authAudience"] },
ValidIssuers = new[] { ConfigurationManager.AppSettings["authIssuer"] },
TokenHandler = new AppServiceTokenHandlerWithCustomClaims(config)
});
}
// Azure
else
{
var signingKey = GetSigningKey();
string hostName = GetHostName(settings);
app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions
{
SigningKey = signingKey,
ValidAudiences = new[] { hostName },
ValidIssuers = new[] { hostName },
TokenHandler = new AppServiceTokenHandlerWithCustomClaims(config)
});
}
//Authenticate stage handler in OWIN Pipeline
app.Use((context, next) =>
{
return next.Invoke();
});
app.UseStageMarker(PipelineStage.Authenticate);
}
private static string GetSigningKey()
{
// Check for the App Service Auth environment variable WEBSITE_AUTH_SIGNING_KEY,
// which holds the signing key on the server. If it's not there, check for a SigningKey
// app setting, which can be used for local debugging.
string key = Environment.GetEnvironmentVariable("WEBSITE_AUTH_SIGNING_KEY");
if (string.IsNullOrWhiteSpace(key))
{
key = ConfigurationManager.AppSettings["SigningKey"];
}
return key;
}
private static string GetHostName(MobileAppSettingsDictionary settings)
{
return string.Format("https://{0}/", settings.HostName);
}