Search code examples
asp.netasp.net-mvcangularasp.net-coreauth-token

Upgrading from asp net mvc to asp core + angular


I'm upgrading an old application in asp net mvc to a new version with asp core + angular 7. In the old app, we had an external service calling our api, and sending the auth token in the URL because it couldn't do otherwise.

I intercept it to inject the token in the header like this:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_PreSendRequestHeaders()
    {
        Response.Headers.Remove("X-Frame-Options");
        Response.AddHeader("X-Frame-Options", "AllowAll");
    }

    private void Application_BeginRequest(object sender, EventArgs e)
    {
        var header = HttpContext.Current.Request;
        var url = HttpContext.Current.Request.Url;
        var Params = HttpContext.Current.Request.Params;
        if (ReferenceEquals(null, HttpContext.Current.Request.Headers["Authorization"]))
        {
            var token = HttpContext.Current.Request.Params["access_token"];
            if (!String.IsNullOrEmpty(token))
            {
                HttpContext.Current.Request.Headers.Add("Authorization", "Bearer " + token);
            }
        }
    }

    protected void Application_Start()
    {
        //DashboardConfig.RegisterService(RouteTable.Routes);
        DevExtremeBundleConfig.RegisterBundles(BundleTable.Bundles);

        C_Interface_Meta.IntialiserBdd();
        ViewEngines.Engines.Clear();
        ViewEngines.Engines.Add(new RazorViewEngine());

        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        GlobalConfiguration.Configure(WebApiConfig.Register);
        RouteConfig.RegisterRoutes(RouteTable.Routes);

        //GlobalConfiguration.Configure(WebApiConfig.Register);
        ASPxWebControl.CallbackError += Application_Error;

        BundleConfig.RegisterBundles(BundleTable.Bundles);
        DisableApplicationInsightsOnDebug();
    }

    /// <summary>
    /// Disables the application insights locally.
    /// </summary>
    [Conditional("DEBUG")]
    private static void DisableApplicationInsightsOnDebug()
    {
        TelemetryConfiguration.Active.DisableTelemetry = true;
    }

    public static void Register(HttpConfiguration config)
    {
        config.Filters.Add(new PrettyPrintFilterAttribute());
    }

    protected void Application_Error(object sender, EventArgs e)
    {
        Exception exception = HttpContext.Current.Server.GetLastError();
        if (exception is HttpUnhandledException)
            exception = exception.InnerException;
        AddToLog(exception.Message, exception.StackTrace);
    }

    public static void AddToLog(string message, string stackTrace)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine(DateTime.Now.ToLocalTime().ToString());
        sb.AppendLine(message);
        sb.AppendLine();
        sb.AppendLine("Source File: " + HttpContext.Current.Request.RawUrl);
        sb.AppendLine();
        sb.AppendLine("Stack Trace: ");
        sb.AppendLine(stackTrace);
        for (int i = 0; i < 150; i++)
            sb.Append("-");
        sb.AppendLine();
        HttpContext.Current.Application["Log"] += sb.ToString();
        sb.AppendLine();
    }
}

What is the equivalent way for doing that in an angular asp core application? After much searching, I didn't find anything.


Solution

    1. Sounds like you're using JWT bearer and sending the token via query string. If that's the case, you could simply use an event handler OnMessageReceived to set the token dynamically :
    public void ConfigureServices(IServiceCollection services)
    {
        // ...
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options=> {
                options.TokenValidationParameters = new TokenValidationParameters{
                    // ValidIssuer, ValidAudience, IssuerSigningKey , ...
                };
                options.Events = new JwtBearerEvents() {
                    OnMessageReceived = async (context) =>{
                        // get bearer From Header/QueryString as you like
                        var bearer=context.HttpContext.Request.Query["access_token"].FirstOrDefault();
                        if(!String.IsNullOrEmpty(bearer)){
                            context.Token = bearer; // simply set the token
                        }
                    },
                };
            });
        // other services ...
    }
    
    1. Or as suggested by Razgort, you could register a middleware to set the token. Be careful for the order of middlewares.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // register it before other middlewares that rely on this token
        app.Use(async(context,next)=>{
            var bearer = context.Request.Headers["Authorization"].FirstOrDefault();
            if(bearer==null){
                bearer=context.Request.Query["access_token"].FirstOrDefault();
                if(!String.IsNullOrEmpty(bearer)){
                    context.Request.Headers.Add("Authorization", "Bearer " + bearer);
                }  
            }
            await next();
        });
    
        // other middlewares ...
        app.UseMvc(...)//
    }