How to modify token endpoint response body with Ow

2019-01-25 11:45发布

I want to modify the response body from the token endpoint response.

I've tried to intercept the /Token request with a MessageHandler but it doesn't work.

I'm able to add some additional informations to the response by overriding the OAuthAuthorizationServerProvider.TokenEndpointmethod, but I'm not able to create my own response body.

Is there a way to intercept the /Token request?


Edit

I found out how to remove the response body content from the token endpoint response, like this: HttpContext.Current.Response.SuppressContent = true;

It seems the right way to achieve my goal, but now when I use the context.AdditionalResponseParameters.Add() method to add my custom information, the SuppressContent block any alterations.

Now I have something like this:

// Removing the body from the token endpoint response
HttpContext.Current.Response.SuppressContent = true;
// Add custom informations
context.AdditionalResponseParameters.Add("a", "test");

4条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-01-25 12:01

The best way to intercept request and response is via MessageHandler if you want to avoid doing so after a request has reached the IControllerFactory handler in the pipeline - obviously in that case use a custom 'Attribute'

I have used MessageHandlers in the past to intercept request to api/token, create a new request and get the response, create a new response.

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        //create a new auth request
        var authrequest = new HttpRequestMessage();
        authrequest.RequestUri = new Uri(string.Format("{0}{1}", customBaseUriFromConfig, yourApiTokenPathFromConfig));

        //copy headers from the request into the new authrequest
        foreach(var header in request.Headers)
        {
            authrequest.Headers.Add(header.Key, header.Value);
        }

        //add authorization header for your SPA application's client and secret verification
        //this to avoid adding client id and secret in your SPA
        var authorizationHeader =
            Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", _clientIdFromConfig, _secretKeyFromConfig)));

        //copy content from original request
        authrequest.Content = request.Content;

        //add the authorization header to the client for api token
        var client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(request.Headers.Authorization.Scheme, authorizationHeader);
        var response = await client.PostAsync(authrequest.RequestUri, authrequest.Content, cancellationToken);

        if(response.StatusCode == HttpStatusCode.OK)
        {
            response.Headers.Add("MyCustomHeader", "Value");
            //modify other attributes on the response
        }

        return response;
    }

This works for me perfectly. There is, however, the configuration for this handler required in the WebApiConfig.cs file (RouteConfig.cs if you're using ASP.NET MVC).

Can you elaborate on what it is that does not work for you on the handler?

查看更多
Bombasti
3楼-- · 2019-01-25 12:23

To simply add new items to the JSON token response, you can use TokenEndpointResponse instead of the TokenEndpoint notification.


If you're looking for a way to completely replace the token response prepared by the OAuth2 authorization server by your own one, there's sadly no easy way to do that because OAuthAuthorizationServerHandler.InvokeTokenEndpointAsync doesn't check the OAuthTokenEndpointContext.IsRequestCompleted property after invoking the TokenEndpointResponse notification.

https://github.com/aspnet/AspNetKatana/blob/dev/src/Microsoft.Owin.Security.OAuth/OAuthAuthorizationServerHandler.cs

This is a known issue, but it was too late to include it in Katana 3 when I suggested to fix it.

You should give Owin.Security.OpenIdConnect.Server a try: it's an a fork of the OAuthAuthorizationServerMiddleware designed for Katana 3.0 and 4.0.

https://www.nuget.org/packages/Owin.Security.OpenIdConnect.Server/1.0.2

Of course, it includes the correct check to allow bypassing the default token request processing (this was even one of the first things I fixed when forking it).

查看更多
乱世女痞
4楼-- · 2019-01-25 12:23

This question is similar to How to extend IdentityServer4 workflow to run custom code

So you can create custom middleware and register it before OAuth2 service in Startup:

    public void Configuration(IAppBuilder app)
    {
        ....
        app.Use(ResponseBodyEditorMiddleware.EditResponse);

        app.UseOAuthAuthorizationServer(...);
        ...
    }

where custom middleware is:

    public static async Task EditResponse(IOwinContext context, Func<Task> next)
    {
        // get the original body
        var body = context.Response.Body;

        // replace the original body with a memory stream
        var buffer = new MemoryStream();
        context.Response.Body = buffer;

        // invoke the next middleware from the pipeline
        await next.Invoke();

        // get a body as string
        var bodyString = Encoding.UTF8.GetString(buffer.GetBuffer());

        // make some changes to the body
        bodyString = $"The body has been replaced!{Environment.NewLine}Original body:{Environment.NewLine}{bodyString}";

        // update the memory stream
        var bytes = Encoding.UTF8.GetBytes(bodyString);
        buffer.SetLength(0);
        buffer.Write(bytes, 0, bytes.Length);

        // replace the memory stream with updated body
        buffer.Position = 0;
        await buffer.CopyToAsync(body);
        context.Response.Body = body;
    }
查看更多
虎瘦雄心在
5楼-- · 2019-01-25 12:24

You were almost there +Samoji @Samoji and really helped/inspired me to get the answer.

// Add custom informations
context.AdditionalResponseParameters.Add("a", "test");
// Overwrite the old content
var newToken = context.AccessToken;
context.AdditionalResponseParameters.Add("access_token", newToken);

I found it just replaced my old token with my new.

查看更多
登录 后发表回答