Make ASP.NET handle reverse proxies
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
2
down vote
favorite
In my ASP.NET MVC application there are occasions where I need to generate an absolute URI, such as when sending an email confirmation link to a user. The most straightforward approach is to use UrlHelper.Action() with the protocol
parameter, and this has worked well for me.
However now my server is behind a reverse proxy. So the absolute URIs that I'm generating are pointing to backendserver.myorg.local
instead of publicsite.example.com
, and that's not good for business.
So I wrote this method to inspect the Origin header. Do you see any security problems or other reasons this might not be a good solution?
static class UrlHelperExtensions
private const string OriginHeader = "Origin";
/// <summary>
/// Generates a full absolute URI, with HTTP(S), host name, and everything. Is reverse-proxy-aware,
/// so will generate public URIs in the event that our server is behind a reverse proxy.
/// </summary>
/// <param name="urlHelper"></param>
/// <param name="actionName"></param>
/// <param name="controllerName"></param>
/// <param name="routeValues"></param>
/// <returns></returns>
public static string AbsoluteAction(this UrlHelper urlHelper, string actionName, string controllerName, object routeValues = null)
if (urlHelper == null)
throw new ArgumentNullException(nameof(urlHelper), $"nameof(urlHelper) is null.");
var protocol = urlHelper.RequestContext.HttpContext.Request.Url.Scheme; // Should be "http" or "https"
var localUriString = urlHelper.Action(actionName, controllerName, routeValues, protocol);
var originValues = urlHelper.RequestContext.HttpContext.Request.Headers.GetValues(OriginHeader)
.Where(x => !String.IsNullOrWhiteSpace(x))
.ToList();
if (!originValues.Any())
return localUriString; // We are NOT behind a reverse proxy. Easy peasy, return local URI.
var originUriString = originValues.First(); // There should only be only 1 Origin header, but theoretically it's possible to have more than 1.
var originUri = parseOriginUri(originUriString);
var uriBuilder = new UriBuilder(localUriString);
uriBuilder.Scheme = originUri.Scheme; // AKA "protocol" (http or https)
uriBuilder.Host = originUri.Host;
uriBuilder.Port = originUri.Port;
return uriBuilder.ToString();
private static Uri parseOriginUri(string originText)
try
return new Uri(originText);
catch (UriFormatException ex)
throw new UriFormatException($"OriginHeader header URI is in an invalid format: "originText"", ex);
Note: Right now I don't have any requirements to actually manipulate the URL path.
security http asp.net-mvc url-routing
add a comment |Â
up vote
2
down vote
favorite
In my ASP.NET MVC application there are occasions where I need to generate an absolute URI, such as when sending an email confirmation link to a user. The most straightforward approach is to use UrlHelper.Action() with the protocol
parameter, and this has worked well for me.
However now my server is behind a reverse proxy. So the absolute URIs that I'm generating are pointing to backendserver.myorg.local
instead of publicsite.example.com
, and that's not good for business.
So I wrote this method to inspect the Origin header. Do you see any security problems or other reasons this might not be a good solution?
static class UrlHelperExtensions
private const string OriginHeader = "Origin";
/// <summary>
/// Generates a full absolute URI, with HTTP(S), host name, and everything. Is reverse-proxy-aware,
/// so will generate public URIs in the event that our server is behind a reverse proxy.
/// </summary>
/// <param name="urlHelper"></param>
/// <param name="actionName"></param>
/// <param name="controllerName"></param>
/// <param name="routeValues"></param>
/// <returns></returns>
public static string AbsoluteAction(this UrlHelper urlHelper, string actionName, string controllerName, object routeValues = null)
if (urlHelper == null)
throw new ArgumentNullException(nameof(urlHelper), $"nameof(urlHelper) is null.");
var protocol = urlHelper.RequestContext.HttpContext.Request.Url.Scheme; // Should be "http" or "https"
var localUriString = urlHelper.Action(actionName, controllerName, routeValues, protocol);
var originValues = urlHelper.RequestContext.HttpContext.Request.Headers.GetValues(OriginHeader)
.Where(x => !String.IsNullOrWhiteSpace(x))
.ToList();
if (!originValues.Any())
return localUriString; // We are NOT behind a reverse proxy. Easy peasy, return local URI.
var originUriString = originValues.First(); // There should only be only 1 Origin header, but theoretically it's possible to have more than 1.
var originUri = parseOriginUri(originUriString);
var uriBuilder = new UriBuilder(localUriString);
uriBuilder.Scheme = originUri.Scheme; // AKA "protocol" (http or https)
uriBuilder.Host = originUri.Host;
uriBuilder.Port = originUri.Port;
return uriBuilder.ToString();
private static Uri parseOriginUri(string originText)
try
return new Uri(originText);
catch (UriFormatException ex)
throw new UriFormatException($"OriginHeader header URI is in an invalid format: "originText"", ex);
Note: Right now I don't have any requirements to actually manipulate the URL path.
security http asp.net-mvc url-routing
add a comment |Â
up vote
2
down vote
favorite
up vote
2
down vote
favorite
In my ASP.NET MVC application there are occasions where I need to generate an absolute URI, such as when sending an email confirmation link to a user. The most straightforward approach is to use UrlHelper.Action() with the protocol
parameter, and this has worked well for me.
However now my server is behind a reverse proxy. So the absolute URIs that I'm generating are pointing to backendserver.myorg.local
instead of publicsite.example.com
, and that's not good for business.
So I wrote this method to inspect the Origin header. Do you see any security problems or other reasons this might not be a good solution?
static class UrlHelperExtensions
private const string OriginHeader = "Origin";
/// <summary>
/// Generates a full absolute URI, with HTTP(S), host name, and everything. Is reverse-proxy-aware,
/// so will generate public URIs in the event that our server is behind a reverse proxy.
/// </summary>
/// <param name="urlHelper"></param>
/// <param name="actionName"></param>
/// <param name="controllerName"></param>
/// <param name="routeValues"></param>
/// <returns></returns>
public static string AbsoluteAction(this UrlHelper urlHelper, string actionName, string controllerName, object routeValues = null)
if (urlHelper == null)
throw new ArgumentNullException(nameof(urlHelper), $"nameof(urlHelper) is null.");
var protocol = urlHelper.RequestContext.HttpContext.Request.Url.Scheme; // Should be "http" or "https"
var localUriString = urlHelper.Action(actionName, controllerName, routeValues, protocol);
var originValues = urlHelper.RequestContext.HttpContext.Request.Headers.GetValues(OriginHeader)
.Where(x => !String.IsNullOrWhiteSpace(x))
.ToList();
if (!originValues.Any())
return localUriString; // We are NOT behind a reverse proxy. Easy peasy, return local URI.
var originUriString = originValues.First(); // There should only be only 1 Origin header, but theoretically it's possible to have more than 1.
var originUri = parseOriginUri(originUriString);
var uriBuilder = new UriBuilder(localUriString);
uriBuilder.Scheme = originUri.Scheme; // AKA "protocol" (http or https)
uriBuilder.Host = originUri.Host;
uriBuilder.Port = originUri.Port;
return uriBuilder.ToString();
private static Uri parseOriginUri(string originText)
try
return new Uri(originText);
catch (UriFormatException ex)
throw new UriFormatException($"OriginHeader header URI is in an invalid format: "originText"", ex);
Note: Right now I don't have any requirements to actually manipulate the URL path.
security http asp.net-mvc url-routing
In my ASP.NET MVC application there are occasions where I need to generate an absolute URI, such as when sending an email confirmation link to a user. The most straightforward approach is to use UrlHelper.Action() with the protocol
parameter, and this has worked well for me.
However now my server is behind a reverse proxy. So the absolute URIs that I'm generating are pointing to backendserver.myorg.local
instead of publicsite.example.com
, and that's not good for business.
So I wrote this method to inspect the Origin header. Do you see any security problems or other reasons this might not be a good solution?
static class UrlHelperExtensions
private const string OriginHeader = "Origin";
/// <summary>
/// Generates a full absolute URI, with HTTP(S), host name, and everything. Is reverse-proxy-aware,
/// so will generate public URIs in the event that our server is behind a reverse proxy.
/// </summary>
/// <param name="urlHelper"></param>
/// <param name="actionName"></param>
/// <param name="controllerName"></param>
/// <param name="routeValues"></param>
/// <returns></returns>
public static string AbsoluteAction(this UrlHelper urlHelper, string actionName, string controllerName, object routeValues = null)
if (urlHelper == null)
throw new ArgumentNullException(nameof(urlHelper), $"nameof(urlHelper) is null.");
var protocol = urlHelper.RequestContext.HttpContext.Request.Url.Scheme; // Should be "http" or "https"
var localUriString = urlHelper.Action(actionName, controllerName, routeValues, protocol);
var originValues = urlHelper.RequestContext.HttpContext.Request.Headers.GetValues(OriginHeader)
.Where(x => !String.IsNullOrWhiteSpace(x))
.ToList();
if (!originValues.Any())
return localUriString; // We are NOT behind a reverse proxy. Easy peasy, return local URI.
var originUriString = originValues.First(); // There should only be only 1 Origin header, but theoretically it's possible to have more than 1.
var originUri = parseOriginUri(originUriString);
var uriBuilder = new UriBuilder(localUriString);
uriBuilder.Scheme = originUri.Scheme; // AKA "protocol" (http or https)
uriBuilder.Host = originUri.Host;
uriBuilder.Port = originUri.Port;
return uriBuilder.ToString();
private static Uri parseOriginUri(string originText)
try
return new Uri(originText);
catch (UriFormatException ex)
throw new UriFormatException($"OriginHeader header URI is in an invalid format: "originText"", ex);
Note: Right now I don't have any requirements to actually manipulate the URL path.
security http asp.net-mvc url-routing
asked Aug 1 at 12:10
Phil
1334
1334
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
1
down vote
This is based on a misunderstanding of the Origin
header. Chrome and Safari add this header to their web requests, but other browsers don't necessarily. You only have to test this from a browser like Internet Explorer or Firefox to find out it won't work.
The Forwarded header is probably more what you're looking for.
This header-based approach could be a security issue as well, depending on your environment. If your server is accessed directly somehow, then you're basically giving the remote client control over what URLs will be generated. All the client would need to do is manipulate the right headers in the right way. Giving remote clients control over your internal URLs sounds like a very bad thing.
You're probably better off using a server-side setting (perhaps in Web.config) that contains the public URI, and using that server-side setting instead.
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
This is based on a misunderstanding of the Origin
header. Chrome and Safari add this header to their web requests, but other browsers don't necessarily. You only have to test this from a browser like Internet Explorer or Firefox to find out it won't work.
The Forwarded header is probably more what you're looking for.
This header-based approach could be a security issue as well, depending on your environment. If your server is accessed directly somehow, then you're basically giving the remote client control over what URLs will be generated. All the client would need to do is manipulate the right headers in the right way. Giving remote clients control over your internal URLs sounds like a very bad thing.
You're probably better off using a server-side setting (perhaps in Web.config) that contains the public URI, and using that server-side setting instead.
add a comment |Â
up vote
1
down vote
This is based on a misunderstanding of the Origin
header. Chrome and Safari add this header to their web requests, but other browsers don't necessarily. You only have to test this from a browser like Internet Explorer or Firefox to find out it won't work.
The Forwarded header is probably more what you're looking for.
This header-based approach could be a security issue as well, depending on your environment. If your server is accessed directly somehow, then you're basically giving the remote client control over what URLs will be generated. All the client would need to do is manipulate the right headers in the right way. Giving remote clients control over your internal URLs sounds like a very bad thing.
You're probably better off using a server-side setting (perhaps in Web.config) that contains the public URI, and using that server-side setting instead.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
This is based on a misunderstanding of the Origin
header. Chrome and Safari add this header to their web requests, but other browsers don't necessarily. You only have to test this from a browser like Internet Explorer or Firefox to find out it won't work.
The Forwarded header is probably more what you're looking for.
This header-based approach could be a security issue as well, depending on your environment. If your server is accessed directly somehow, then you're basically giving the remote client control over what URLs will be generated. All the client would need to do is manipulate the right headers in the right way. Giving remote clients control over your internal URLs sounds like a very bad thing.
You're probably better off using a server-side setting (perhaps in Web.config) that contains the public URI, and using that server-side setting instead.
This is based on a misunderstanding of the Origin
header. Chrome and Safari add this header to their web requests, but other browsers don't necessarily. You only have to test this from a browser like Internet Explorer or Firefox to find out it won't work.
The Forwarded header is probably more what you're looking for.
This header-based approach could be a security issue as well, depending on your environment. If your server is accessed directly somehow, then you're basically giving the remote client control over what URLs will be generated. All the client would need to do is manipulate the right headers in the right way. Giving remote clients control over your internal URLs sounds like a very bad thing.
You're probably better off using a server-side setting (perhaps in Web.config) that contains the public URI, and using that server-side setting instead.
answered Aug 1 at 15:48
Phil
1334
1334
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f200742%2fmake-asp-net-handle-reverse-proxies%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password