{"action":"created","issue":{"url":"https://api.github.com/repos/aspnet/Home/issues/3027","repository_url":"https://api.github.com/repos/aspnet/Home","labels_url":"https://api.github.com/repos/aspnet/Home/issues/3027/labels{/name}","comments_url":"https://api.github.com/repos/aspnet/Home/issues/3027/comments","events_url":"https://api.github.com/repos/aspnet/Home/issues/3027/events","html_url":"https://github.com/aspnet/Home/issues/3027","id":311568992,"node_id":"MDU6SXNzdWUzMTE1Njg5OTI=","number":3027,"title":"Asp.net core 2 + Antiforgery: all POST endpoints return 400 Bad Request","user":{"login":"Corstiaan84","id":3714933,"node_id":"MDQ6VXNlcjM3MTQ5MzM=","avatar_url":"https://avatars3.githubusercontent.com/u/3714933?v=4","gravatar_id":"","url":"https://api.github.com/users/Corstiaan84","html_url":"https://github.com/Corstiaan84","followers_url":"https://api.github.com/users/Corstiaan84/followers","following_url":"https://api.github.com/users/Corstiaan84/following{/other_user}","gists_url":"https://api.github.com/users/Corstiaan84/gists{/gist_id}","starred_url":"https://api.github.com/users/Corstiaan84/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Corstiaan84/subscriptions","organizations_url":"https://api.github.com/users/Corstiaan84/orgs","repos_url":"https://api.github.com/users/Corstiaan84/repos","events_url":"https://api.github.com/users/Corstiaan84/events{/privacy}","received_events_url":"https://api.github.com/users/Corstiaan84/received_events","type":"User","site_admin":false},"labels":[{"id":792347695,"node_id":"MDU6TGFiZWw3OTIzNDc2OTU=","url":"https://api.github.com/repos/aspnet/Home/labels/repo:Antiforgery","name":"repo:Antiforgery","color":"5319e7","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":9,"created_at":"2018-04-05T11:14:39Z","updated_at":"2018-09-25T22:14:35Z","closed_at":null,"author_association":"NONE","body":"I have an asp.net core 2.1.4 app with a custom IXmlRepository to store the app keys using ef core + postgres. I deploy the app using Docker.\r\n\r\nEverything deploys and run fine except that all POST request return a 400 bad request response when running in Production. All is fine in Development.\r\n\r\nThe problem is related to the setup of the antiforgery/dataprotection settings, I think\r\n\r\nThis is my Startup.cs when I config the DataProtection and Antiforgery stuff. I have redacted it minimal just in case some other settings might be interfering.\r\n\r\n    public class Startup\r\n    {\r\n        IHostingEnvironment _env;\r\n\r\n        public Startup(IConfiguration configuration, IHostingEnvironment env)\r\n        {\r\n            Configuration = configuration;\r\n            _env = env;\r\n        }\r\n\r\n        public IConfiguration Configuration { get; }\r\n\r\n        // This method gets called by the runtime. Use this method to add services to the container.\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            services.AddDbContext<AppDbContext>(options =>\r\n                options.UseNpgsql(Configuration.GetConnectionString(\"DefaultConnection\"))\r\n            );\r\n\r\n            services.AddIdentity<User, Role>()\r\n            .AddEntityFrameworkStores<AppDbContext>()\r\n            .AddDefaultTokenProviders();\r\n\r\n            services.Configure<IdentityOptions>(options =>\r\n            {\r\n                // Password settings\r\n                options.Password.RequireDigit = true;\r\n                options.Password.RequiredLength = 8;\r\n                options.Password.RequireNonAlphanumeric = false;\r\n                options.Password.RequireUppercase = true;\r\n                options.Password.RequireLowercase = false;\r\n                options.Password.RequiredUniqueChars = 6;\r\n\r\n                // Lockout settings\r\n                options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);\r\n                options.Lockout.MaxFailedAccessAttempts = 10;\r\n                options.Lockout.AllowedForNewUsers = true;\r\n\r\n                // User settings\r\n                options.User.RequireUniqueEmail = true;\r\n            });\r\n\r\n            ### HERE I SET THE CUSTOM KEY STORE ###\r\n\r\n            services.AddSingleton<IXmlRepository, EfXmlRepository>();\r\n            var sp = services.BuildServiceProvider();\r\n            services.AddDataProtection()\r\n                    .AddKeyManagementOptions(options => options.XmlRepository = sp.GetService<IXmlRepository>());\r\n\r\n            services.AddMvc(options =>\r\n            {\r\n                options.OutputFormatters.Add(new HtmlOutputFormatter());\r\n                options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());\r\n            });\r\n\r\n            ### HERE I SET THE ANTI FORGERY HEADER FOR SOME API CALLS ###\r\n\r\n            services.AddAntiforgery(x => x.HeaderName = \"X-XSRF-TOKEN\");\r\n\r\n            services.AddAuthentication()\r\n            .AddCookie()         \r\n            .AddJwtBearer(options =>\r\n            {\r\n                options.TokenValidationParameters = new TokenValidationParameters\r\n                {\r\n                    ValidateIssuer = true,\r\n                    ValidateAudience = true,\r\n                    ValidateIssuerSigningKey = true,\r\n                    ValidIssuer = \"myapp.com\",\r\n                    ValidAudience = \"myapp.com\",\r\n                    RequireExpirationTime = false,\r\n                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration[\"SecurityKey\"]))\r\n                };\r\n            });;\r\n\r\n            services.AddTransient<JwtService>();\r\n            services.AddTransient<PaymentProviderService>();\r\n            services.AddTransient<SubscriptionService>();\r\n            services.AddTransient<IInvalidJwtTokenStore, EfInvalidJwtTokenStore>();\r\n\r\n            //setup hangfire\r\n            GlobalConfiguration.Configuration.UsePostgreSqlStorage(Configuration.GetConnectionString(\"DefaultConnection\"));\r\n\r\n        }\r\n\r\n        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\r\n        public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IHostingEnvironment env)\r\n        {\r\n            if (env.IsDevelopment())\r\n            {\r\n                app.UseDeveloperExceptionPage();\r\n            }\r\n            else\r\n            {\r\n                app.UseExceptionHandler(\"/Home/Error\");\r\n            }\r\n\r\n            app.UseStaticFiles();\r\n            app.UseAuthentication();\r\n\r\n            app.UseMvc(\r\n                routes =>\r\n                {\r\n                    routes.MapRoute(\r\n                        name: \"default\",\r\n                        template: \"{controller=Home}/{action=Index}/{id?}\");\r\n                }\r\n            );\r\n\r\n            loggerFactory.AddConsole(LogLevel.Information);\r\n        }\r\n\r\nThis is my ef core IXmlRepository implementation:\r\n\r\n    public class EfXmlRepository : IXmlRepository\r\n    {\r\n        AppDbContext _db;\r\n\r\n        public EfXmlRepository(AppDbContext dbContext)\r\n        {\r\n            _db = dbContext;\r\n        }\r\n\r\n        public IReadOnlyCollection<XElement> GetAllElements()\r\n        {\r\n            var list = _db.XmlKeys.ToList().Select(x => XElement.Parse(x.Xml)).ToList();\r\n            return list;\r\n        }\r\n\r\n        public void StoreElement(XElement element, string friendlyName)\r\n        {\r\n            _db.XmlKeys.Add(new XmlKey\r\n            {\r\n                Xml = element.ToString(SaveOptions.DisableFormatting)\r\n            });\r\n\r\n            _db.SaveChanges();\r\n        }\r\n    }\r\n\r\nAt an earlier stage the logs told me this:\r\n\r\n    2018-04-04T18:05:58.950344099Z app[web.1]: fail: \r\n    Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgery[7]\r\n    2018-04-04T18:05:58.950392982Z app[web.1]:       An exception was \r\n    thrown while deserializing the token.\r\n    2018-04-04T18:05:58.950398037Z app[web.1]: \r\n    System.InvalidOperationException: The antiforgery token could not be \r\n    decrypted. ---> System.Security.Cryptography.CryptographicException: \r\n    The key {9b8ab2d0-3ca5-4fcd-af54-b1a6601077af} was not found in the key \r\n    ring.\r\n\r\nBut this error disappeared when I tweaked the postgres settings for the IXmlRepository.\r\n\r\nJust in case this is my Dockerfile\r\n\r\n    FROM microsoft/dotnet:latest\r\n    COPY . /app\r\n    WORKDIR /app\r\n\r\n    ENV ASPNETCORE_URLS http://0.0.0.0:5000\r\n    ENV ASPNETCORE_ENVIRONMENT Production\r\n    EXPOSE 5000\r\n\r\n    RUN dotnet restore\r\n    RUN dotnet publish -c Release\r\n\r\n    WORKDIR /app/MyApp.Web\r\n    RUN dotnet ef database update\r\n\r\n    WORKDIR /app/MyApp.Web/bin/Release/netcoreapp2.0/publish\r\n    ENTRYPOINT dotnet MyApp.Web.dll\r\n\r\nLooking forward ot hearing your thoughts. Thanks!"},"comment":{"url":"https://api.github.com/repos/aspnet/Home/issues/comments/424519772","html_url":"https://github.com/aspnet/Home/issues/3027#issuecomment-424519772","issue_url":"https://api.github.com/repos/aspnet/Home/issues/3027","id":424519772,"node_id":"MDEyOklzc3VlQ29tbWVudDQyNDUxOTc3Mg==","user":{"login":"mkArtakMSFT","id":34246760,"node_id":"MDQ6VXNlcjM0MjQ2NzYw","avatar_url":"https://avatars3.githubusercontent.com/u/34246760?v=4","gravatar_id":"","url":"https://api.github.com/users/mkArtakMSFT","html_url":"https://github.com/mkArtakMSFT","followers_url":"https://api.github.com/users/mkArtakMSFT/followers","following_url":"https://api.github.com/users/mkArtakMSFT/following{/other_user}","gists_url":"https://api.github.com/users/mkArtakMSFT/gists{/gist_id}","starred_url":"https://api.github.com/users/mkArtakMSFT/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mkArtakMSFT/subscriptions","organizations_url":"https://api.github.com/users/mkArtakMSFT/orgs","repos_url":"https://api.github.com/users/mkArtakMSFT/repos","events_url":"https://api.github.com/users/mkArtakMSFT/events{/privacy}","received_events_url":"https://api.github.com/users/mkArtakMSFT/received_events","type":"User","site_admin":false},"created_at":"2018-09-25T22:14:35Z","updated_at":"2018-09-25T22:14:35Z","author_association":"NONE","body":"Thanks for contacting us, @Corstiaan84.\r\n@javiercn, can you please look into this? Thanks!\r\n"}}
{"actor":{"display_login":"mkArtakMSFT"}}