I'm working on implementing OAuth in an ASP.NET Core (using .NET 5, Razor Pages) application. I'm encountering an error, but I don't quite understand what it's telling me.
Background Info
I haven't gotten the OAuth implementation to work yet, so even if I am able to get it to work and resolve this error, I'm not convinced that I have everything set up perfectly. If you have any tips on things I could improve it would be greatly appreciated!
For reference, I've only been trying to work with OAuth for a few days, and I don't have any prior experience in authentication/authorization. I have read a few guides though, which I'll mention at the end of my post here.
I've included details on the following:
- the exception message and the stack trace
- my code
- my thoughts
- references
The Error
Exception: The oauth state was missing or invalid.
Stack Trace:
System.Exception: An error was encountered while handling the remote login.
---> System.Exception: The oauth state was missing or invalid.
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
My Code
- I'm not sure how private the information relating to my company's implementation of OAuth is, so I've omitted details that could identify the company just to be safe.
Startup.cs ConfigureServices()
- only including portion that relates to OAuth2
public void ConfigureServices(IServiceCollection services)
{
// OAuth2 Authentication
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "MyCompanyAuthenticationScheme";
}).AddCookie(options =>
{
options.Cookie.IsEssential = true;
}).AddOAuth("MyCompanyAuthenticationScheme", options =>
{
options.ClientId = Configuration["Company:ClientId"];
options.ClientSecret = Configuration["Company:ClientSecret"];
options.CallbackPath = new PathString("/Auth/Login");
options.AuthorizationEndpoint = "...";
options.TokenEndpoint = "...";
options.UserInformationEndpoint = "...";
// todo: are all three of these necessary?
options.Scope.Add("loginAccountInfo");
options.Scope.Add("contactInfo");
options.Scope.Add("employeeInfo");
options.SaveTokens = true;
// todo: are the jsonKeys defined in the above Scopes? follow up when you have a better understanding of how these work, or if the MapJsonKey lines are even necessary
options.ClaimActions.MapJsonKey(ClaimTypes.Name, "firstName");
options.ClaimActions.MapJsonKey(ClaimTypes.Email, "emailAddress");
});
}
Startup.cs Configure()
- again only included relevant sections of code
- the important piece is that I do include
app.UseAuthentication()
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
});
}
Auth controller:
[AllowAnonymous]
[Route("[controller]/[action]")]
public class AuthController : Controller
{
[HttpGet]
public IActionResult Login(string returnUrl = "/")
{
if(!User.Identity.IsAuthenticated)
return Challenge(new AuthenticationProperties() { RedirectUri = returnUrl});
return Forbid();
}
}
I think this is all of the relevant code relating to OAuth, but if you think I need to include more details let me know!
My Thoughts
- I think the issue is something with my
options.CallbackPathdefined in Startup.cs ConfigureServices(), under services.AddOAuth().- I've seen some posts detailing that I don't need to set this variable, but in those posts it seems that they're implementing OAuth for a provider (such as Google, GitHub, Facebook, etc) that has a NuGet package in which
options.CallbackPathis defined ahead of time. - I've also seen some information saying that
options.CallbackPathis used internally by the OAuth middleware, and that it doesn't correspond to a controller action (which means I wouldn't need my Auth controller and its Login action). However, if I remove the line definingoptions.CallbackPath, I get another error saying that it isn't defined, leading me to believe that it is very necessary.
- I've seen some posts detailing that I don't need to set this variable, but in those posts it seems that they're implementing OAuth for a provider (such as Google, GitHub, Facebook, etc) that has a NuGet package in which
References
- I used this website initially to gain background info on what OAuth is and how it works.
- I used this guide as a reference when setting up OAuth in this application.
- Before asking my question, I looked at and considered these existing StackOverflow posts, but wasn't able to find an answer: