I'm using openiddict 2.0.1 with aspnet.core 2.0
This is my only option since paypal support for .net core is stopped at 2.0 so far.
So my problem is, for example: http://localhost:83917/connect/token will spit out access_token in a local environment, but when it's deployed to production in Azure, (https://api.blabla.com/connect/token) I get HTTPS error:
This server only accepts HTTPS requests.
Startup.cs published in production
public class Startup
{
private readonly string _appSettingsEnv;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
// Get value from Azure's App Settings when deployed. Debug (local) mode gets value from appsettings.json
_appSettingsEnv = Configuration["APPSETTINGS:ENVIRONMENT"];
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add database configurations
services.AddDbContext<PayPalContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("DemoConnection"));
options.UseOpenIddict();
});
// Add membership
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
// Password settings
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequiredLength = 5;
options.User.RequireUniqueEmail = true;
options.SignIn.RequireConfirmedEmail = false;
})
.AddEntityFrameworkStores<PayPalContext>()
.AddDefaultTokenProviders();
// Register the OAuth2 validation handler.
services.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Audience = "resource_server";
options.Authority = "https://api.blabla.com/";
options.RequireHttpsMetadata = true;
options.IncludeErrorDetails = true;
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = OpenIdConnectConstants.Claims.Subject,
RoleClaimType = OpenIdConnectConstants.Claims.Role
};
});
// Configure Identity to use the same JWT claims as OpenIddict instead
// of the legacy WS-Federation claims it uses by default (ClaimTypes),
// which saves you from doing the mapping in your authorization controller.
services.Configure<IdentityOptions>(options =>
{
options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
options.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject;
options.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role;
});
services.AddOpenIddict()
// Register the OpenIddict core services.
.AddCore(options =>
{
// Register the Entity Framework stores and models.
options.UseEntityFrameworkCore()
.UseDbContext<PayPalContext>();
})
// Register the OpenIddict server handler.
.AddServer(options =>
{
options.UseMvc();
options.EnableTokenEndpoint("/connect/token");
options.AllowPasswordFlow();
options.AcceptAnonymousClients();
options.UseJsonWebTokens();
options.AddEphemeralSigningKey();
});
services.AddCors();
services.AddMvc()
.AddJsonOptions(opts =>
{
// Force Camel Case to JSON
opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
// Without this controller actions are not forbidden if other roles are trying to access
services.AddSingleton<IAuthenticationSchemeProvider, CustomAuthenticationSchemeProvider>();
services.AddSingleton(Configuration);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();
app.UseStaticFiles();
app.UseCors(builder =>
{
builder.AllowAnyOrigin();
builder.AllowAnyHeader();
builder.AllowAnyMethod();
builder.AllowCredentials();
});
app.UseExceptionHandler(builder =>
{
builder.Run(async context =>
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
var error = context.Features.Get<IExceptionHandlerFeature>();
if (error != null)
{
//context.Response.AddApplicationError(error.Error.Message);
await context.Response.WriteAsync(error.Error.Message).ConfigureAwait(false);
}
});
});
app.UseAuthentication();
app.UseMvcWithDefaultRoute();
app.UseWelcomePage();
}
}
Is there anything that I need to add in Startup.cs?
For some reasons, ASP.NET Core doesn't infer the correct scheme, that OpenIddict uses to determine whether the request uses transport security or not. Read https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-3.1 for options to mitigate that.
@PinpointTownes Thanks for the guidance. According to the article, I believe I need to use app.UseCertificateForwarding(); but this is not supported in .net core 2.0. Am I really the only person who's encountering this issue? people must have faced the similar issue before, but I can't find the resolution :(
No, that extension is for client certificates, it has nothing to do with server authentication. It's meant for people who use mutual or client authentication, you don't need it.
Ok. I think this can be related to TLS/SSL binding in my server app. I binded private certificate with a custom domain. (ex: api.blabla.com). What do you think?
I think https://github.com/aspnet/AspNetCore would be a more appropriate place for non-OpenIddict-specific questions 馃槃
Alright, so is it transport security related? I just wanna narrow it down so they can understand what I'm asking.
ASP.NET Core doesn't infer the correct scheme, that OpenIddict uses to determine whether the request uses transport security
Yes, it's a classical SSL/TLS issue.