简体   繁体   中英

ASP.NET Core OAuth2 implementation using company provider. Exception: The oauth state was missing or invalid

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.CallbackPath defined 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.CallbackPath is defined ahead of time.
    • I've also seen some information saying that options.CallbackPath is 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 defining options.CallbackPath , I get another error saying that it isn't defined, leading me to believe that it is very necessary.

References

options.CallbackPath = new PathString("/Auth/Login");

If you have a controller action bound to /Auth/Login , this should be the source of the issue.

The vale of options.CallbackPath doesn't have to match any controller action. It is an internal route where the middleware receives the answer of the Identity provider. You can simply assign /callback as its value or any other value that doesn't match an existing route

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM