How can I control serialization of ASP.NET Core Cookie Authentication's claims, tickets, and properties?

时间:2019-05-19 04:05:55

标签: authentication asp.net-core cookies serialization

  • I have an ASP.NET Core 2.2 MVC web-application that uses OIDC from a separate website.
  • In Startup.cs, it has:

    services
        .AddAuthentication()
        .AddCookie( "Cookies", o => ... )
        .AddOpenIdConnect( "Oidc",  o => ... );
    
  • The access_token from the ID Provider is about 800 bytes and the id_token is about 1500 bytes.

  • When the id_token is retrieved, my code parses all of the id_token claims and converts them to strongly-typed C# object properties and then generates a List<Claim> based on these properties. This List<Claim> is then passed into ASP.NET Core's SignInAsync method.
  • However, the ASP.NET Core cookie that is issued is often over 7,000 bytes (!!) and it's so big that it's spread out over 2 or 3 cookies (using ASP.NET Core's Chunked Cookies feature). This causes a problem because Chrome sometimes rejects cookies that exceed 4096 bytes.
  • I used this trick ( https://stackoverflow.com/a/55729188/159145 ) to convert the chunked cookies into a single binary which I used a hex-editor to inspect and I saw how the space was being used:
    • Each of the Claim items from my List<Claim> is serialized (as expected), but each Claim's ClaimValueType is also serialized with the full issuer URI (23 bytes) and full XML data-type URI, e.g. "http://www.w3.org/2001/XMLSchema#integer" (40 bytes) (I note that ASP.NET Core seems to omit the full XML data-type URI if it's "http://www.w3.org/2001/XMLSchema#string" - it's unfortunate because the reason I used integer in the first place was to save the space from string encoding and quotes.
      • Combined, these all use about 1,900 bytes of the 7,000 byte cookie.
    • Next, the various OIDC values are stored, such as the AuthScheme.oidc\r.sessionState and .Token.access_token”. I note that these values are Base64-encoded already and are then doubly encoded by ASP.NET Core. (So if ASP.NET Core was smarter it would un-encode any Base64 values and represent them as their original binary form, then pass that into the data-protection (encryption) and then run the outer-Base64 - but I digress.
    • After that, the .Token.id_token is redundantly stored. This is redundant because all of the id_token's claims have been parsed out into the ClaimsIdentity - but there's no option in AddOpenIdConnect to only save access_token into the user's cookie and to drop the id_token.
      • Actually, the id_token must be saved because it's needed to use the OIDC sign-out hint feature (the original id_token string must be provided back to the IP, verbatim).

I see a few possibilities for optimizing this - but very little documentation anywhere online about how to accomplish it.

  • Can I prevent any (or most) of the Claim values being serialized and instead have ASP.NET Core materialize the Claim objects by re-parsing the id_token?
  • I can have ASP.NET Core use the User Info Endpoint for Claims instead of using id_token, but how do I do that while still ensuring I get all of the OpenID Identity Resources I need?
  • How can I ensure each Claim value is serialized efficiently?
  • How can I prevent double-Base64-encoding of things like the access_token and id_token values?

1 个答案:

答案 0 :(得分:0)

2 年后,有人对我的问题投了赞成票,这促使我从 2019 年 6 月将我的 PR 代码发布到 ASP.NET Core 团队,was rejected because applying compression before encrypting user-provided input opens you up to the CRIME and BREACH vulnerabilities - 可能需要一段时间才能理解它,但这是有道理的,我同意 @Blowdart 拒绝将其作为通用代码的决定。

...但是我明白使用 如果 cookie 中没有不受信任/未经验证的用户提供的秘密仍然可以使用 - 所以如果你存储的只是一些非秘密或远程用户无法控制的固定大小(例如 Int32)值,那么它就不会真正容易受到犯罪/破坏:

享受:https://github.com/Jehoel/aspnetcore-auth-cookie-optimizations