In the past 7 days I've tried to setup an ASP.NET 5 WebApi using OpenIdConnect.Server
with the resource owner flow.
I was more or less successful in generating a token and accessing [Authorize]
protected actions.
However, when I try to access this.User.Identity.Claims
, it's empty. I am using ASP.NET 5, beta6 for now (having troubles upgrading to most recent beta7 and waiting for it's official release)
In the Startup.cs I got the following:
public void ConfigureServices(IServiceCollection services)
{
services.AddCaching();
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<AuthContext>(options =>
{
options.UseSqlServer(Configuration.Get("Data:DefaultConnection:ConnectionString"));
});
services.AddIdentity<AuthUser, AuthRole>(
options => options.User = new Microsoft.AspNet.Identity.UserOptions
{
RequireUniqueEmail = true,
UserNameValidationRegex = "^[a-zA-Z0-9@_\\.-]+$"
})
.AddEntityFrameworkStores<AuthContext, Guid>()
.AddDefaultTokenProviders();
services.ConfigureCors(configure =>
{
configure.AddPolicy("CorsPolicy", builder =>
{
builder.WithOrigins("http:/localhost/", "http://win2012.bludev.com/");
});
});
services.AddScoped<IAuthRepository, AuthRepository>();
}
public void Configure(IApplicationBuilder app)
{
var factory = app.ApplicationServices.GetRequiredService<ILoggerFactory>();
factory.AddConsole();
app.UseStaticFiles();
app.UseOAuthBearerAuthentication(options =>
{
options.Authority = "http://win2012.bludev.com/api/auth/";
options.Audience = "http://win2012.bludev.com/";
options.AutomaticAuthentication = true;
options.TokenValidationParameters = new TokenValidationParameters()
{
RequireExpirationTime = true,
RequireSignedTokens = true,
RoleClaimType = ClaimTypes.Role,
NameClaimType = ClaimTypes.NameIdentifier,
ValidateActor = true,
ValidateAudience = false,
ValidateIssuer = true,
ValidateLifetime = false,
ValidateIssuerSigningKey = true,
ValidateSignature = true,
ValidAudience = "http://win2012.bludev.com/",
ValidIssuer = "http://win2012.bludev.com/"
};
});
app.UseOpenIdConnectServer(options =>
{
options.Issuer = new Uri("http://win2012.bludev.com/api/auth/");
options.AllowInsecureHttp = true;
options.AuthorizationEndpointPath = PathString.Empty;
options.Provider = new AuthorizationProvider();
options.ApplicationCanDisplayErrors = true;
// Note: in a real world app, you'd probably prefer storing the X.509 certificate
// in the user or machine store. To keep this sample easy to use, the certificate
// is extracted from the Certificate.pfx file embedded in this assembly.
options.UseCertificate(
assembly: typeof(Startup).GetTypeInfo().Assembly,
resource: "AuthExample.Certificate.pfx",
password: "Owin.Security.OpenIdConnect.Server");
});
app.UseIdentity();
app.UseMvc();
}
}
I used app.UseOAuthBearerAuthentication
because I couldn't get app.UseOpenIdConnectAuthentication
working, all I would get is this in the console:
request: /admin/user/ warning : [Microsoft.AspNet.Authentication.OpenIdConnect.OpenIdConnectAuthentica tionMiddleware] OIDCH_0004: OpenIdConnectAuthenticationHandler: message.State is null or empty. request: /.well-known/openid-configuration warning : [Microsoft.AspNet.Authentication.OpenIdConnect.OpenIdConnectAuthentica tionMiddleware] OIDCH_0004: OpenIdConnectAuthenticationHandler: message.State is null or empty.
and an Exception after the time out
error : [Microsoft.AspNet.Server.WebListener.MessagePump] ProcessRequestAsync System.InvalidOperationException: IDX10803: Unable to create to obtain configura tion from: 'http://win2012.bludev.com/api/auth/.well-known/openid-configuration' . at Microsoft.IdentityModel.Logging.LogHelper.Throw(String message, Type excep tionType, EventLevel logLevel, Exception innerException) at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.d__24.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNot ification(Task task) ...
With this configuration UseOpenIdConnectAuthentication
app.UseOpenIdConnectAuthentication(options =>
{
options.AuthenticationScheme = OpenIdConnectAuthenticationDefaults.AuthenticationScheme;
options.Authority = "http://win2012.bludev.com/api/auth/";
options.Audience = "http://win2012.bludev.com/";
options.Resource = "http://win2012.bludev.com/";
options.AutomaticAuthentication = true;
options.TokenValidationParameters = new TokenValidationParameters()
{
RequireExpirationTime = true,
RequireSignedTokens = true,
RoleClaimType = ClaimTypes.Role,
NameClaimType = ClaimTypes.NameIdentifier,
ValidateActor = true,
ValidateAudience = false,
ValidateIssuer = true,
ValidateLifetime = false,
ValidateIssuerSigningKey = true,
ValidateSignature = true
};
});
So the real question is:
- How to get resource owner flow to work with claims
ValidateLifetime = true
orValidateAudience = true
would throw exception and result in a Http Code 500 response without a printed error.- How to turn authentication failures into a meaningful 400/403 code and a json or xml respones (depending on the client preference) to be displayed for the user? (JavaScript is the client in this case)?