Azure redirect "m." to mobile site - asp.net

I am implementing when user enters "m.co-oprating.com" it will be redirect to "www.co-oprating.com/mobile", but when I used the following code it doesn't work:
if (Request.Url.Host.StartsWith("m."))
{
UriBuilder builder = new UriBuilder(Request.Url);
builder.Host = "www." + Request.Url.Host;
Response.Clear();
Response.StatusCode = 301;
Response.StatusDescription = "Moved Permanently";
Response.AddHeader("Location", "www.co-oprating.com/mobile");
Response.End();
}
Was it because the request did not reach co-oprating.com at all, do I have to fix the DNS ?

I have to fix the DNS
Yes.
nslookup
> m.co-oprating.com
Server: google-public-dns-a.google.com
Address: 8.8.8.8
*** google-public-dns-a.google.com can't find m.co-oprating.com: Non-existent domain

Related

Apache2.49 cookies not working via my ProxyPass VirtualHost

In the apache virtualHost i have these commands:
ProxyPass "/s" "http://127.0.0.1:3001"
ProxyPassReverse "/s" "http://127.0.0.1:3001"
RewriteRule ^/s/(.*) http://127.0.0.1:3001/$1 [P,L]
ProxyPassReverseCookiePath "/" "/"
The backend server is NodeJS. The proxy itself works fine. The problem is that the Node is sending a set-cookie in the HTTP header (session ID) but the browser seems to ignore it. I tested with Chromium and Firefox but none creates the cookie. I tried to change the virtualhost configuration but nothing appears to solve the problem The set-cookie command is:
set-cookie: sid=s%3AhgHWDO3D...BBUZbbOA; Path=/; HttpOnly; Secure;HttpOnly;Secure
I need your help to solve this problem. Thank you.
UPDATE
If the url is containing a direct request for the Node:
https://example.com/s/backend
it works. It creates the session is cookie. But if this URL is called from a AJAX request in the JS, it does not create the cookie.
The https://example.com load a HTML with a script load of a JS file. That JS file makes the AJAX call to the backend using the path https://example.com/s/something and in this case the cookie is never created.
Any suggestions?
UPDATE
I discovered that the problem is when i use the Fetch API to retrieve a JSON file. This code running does not create the session ID cookie:
fetch("https://localbestbatteriesonline.com/s/p.json?0103")
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
});
But if i have this code, it creates the cookie:
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log(this.responseText);
}
};
xhttp.open("GET", "https://localbestbatteriesonline.com/s/p.json?0103", true);
xhttp.send();
Analysing the requests, both are exactly the same. Both receive the cookie to create.
Any ideas why with the fetch does not work?
Problem solved. Using the Fetch API does not include the cookies exchange like it does in the XMLHttpRequest. Therefor, it does not create the session id cookie. To enable this, the Fetch call must have the option:
credentials:"same-origin".
fetch("https://localbestbatteriesonline.com/s/p.json?0103",{credentials:"same-origin"})
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
});
Now it works.

Http redirection loop Issue - IIS 7.5

In IIS 7.5, using global.asax, I intend to redirect as follows.
The scenario is this, 1. http + domainname should be redirected to https + www + domainname.
http + www + domainname should be redirected to https + www + domainname.
Code below
string currentUrl = HttpContext.Current.Request.Url.ToString().ToLower();
string newURL = currentUrl;
try
{
Response.Status = "301 Moved Permanently";
newURL = newURL.Replace("http://domainname", "https://www.domainname");
newURL = newURL.Replace("http://www.domainname", "https://www.domainname");
Response.AddHeader("Location", newURL);
Response.End();
}
catch(Exception ex)
{
}
It gets into an infinite redirect loop and it doesn't load the site at all. Can someone please help?
Click here to view Site Binding screenshot
Looks like you need to check, after currentUrl is assigned, whether it is in the format you desire -- https + www + domainname . If it isn't then do your redirect code, but if it's already correct, skip the redirect stuff.
Please try with IIS rewrite module, that will be cleaner.
https://learn.microsoft.com/en-us/iis/extensions/url-rewrite-module/creating-rewrite-rules-for-the-url-rewrite-module

