通过 AWS EC2 上的 Docker 容器发布时,Auth0 OWIN API 未验证 JWT 令牌
Posted
技术标签:
【中文标题】通过 AWS EC2 上的 Docker 容器发布时,Auth0 OWIN API 未验证 JWT 令牌【英文标题】:Auth0 OWIN API not validating JWT token when published via Docker Container on AWS EC2 【发布时间】:2017-06-25 04:16:33 【问题描述】:托管在 EC2 上的我的 OWIN Web.API 2 不会授权 JWT 令牌。我已经在本地测试了该功能,没有出现问题,但是一旦我将其发布到托管在 EC2 上的 docker 容器,它就会以 401 响应。我使用的是默认的 RS256 算法和这些设置:
var domain = Environment.GetEnvironmentVariable("AUTH0_DOMAIN");
var audience = Environment.GetEnvironmentVariable("AUTH0_CLIENT_IDS");
var keyResolver = new OpenIdConnectSigningKeyResolver(domain);
appBuilder.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] audience ,
TokenValidationParameters = new TokenValidationParameters()
ValidAudience = audience,
ValidIssuer = domain,
IssuerSigningKeyResolver = (token, securityToken, identifier, parameters) => keyResolver.GetSigningKey(identifier)
);
My Endpoint 仅说明您是否已通过身份验证。
[Authorize]
[Route("secure")]
public HttpResponseMessage GetSecured()
var userId = ClaimsPrincipal.Current.Identity.GetUserId();
return Request.CreateResponse($"Hello, userId! You are currently authenticated.");
这是我的启动配置:
public void Configuration(IAppBuilder appBuilder)
appBuilder.UseCors(CorsOptions.AllowAll); //must be first
Auth0Config.Register(appBuilder);
var httpConfiguration = new HttpConfiguration();
httpConfiguration.MapHttpAttributeRoutes();
UnityConfig.Register(httpConfiguration);
appBuilder.UseWebApi(httpConfiguration);
【问题讨论】:
我过去曾多次遇到此问题,通常归结为配置设置不正确。检查域是否正确(带有尾随的“/”)以及您的其他设置。还要确保您是否从已启用 CORS 的其他域(Angular SPA 等)调用此端点。 我已经确定我有斜杠,并在我的问题中添加了我的启动配置。 【参考方案1】:我不再使用 OWIN 管道,但在以前的项目中,这是我配置它的方式。看起来你正在使用 OpenID,我没有。不确定这是否有帮助。
var issuer = AppSettings.Auth0Domain;
var audience = AppSettings.Auth0ClientID;
var secret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["Auth0ClientSecret"]);
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] audience,
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
,
Provider = new Auth0AuthenticationProvider()
);
编辑添加了 Auth0AuthenticationProvider
public class Auth0AuthenticationProvider : IOAuthBearerAuthenticationProvider
private string token;
public Task ApplyChallenge(OAuthChallengeContext context)
return Task.FromResult<object>(null);
public Task RequestToken(OAuthRequestTokenContext context)
token = context.Token;
return Task.FromResult<object>(null);
public Task ValidateIdentity(OAuthValidateIdentityContext context)
if (string.IsNullOrEmpty(token))
return Task.FromResult<object>(null);
var notPadded = token.Split('.')[1];
var padded = notPadded.PadRight(notPadded.Length + (4 - notPadded.Length % 4) % 4, '=');
var urlUnescaped = padded.Replace('-', '+').Replace('_', '/');
var claimsPart = Convert.FromBase64String(urlUnescaped);
var obj = JObject.Parse(Encoding.UTF8.GetString(claimsPart, 0, claimsPart.Length));
// simple, not handling specific types, arrays, etc.
foreach (var prop in obj.Properties().AsJEnumerable())
switch (prop.Name)
case "app_metadata":
SetAppMetadataClaims(context, prop.Value.ToString());
break;
return Task.FromResult<object>(null);
private static void SetAppMetadataClaims(OAuthValidateIdentityContext context, string jsonString)
var appMetadata = JsonConvert.DeserializeObject<Auth0AppMetaDataModel>(jsonString);
if(!context.Ticket.Identity.HasClaim("AccountId", appMetadata.accountId.ToString()))
context.Ticket.Identity.AddClaim(new Claim("AccountId", appMetadata.accountId.ToString()));
if (!context.Ticket.Identity.HasClaim("ClientId", appMetadata.clientId.ToString()))
context.Ticket.Identity.AddClaim(new Claim("ClientId", appMetadata.clientId.ToString()));
if (!context.Ticket.Identity.HasClaim("IsActive", appMetadata.isActive.ToString()))
context.Ticket.Identity.AddClaim(new Claim("IsActive", appMetadata.isActive.ToString()));
if (appMetadata.roles == null)
return;
foreach (var role in appMetadata.roles)
if (context.Ticket.Identity.HasClaim(ClaimTypes.Role, role))
continue;
context.Ticket.Identity.AddClaim(new Claim(ClaimTypes.Role, role));
【讨论】:
您的 Auth0AuthenticationProvider 是什么样的?我正在用 HS256 试试这个。 好吧,我已经尝试使用 UseJwtBearerAuthentication 切换到 RS256,我可以毫无问题地进行调试,但我在 docker compose-up 上收到错误,如下所示: System.Reflection.TargetInvocationException: Exception has been throwed by调用的目标。 ---> System.TypeLoadException: 无法使用令牌 01000042 解析类型我正在使用 mono:onbuild 作为我的图像库。【参考方案2】:问题不在于使用 HS256 或 RS256 的 Auth0,而在于我使用的基本映像。 Mono 默默地失败了,很可能阻止了我的令牌的验证。我已切换到 dotnet 核心以使用 docker 映像:microsoft/dotnet:latest
我的启动文件现在如下所示:
public void ConfigureServices(IServiceCollection services)
services.AddCors(options =>
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
);
...
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
app.UseCors("CorsPolicy");
var options = new JwtBearerOptions
Audience = Configuration["Auth0:ApiIdentifier"],
Authority = $"https://Configuration["Auth0:Domain"]/"
;
app.UseJwtBearerAuthentication(options);
...
【讨论】:
以上是关于通过 AWS EC2 上的 Docker 容器发布时,Auth0 OWIN API 未验证 JWT 令牌的主要内容,如果未能解决你的问题,请参考以下文章
AWS Elastic Beanstalk 与 EC2 容器服务 (ECS) - Docker
AWS EC2 容器服务/Elastic Beanstalk Docker 容器端口 udp 绑定
Aws ec2 实例中 docker 容器内的“Composer update”命令内存不足错误
具有 Auto Scaling 与弹性容器服务 (ECS) 的 AWS EC2 - Docker