I am creating an ASP.NET core web API and want to integrate microsoft Azure AD authentication services. On compile-time everything works just fine. However, when I access the route meant to return a Challenge, I get a null URI Exception (Stacktrace below). I have tried specifying a challenge URI in my ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppContext>(options => options.UseSqlite("Data Source=app.db"));
// Identity/Authorization Services
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddAzureAD(options =>
{
options.ClientId = Configuration["Authentication:Microsoft:ApplicationId"];
options.ClientSecret = Configuration["Authentication:Microsoft:Password"];
options.SignedOutCallbackPath = "/api/v1/accounts/signout";
})
.AddCookie(options => options.AccessDeniedPath = "/api/v1/accounts/accessdenied");
services.AddTransient<IRecognitionService, RecognitionService>();
services.AddTransient<IProfileService, ProfileService>();
services.AddMvc();
}
I have also tried changing the redirect URI in my route:
[Route("api/v1/accounts/[action]")]
public class AccountController : Controller
{
public async Task<IActionResult> AccessDenied()
{
return Unauthorized();
}
[HttpGet]
public async Task<IActionResult> Signin()
{
return Challenge(new AuthenticationProperties {RedirectUri = "/accessdenied"},
AzureADDefaults.AuthenticationScheme);
}
}
}
I cant seem to find the root of the issue, and the stacktrace makes no sense to me:
System.ArgumentNullException: Value cannot be null.
Parameter name: uriString
at System.Uri..ctor(String uriString)
at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.<InitializeAsync>d__42.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.<GetHandlerAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationService.<ChallengeAsync>d__11.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.<ChallengeAsync>d__54.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationService.<ChallengeAsync>d__11.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.ChallengeResult.<ExecuteResultAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeResultAsync>d__20.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextResultFilterAsync>d__28`2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeResultFilters>d__26.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextResourceFilter>d__23.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeFilterPipelineAsync>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeAsync>d__16.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7.MoveNext()
I am using ASP.NET Core 2.1.1 with MVC, Cors, Azure AD, and EntityFramework There is no in-project CSHTML, as we are using a separate front end (Using VueJS)
To handle exceptions and display user friendly messages, we need to install Microsoft. AspNetCore. Diagnostics NuGet package and add middleware in the Configure() method. If you are using Visual Studio templates to create ASP.NET Core application then this package might be already installed.
UseExceptionHandler(IApplicationBuilder, Action<IApplicationBuilder>) Adds a middleware to the pipeline that will catch exceptions, log them, and re-execute the request in an alternate pipeline. The request will not be re-executed if the response has already started. UseExceptionHandler(IApplicationBuilder, String)
UseDeveloperExceptionPage(IApplicationBuilder) Captures synchronous and asynchronous Exception instances from the pipeline and generates HTML error responses.
I think the problem is because the Instance property is not set on your AzureADOptions
See this link
https://github.com/aspnet/AADIntegration/issues/34
So add, for example
.AddAzureAD(options =>
{
options.Instance = "https://login.microsoftonline.com"
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With