Jersey client doesn't redirect properly on 301 response (after PATCH)

I use a Jersey client to make a request to an API to change the ID of a resource, using the PATCH method:
Client client = ClientBuilder.newClient()
.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true); // To allow PATCH
...
// Setting uri, path, accessToken and entity used below
...
WebTarget target = client.target(uri).path(path);
Response response = target.request(MediaType.APPLICATION_JSON)
.header(HttpHeaders.AUTHORIZATION, BEARER + accessToken)
.method("PATCH", entity);
I see in Fiddler that the ID is changed successfully: a "301 Moved Permanently" response with a Location header is returned, the Location header contains the URL with the new ID.
Then again in Fiddler I see that the Jersey client calls the URL from the Location header, right after the first request, but using the PATCH method again...
Shouldn't it make the request to the URL in the Location header using GET since the response code was 301?
Thanks.

nginx reverse proxy with Windows authentication that uses NTLM

Anyone knows if is possible to do reverse proxy with Windows authentication that uses NTLM? I cant find any example on this. What should be the values of more_set_headers field?
location / {
proxy_http_version 1.1;
proxy_pass_request_headers on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
more_set_input_headers 'Authorization: $http_authorization';
proxy_set_header Accept-Encoding "";
proxy_pass http://host/;
proxy_redirect default;
#This is what worked for me, but you need the headers-more mod
more_set_headers -s 401 'WWW-Authenticate: Basic realm="host.local"';
}
If I access the host directly the authentication succeed if I access with the reverse proxy the authentication fail every time.
To enable NTLM pass-through with Nginx -
upstream http_backend {
server 2.3.4.5:80;
keepalive 16;
}
server {
...
location / {
proxy_pass http://http_backend/;
proxy_http_version 1.1;
proxy_set_header Connection "";
...
}
}
-- Ramon
As far as I know, this is currently not possible with nginx. I investigated this in depth myself just a little while ago. The basic problem is that NTLM authentication will require the same socket be used on the subsequent request, but the proxy doesn't do that. Until the nginx development team provides some kind of support for this behavior, the way I handled this was by resorting to authenticate in the reverse proxy itself. I am currently doing this using apache 2.2, mod_proxy, mod_auth_sspi (not perfect, but works). Good luck! Sorry nginx, I love you, but we could really use some help for this common use case.
I have since come up with another solution for this. This is still not the same as nginx doing the NTLM (which will be nice if the nginx team ever implements this). But, for now, what I'm doing works for us.
I've written some lua code that uses an encrypted cookie. The encrypted cookie contains the user's id, the time he authenticated and the ip address from which he authenticated. I'm attaching this stuff here for reference. It's not polished, but perhaps you can use it to develop your own similar scheme.
Basically, how it works is:
If the cookie is NOT available or if it's expired or invalid, nginx makes a service call (pre-auth) to a backend IIS application passing the client's IP address and then redirects the client to an IIS web application where I have "Windows Authentication" turned on. The back-end IIS application's pre-auth service generates a GUID and stores an entry in the db for that guid and a flag indicating this GUID is about to be authenticated.
The browser is redirected by nginx to the authenticator app passing the GUID.
The IIS app authenticates the user via windows authentication and updates the db record for that GUID and client IP address with the user id and the time authenticated.
The IIS app redirects the client back to the original request.
nginx lua code intercepts this call and makes a back-door service call to the IIS app again (post-auth) and asks for the user id and time authenticated. This information is set in an encrypted cookie and is sent to the browser. The request is allowed to pass through and the REMOTE_USER is sent along.
subsequent requests by the browser pass the cookie and the nginx lua code sees the valid cookie and proxies the request directly (without needing to authenticate again of course) by passing the REMOTE_USER request header.
access.lua:
local enc = require("enc");
local strings = require("strings");
local dkjson = require("dkjson");
function beginAuth()
local headers = ngx.req.get_headers();
local contentTypeOriginal = headers["Content-Type"];
print( contentTypeOriginal );
ngx.req.set_header( "Content-Type", "application/json" );
local method = ngx.req.get_method();
local body = "";
if method == "POST" then
local requestedWith = headers["X-Requested-With"];
if requestedWith ~= nil and requestedWith == "XMLHttpRequest" then
print( "bailing, won't allow post during re-authentication." );
ngx.exit(ngx.HTTP_GONE); -- for now, we are NOT supporting a post for re-authentication. user must do a get first. cookies can't be set on these ajax calls when redirecting, so for now we can't support it.
ngx.say("Reload the page.");
return;
else
print( "Attempting to handle POST for request uri: " .. ngx.var.uri );
end
ngx.req.read_body();
local bodyData = ngx.req.get_body_data();
if bodyData ~= nil then
body = bodyData;
end
end
local json = dkjson.encode( { c = contentTypeOriginal, m = method, d = body } );
local origData = enc.base64encode( json );
local res = ngx.location.capture( "/preauth", { method = ngx.HTTP_POST, body = "{'clientIp':'" .. ngx.var.remote_addr .. "','originalUrl':'" .. ngx.var.FrontEndProtocol .. ngx.var.host .. ngx.var.uri .. "','originalData':'" .. origData .. "'}" } );
if contentTypeOriginal ~= nil then
ngx.req.set_header( "Content-Type", contentTypeOriginal );
else
ngx.req.clear_header( "Content-Type" );
end
if res.status == 200 then
ngx.header["Access-Control-Allow-Origin"] = "*";
ngx.header["Set-Cookie"] = "pca=guid:" .. enc.encrypt( res.body ) .. "; path=/"
ngx.redirect( ngx.var.authurl .. "auth/" .. res.body );
else
ngx.exit(res.status);
end
end
function completeAuth( cookie )
local guid = enc.decrypt( string.sub( cookie, 6 ) );
local contentTypeOriginal = ngx.header["Content-Type"];
ngx.req.set_header( "Content-Type", "application/json" );
local res = ngx.location.capture( "/postauth", { method = ngx.HTTP_POST, body = "{'clientIp':'" .. ngx.var.remote_addr .. "','guid':'" .. guid .. "'}" } );
if contentTypeOriginal ~= nil then
ngx.req.set_header( "Content-Type", contentTypeOriginal );
else
ngx.req.clear_header( "Content-Type" );
end
if res.status == 200 then
local resJson = res.body;
-- print( "here a1" );
-- print( resJson );
local resTbl = dkjson.decode( resJson );
if resTbl.StatusCode == 0 then
resTbl = resTbl.Result;
local time = os.time();
local sessionData = dkjson.encode( { u = resTbl.user, t = time, o = time } );
ngx.header["Set-Cookie"] = "pca=" .. enc.encrypt( sessionData ) .. "; path=/"
ngx.req.set_header( "REMOTE_USER", resTbl.user );
if resTbl.originalData ~= nil and resTbl.originalData ~= "" then
local tblJson = enc.base64decode( resTbl.originalData );
local tbl = dkjson.decode( tblJson );
if tbl.m ~= nil and tbl.m == "POST" then
ngx.req.set_method( ngx.HTTP_POST );
ngx.req.set_header( "Content-Type", tbl.c );
ngx.req.read_body();
ngx.req.set_body_data( tbl.d );
end
end
else
ngx.log( ngx.ERR, "error parsing json " .. resJson );
ngx.exit(500);
end
else
print( "error completing auth." );
ngx.header["Set-Cookie"] = "pca=; path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; token=deleted;"
print( res.status );
ngx.exit(res.status);
end
end
local cookie = ngx.var.cookie_pca;
print( cookie );
if cookie == nil then
beginAuth();
elseif strings.starts( cookie, "guid:" ) then
completeAuth( cookie );
else
-- GOOD TO GO...
local json = enc.decrypt( cookie );
local d = dkjson.decode( json );
local now = os.time();
local diff = now - d.t;
local diffOriginal = 0;
if d.o ~= nil then
diffOriginal = now - d.o;
end
if diff > 3600 or diffOriginal > 43200 then
beginAuth();
elseif diff > 300 then
print( "regenerating new cookie after " .. tostring( diff ) .. " seconds." );
local sessionData = dkjson.encode( { u = d.u, t = now, o = d.t } );
ngx.header["Set-Cookie"] = "pca=" .. enc.encrypt( sessionData ) .. "; path=/"
end
ngx.req.set_header( "REMOTE_USER", d.u );
end
strings.lua:
local private = {};
local public = {};
strings = public;
function public.starts(String,Start)
return string.sub(String,1,string.len(Start))==Start
end
function public.ends(String,End)
return End=='' or string.sub(String,-string.len(End))==End
end
return strings;
enc.lua:
-- for base64, try something like: http://lua-users.org/wiki/BaseSixtyFour
local private = {};
local public = {};
enc = public;
local aeslua = require("aeslua");
private.key = "f8d7shfkdjfhhggf";
function public.encrypt( s )
return base64.base64encode( aeslua.encrypt( private.key, s ) );
end
function public.decrypt( s )
return aeslua.decrypt( private.key, base64.base64decode( s ) );
end
return enc;
sample nginx conf:
upstream dev {
ip_hash;
server app.server.local:8080;
}
set $authurl http://auth.server.local:8082/root/;
set $FrontEndProtocol https://;
location / {
proxy_pass http://dev/;
proxy_set_header Host $host;
proxy_redirect default;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header X-Real-IP $remote_addr;
proxy_buffers 128 8k;
access_by_lua_file conf/lua/app/dev/access.lua;
}
Ok, we wrote lua code for nginx/openresty, which solves ntlm reverse-proxy issue with some solvable limitations and without need of commercial nginx version
According to nginx documentation:
Allows proxying requests with NTLM Authentication. The upstream connection is bound to the client connection once the client sends a request with the “Authorization” header field value starting with “Negotiate” or “NTLM”. Further client requests will be proxied through the same upstream connection, keeping the authentication context.
upstream http_backend {
server 127.0.0.1:8080;
ntlm;
}
but the ntlm; option is available only with a commercial subscription (Nginx Plus)
You can use this module for non-production environments.
gabihodoroaga/nginx-ntlm-module
The module is not complete but it was enough for me to solve my issues. There is also a blog post about this module at hodo.dev.

