Skip to content
This repository has been archived by the owner on Dec 13, 2018. It is now read-only.

Reading Request.Body on AuthenticationHandler causes model null on MVC #1638

Closed
grandchamp opened this issue Feb 2, 2018 · 10 comments
Closed

Comments

@grandchamp
Copy link

Hi.
What i'm trying to do is to read the Request.Body on a custom AuthenticationHandler but when i do this, the Model passed to MVC is null (probably because you can't read the Request.Body twice).
The code is https://github.com/grandchamp/AuthAPI/blob/master/AuthAPI.Middlewares.Mvc/AuthAPIAuthenticationHandler.cs#L58.

What can i do here?

@Tratcher
Copy link
Member

Tratcher commented Feb 2, 2018

You need to buffer the body, e.g. to a memory stream if it's small, seek back to the start, and then re-assign Request.Body.

@davidfowl
Copy link
Member

Is the body tiny? How big can it get?

@grandchamp
Copy link
Author

@Tratcher i've tried some things, but MVC always get a null model.

@davidfowl We'll, it's a library, so it can be any size. Currently i'm the only using, so i'm sure the body wont be so big.

@davidfowl
Copy link
Member

davidfowl commented Feb 2, 2018

You’ll probably destroy the performance if you buffer a large body in memory. Just FYI.

@grandchamp
Copy link
Author

That's what i was thinking.
Any thing i can do considering the performance?

@Tratcher
Copy link
Member

Tratcher commented Feb 2, 2018

Show us how you tried to buffer.

As far as perf goes, there's not much you can do. That validation algorithm itself is fundamentally inefficient. Time to switch auth schemes?

@grandchamp
Copy link
Author

Sorry for the late.
Well, i've tried a different way and it worked.

var ms = new MemoryStream();
await Request.Body.CopyToAsync(ms);
ms.Seek(0, SeekOrigin.Begin);

var body = await new StreamReader(ms).ReadToEndAsync();
content = Encoding.UTF8.GetBytes(body);

ms.Seek(0, SeekOrigin.Begin);
Request.Body = ms;

Probably i was messing up with Seek.

@Tratcher the algorithm is inefficient, i know. It's just a playground.

Anyway, what is the other performant way to work with Body without using MemoryStream?

@Tratcher
Copy link
Member

Tratcher commented Feb 5, 2018

You're not going to be able to do much better when your HMAC code requires hashing the entire body before the application gets access to it.

If the body gets really large you could buffer it to disk. See EnableRewind:
https://github.com/aspnet/HttpAbstractions/blob/87cd79d6fc54bb4abf07c1e380cd7a9498a78612/src/Microsoft.AspNetCore.Http/Internal/BufferingHelper.cs#L41

@Eilon Eilon added this to the Discussions milestone Feb 8, 2018
@nganbread
Copy link

nganbread commented May 24, 2018

I have a similar use-case to @grandchamp, where I need to hash the entire body to verify a webhook call

EnableRewind() didn't work for me within AuthenticationHandler<>.HandleAuthenticateAsync() so I ended up using @grandchamp's workaround instead. Not ideal, but not much else seems to get the job done

@aspnet-hello
Copy link

We periodically close 'discussion' issues that have not been updated in a long period of time.

We apologize if this causes any inconvenience. We ask that if you are still encountering an issue, please log a new issue with updated information and we will investigate.

@aspnet-hello aspnet-hello removed this from the Discussions milestone Sep 24, 2018
@aspnet aspnet locked and limited conversation to collaborators Sep 24, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants