deathcat05
deathcat05

Reputation: 469

ASP.NET Core 3.1 OpenIDConnect message.state is null

So, I'm currently trying to test the oidc implicit flow of response_type=token in an OIDC client application I have spun up.

I can get past the /authorize request to my OIDC provider. However, when the response comes back to the signin-oidc redirect_uri in the client I get the following error:

Exception: OpenIdConnectAuthenticationHandler: message.State is null or empty.
Unknown location

Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler<TOptions>.HandleRequestAsync()

This is what the request to my authorize endpoint looks like:

GET https://localhost:44303/oauth/oidctest/authorize?client_id=...

OIDC Authorize

I'm then redirected to my OIDC Provider's /authorizelogin endpoint to accept the application. The request looks like this:

POST https://localhost:44303/oauth/oidctest/authorizelogin HTTP/1.1

authorizelogin

That returns a 302 redirect URL that looks like this:

https://localhost:5001/signin-oidc#token_type=bearer&access_token=<access-token>&scope=openid%20profile%20address%20phone%20email&expires_in=120&state=CfDJ....JDER

As you can see, the state is there for EVERY request. So I'm not sure what's going on.

Here is what my OIDC Middleware setup looks like in my ASP.NET Core client application's Startup.cs:

.AddOpenIdConnect(options =>
            {
                options.Authority = Configuration["auth:oidc:authority"];
                options.ClientId = Configuration["auth:oidc:clientid"];
                options.ClientSecret = Configuration["auth:oidc:clientsecret"];      
                options.ResponseType = OpenIdConnectResponseType.Token;
                options.GetClaimsFromUserInfoEndpoint = true;
                options.SaveTokens = true;
                options.UseTokenLifetime = true;
                options.Scope.Add("address");
                options.Scope.Add("phone");
                options.Scope.Add("email");
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidIssuer = Configuration["auth:oidc:authority"],
                    ValidAudience = Configuration["auth:oidc:clientid"],
                    ValidateIssuerSigningKey = true,
                    ClockSkew = TimeSpan.FromSeconds(3)
                };
            });

Do I need to set this state somewhere in the middleware (eventhough it looks like it sets it automatically)?

Upvotes: 1

Views: 8325

Answers (1)

K&#233;vin Chalet
K&#233;vin Chalet

Reputation: 42020

As you can see, the state is there for EVERY request. So I'm not sure what's going on.

It's a bit more complicated: if you take a closer look, you'll see the state (and the rest of the authorization response parameters) are actually part of the URL fragment, which is never sent by browsers to the remote servers they communicate with. That's why you get an error saying the state is null: the server never received it.

In your case, the authorization server you're targeting doesn't seem to support response_mode=form_post and returns the authorization response in the URL fragment, which is the native response mode for the implicit flow (response_type=token).

It's also worth noting the OIDC client middleware will never work with response_type=token as there's no identity token in this flow.

Instead, consider using response_type=code (the authorization code flow).

Upvotes: 1

Related Questions