Is this a correct way of doing a 301 redirect?

When I check my page using those online host header analyzers, the page says 200 OK.
But when viewing in my browser, it redirects to another website (which is how I want it to be).
The code that I use is:
context.Response.Status = "301 Moved Permanently";
context.Response.AddHeader("Location", "http://www.example.com/article" + articleID);
context.Response.End();
I put this code in a HttpModule.
it is working because when you try and hit the url, it does the redirect.
It just doesn't seem to be returning the correct http header.
Is there something wrong?
Make sure the response buffer is completely clear before you add your headers:
context.Response.Clear();
context.Response.Status = "301 Moved Permanently";
context.Response.AddHeader("Location", "http://www.example.com/article" + articleID);
context.Response.End();
try:
context.Response.StatusCode = 301;
context.Response.StatusDescription = "Moved Permanently";
context.Response.RedirectLocation = "http://www.example.com/article" + articleID;
context.Response.End();
I use the above in a custom module and it does return a proper 301 HTTP response.
Your code is exactly correct. I've used exactly what you've got for years:
context.Response.Status = "301 Moved Permanently";
context.Response.AddHeader("Location",URL);
context.Response.End();
Could you try using:
HttpContext.ApplicationInstance.CompleteRequest()
Instead of Response.End()?
When I use the HTTP logging in Web Development Helper, I see the 301 and the 200. So, yes, your code is correct.

Resources