Passing state through authentication in ASP.NET Core
When authenticating a user, you might want to persist the state through the authentication request - for example whether the user is authenticating for some special action like organizational signup or simply some state of your application. ASP.NET Core makes this very easy.
First, you need to add the state to the request authentication request (this also works with Challenge in MVC Controller):
HttpContext.ChallengeAsync(new AuthenticationProperties(
new Dictionary<string, string>() { { "Hello,", "I am state!" } },
new Dictionary<string, object>() { { "Hello", "I am part of query!" } })
{
RedirectUri = "/success"
});
You can see we have two dictionaries in AuthenticationProperties. The first one, which populates property called Items is actual state. The second one, which is called Parameters (I am mentioning it just to clear up the confusion) is used for adding items into the query. Thanks to parameters, you can easily add prompt property to the URL or use the max_age parameter.
var properties = new OpenIdConnectChallengeProperties();
properties.MaxAge = TimeSpan.FromMinutes(1); // Require the session to be no older than 60 seconds.
Note, that there are many other AuthenticationProperties implementations like GoogleChallengeProperties, OpenIdConnectChallengeProperties etc. These are going to make working with the parameters on the IdP side really easy.
Next, we are going to look at the state. The state is persisted in Dictionary which has a string key and string value. This makes storing larger objects more complex - you have to serialize and deserialize them as needed, however, you should keep the state as small as possible, since the identity provider or their webserver can enforce certain limits like URL length. If you need to store larger amount of data and persist it across the authentication, you can leverage TempData.
Once the state gets serialized into the request it is also going to be protected so the server doesn't manipulate it. It also contains other properties like the RedirectUri for example.
Once the user authenticates and goes back to your server, you can then access the session items really easily:
var result = await HttpContext.AuthenticateAsync(OpenIdConnectDefaults.AuthenticationScheme);
var value = result.Properties.Items["Hello,"];
And there you go, you can now persist state across authentication requests.
Additionally, you should keep on mind that the properties are part of the authentication ticket (therefore stored in the authentication cookie by default) - and you should beware of its size as I previously explained in an article.
Comments
Hana Lara
You saved my day, thank you!
Eslam Mahfouz
Thank you, saved my day.
To submit comments, go to GitHub Discussions.