ASP.Net Identity 2 - custom response from OAuthAuthorizationServerProvider

一世执手 提交于 2019-11-28 08:48:38
Federico Dipuma

This is more of a workaround then a final solution, but I believe it is the most reliable way of solving your issue without rewriting tons of code from the default OAuthAuthorizationServerProvider implementation.

The approach is simple: use a Owin middleware to catch token requests, and overwrite the response if an SMS was sent.

[Edit after comments] Fixed the code to allow the response body to be buffered and changed as per this answer https://stackoverflow.com/a/36414238/965722

Inside your Startup.cs file:

public void Configuration(IAppBuilder app)
{
    var tokenPath = new PathString("/Token"); //the same path defined in OAuthOptions.TokenEndpointPath

    app.Use(async (c, n) =>
    {
        //check if the request was for the token endpoint
        if (c.Request.Path == tokenPath)
        {
            var buffer = new MemoryStream();
            var body = c.Response.Body;
            c.Response.Body = buffer; // we'll buffer the response, so we may change it if needed

            await n.Invoke(); //invoke next middleware (auth)

            //check if we sent a SMS
            if (c.Get<bool>("sms_grant:sent"))
            {
                var json = JsonConvert.SerializeObject(
                    new
                    {
                        message = "code send",
                        expires_in = 300
                    });

                var bytes = Encoding.UTF8.GetBytes(json);

                buffer.SetLength(0); //change the buffer
                buffer.Write(bytes, 0, bytes.Length);

                //override the response headers
                c.Response.StatusCode = 200;
                c.Response.ContentType = "application/json";
                c.Response.ContentLength = bytes.Length;
            }

            buffer.Position = 0; //reset position
            await buffer.CopyToAsync(body); //copy to real response stream
            c.Response.Body = body; //set again real stream to response body
        }
        else
        {
            await n.Invoke(); //normal behavior
        }
    });

    //other owin middlewares in the pipeline
    //ConfigureAuth(app);

    //app.UseWebApi( .. );
}

And inside your custom grant method:

// ...
var result = await userManager.AddAccessCode(user, accessCode, accessCodeExpirationTime);


if(result.Succeeded)
{
    Debug.WriteLine("Login code:"+accessCode);
    //here I'll send login code to user phone via SMS
}

context.OwinContext.Set("sms_grant:sent", true);

//you may validate the user or set an error, doesn't matter anymore
//it will be overwritten
//...

I would recommend to have a look at this answer :

https://stackoverflow.com/a/24090287/2508268

public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
    foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
    {
        context.AdditionalResponseParameters.Add(property.Key, property.Value);
    }

    return Task.FromResult<object>(null);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!