WebPush {"Received unexpected response code"} - c#

How to send notification using Webpush library. I was trying but its throws error msg like {"Received unexpected response code"}
****Now i have created web API to send notification & calling you through fiddler,but did n't get exception it's stuck somewhere
here is my code sample****
public void Sendnotification()
{
try
{
WebPush.VapidDetails vapidKeys = apidHelper.GenerateVapidKeys();
string subject =#"mailto:xyz.com";
string publicKey = Convert.ToString(vapidKeys.PublicKey);
string privateKey = Convert.ToString(vapidKeys.PrivateKey);
var subscription = new PushSubscription(pushEndpoint, p256dh, auth);
var vapidDetails = new VapidDetails(subject, publicKey, privateKey);
client.SendNotification(subscription, "payload", vapidDetails);
}
catch (WebPushException e)
{
}
}
I have configured Https enabled to call api using fidder. Please have look. also its throws error, it stuck somewhere
now it got the error please have look it's showing error HTTP/1.1 410 NotRegistered
See the full screen of Fiddler response error details

If you are getting the error 410 (to check the error use fiddler to intercept the https call), probably what you have is an error in the subscription data of the user probably the keys stored in your database doesn't match the subscription in the browser an easy fix could be to re-subscribe and re-save the subscription data and try again.
to setup fiddler, you have to use it as a proxy visual studio to intercept the https calls and also you have to enable https decryption.
EDIT
you can set up fiddler just by adding this configuration in your web.config or app.config:
<system.net>
<defaultProxy
enabled = "true"
useDefaultCredentials = "true">
<proxy autoDetect="false" bypassonlocal="false" proxyaddress="http://127.0.0.1:8888" usesystemdefault="false" />
</defaultProxy>
</system.net>
if in any case, you get unauthorized registration check this questions:
Web Push API Chrome, returning "Unauthorized Registration"
WebPushError and UnauthorizedRegistration when try to send push notification to Chrome and Opera, FF is OK

Related

How to correctly set up AspNet Core 2 authentication behind a load balancer?

I've set up AspNet Core 2 authentication successfully, but now would like to get it working behind a load balancer.
Because the load balancer address is different from my app address I'm changing the redirect Uri in my startup.cs ConfigureServices like this...
options.Events.OnRedirectToIdentityProvider = async n =>
{
n.ProtocolMessage.RedirectUri = "https://frontfacingaddress.com";
await Task.FromResult(0);
};
This works fine and I successfully authenticate and the callback from the identity server calls https://frontfacingaddress.com/signin-oidc. That is correctly handled and handling OnTokenResponseReceived shows that I successfully recieve the token.
The problem is: it is then making another call to the identity server but this time to the app's actual (not load balancing) address. When that comes back it gives an error of: AspNetCore.Correlation.OpenIdConnect cookie not found.
So the Fiddler trace looks like this:
302 HTTPS frontfacingaddress.com /account/signin
200 HTTPS identity.serveraddress.com /connect/authorize/callback etc...
302 HTTPS frontfacingaddress.com /signin-oidc
-- this is where I successfully receive the code, but then:
302 HTTPS actualwebaddress.com /account/signin
200 HTTPS identity.serveraddress.com /connect/authorize/callback etc...
400 HTTPS frontfacingaddress.com /signin-oidc
-- this is the 400 cookie not found error
Why, after successfully authenticating, is it then firing again from the actual address and failing?
The solution was to modify the ReturnUri to use the front-facing address when the ticket was received:
options.Events.OnTicketReceived = async context =>
{
var host = context.HttpContext.Request.Host.Host;
var forwardedHost = context.HttpContext.Request.Headers["X-Forwarded-Host"].ToString();
context.ReturnUri = context.ReturnUri.Replace(host, forwardedHost);
await Task.FromResult(0);
};

Impersonation issue when making web request to other server

I have an intranet MVC.NET website. Let's call it MySite. From MySite I'm trying to make a web request to another intranet website. Let's call the other website OtherSite. Both websites are in the same domain and are running under IIS. Both websites are using:
<authentication mode="Windows" />
<authorization>
<allow verbs="OPTIONS" users="*" />
<deny users="?" />
</authorization>
MySite is accessed by an authenticated user (same domain) with a web browser (Chrome, IE). Let's call that user Client. The credentials from Client, should be used when MySite calls OtherSite.
I have tried the following:
With WebRequest:
var request = WebRequest.CreateHttp(uri);
request.Credentials = CredentialCache.DefaultCredentials;
request.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
var response = request.GetResponse();
return response;
With WebClient, as suggested here;
using (var client = new WebClient { UseDefaultCredentials = true })
{
client.Headers.Add(HttpRequestHeader.ContentType, "application/json; charset=utf-8");
var data = client.DownloadData(uri);
return data;
}
Both with and without this code around it:
var wi = (System.Security.Principal.WindowsIdentity)HttpContext.Current.User.Identity;
var wic = wi.Impersonate();
try
{
// Code for making request goes here...
}
catch (Exception exc)
{
// handle exception
}
finally
{
wic.Undo();
}
I've tried with and without <identity impersonate="true" /> in the web.config for MySite.
As soon as I try to impersonate the Client I get a 401 from OtherSite. And when I check the IIS logs for OtherSite it looks like the credentials aren't passed with the request at all.
If I don't impersonate the user it all works great. But as soon as I try to impersonate it fails and returns a 401. Do I have to do anything in Active Directory? I've seen this question, where the answer was delegation. Is that the issue? What can be the reason for the 401 I get when i impersonate?
The IIS-logs on OtherSite looks like this when I impersonate:
2016-10-19 07:33:26 2a01:9080:700:0:3fe7:b92a:552:1246 GET /odata/$metadata - 80 - 2a01:9080:700:0:8d90:4bc0:2ffd:d088 - - 401 0 0 0
2016-10-19 07:33:26 2a01:9080:700:0:3fe7:b92a:552:1246 GET /odata/$metadata - 80 - 2a01:9080:700:0:8d90:4bc0:2ffd:d088 - - 401 1 2148074252 0
They look like this when I don't impersonate:
2016-10-19 07:57:11 2a01:9080:700:0:3fe7:b92a:552:1246 GET /odata/$metadata - 80 MyDomain\SVC_ServiceAccount1 2a01:9080:700:0:8d90:4bc0:2ffd:d088 - - 200 0 0 0
2016-10-19 07:57:11 2a01:9080:700:0:3fe7:b92a:552:1246 GET /odata/$metadata - 80 MyDomain\SVC_ServiceAccount1 2a01:9080:700:0:8d90:4bc0:2ffd:d088 - - 200 0 0 0
I have a service account for the app pool, named MyDomain\SVC_ServiceAccount1 in the logs above. Real name is something else...
If your MVC site is running in IIS, what application pool is that running in?
You may need to set that application pool to run under a specific identity, otherwise it'll attempt to access the remote resource using a machine identity.
EDIT (in response to comments)
My next thought was that IIS was also configured for anonymous access and that this was what was being passed. In the IIS management console when you look at authentication for that site what does it say? The settings you're talking about here are about authorisation not authentication.
If you try disabling anonymous authentication in IIS (I'd do an iisreset after to be sure there are no lingering worker processes hanging around) and leaving only Windows authentication there and enabled what happens?
This is how I perform the setup in my code (note I'm using HttpClient though)
protected HttpClient SetupHttpClient(string uri)
{
HttpClient client = new HttpClient {BaseAddress = uri};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
return client;
}

Grapevine.RESTClient throws exception about cookies if service is not up

So I'm using Grapevine.RESTClient to manage the client side of my REST interface. I'm using it to communicate between a service running in LocalSystem and a process run by the user on the same machine.
My problem is that when the service is not running my client gets an exception with a message of 'Error: Value cannot be null. Parameter name: cookies'
I'm trying to create some logic on the client that is supposed to understand and accept that sometimes the service is unavailable like when the service is auto updating.
Or maybe I should just accept that the message of the exception is a little odd?
RESTClient client;
client = new RESTClient(baseUrl);
RESTRequest request = new RESTRequest(resource);
request.Method = Grapevine.HttpMethod.GET;
request.ContentType = Grapevine.ContentType.JSON;
request.Timeout = 30000;
RESTResponse response = client.Execute(request);
The above throws a System.ArgumentNullException with e.Message = "Value cannot be null.\r\nParameter name: cookies"
Hmmm... Looking at the Grapevine code on github it seems the code tries to add a cookie collection to this.Cookies even if the response object was created out of e.response in the catch block of the GetResponse call. It may or may not have a cookie collection. There should have been a test for null block around the this.Cookies.Add(response.Cookies) right?
https://github.com/scottoffen/Grapevine/blob/master/Grapevine/Client/RESTClient.cs
Unable to create a grapevine tag as the developer of grapevine suggested to do. Dont have enough points
I've had the same problem. Unfortunately the error message is misleading. To me the fix was to add a default proxy to the file App.config.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.net>
<defaultProxy useDefaultCredentials="true" />
</system.net>
</configuration>

HttpClient / WebClient - Trouble Interacting With Websites via Proxy

I'd like to use an HttpClient to interact with a website. This is in a corporate-type environment, all web access goes through a web proxy. By default, both the HttpClient and WebClient seem to 'just work' with the proxy here - but I've also specified the proxy details in code.
My problem is that some URLs will load correctly, others will not. The following code shows what I mean.
var webc = new WebClient();
var x1 = webc.DownloadString("http://www.google.com"); // Works
var x2 = webc.DownloadString("http://www.google.ie"); // Works
var x3 = webc.DownloadString("http://maps.google.com"); // Works
var x4 = webc.DownloadString("http://maps.google.ie"); // 403 Forbidden exception
I see the same behaviour with the HttpClient, but the code is more verbose. If I fetch the HTML returned in the 403 error it indicates that I have not authenticated and shows my username as empty.
Using Chrome/FF/IE - I can browse to all four of the sample URLs. The proxy doesn't prevent me, or show the same error message.
It seems like the code only fails on sites that have a non 'www' subdomain - when it is a non .com site. As crazy as that sounds.
I've tried running Fiddler locally to see if anything was different between the requests - from what I can see - it looks identical, except for the URL:
GET http://maps.google.ie/ HTTP/1.1 Host: maps.google.ie
Proxy-Connection: Keep-Alive
GET http://www.google.com/ HTTP/1.1 Host: www.google.com
Proxy-Connection: Keep-Alive
In the 'Auth' tab fiddler shows:
No Proxy-Authorization Header is present.
No Authorization Header is present.
For both. But the .com example works; and the .ie example fails. I tried pulling up the same maps.google.ie URL from within Chrome - which works great and I can see that it has a Proxy-Authorization in it's GET
GET http://maps.google.ie/ HTTP/1.1 Host: maps.google.ie
Proxy-Connection: keep-alive Proxy-Authorization: NTLM
T3RMTVNTUAAFAAACB4IBogQABAAzAAAACwALACgAAAAGAbFdAAAAD1BBVUxTT01xOTlEU1UTUR==
Can anyone tell me what's going on here? If that Proxy-Authorization is what I need, how do I get the HttpClient/WebClient to include it? I've tried creating a WebProxy and setting the Credentials on it - with the CredentialCache and with supplying the username/pass/domain (and every variation of the domain name I could think of). When I get it 'wrong' - all the sites seem to return 403. But when I get it right - the top 3 work and the 4th doesn't. In Fiddler, I'm never able to see that Proxy-Authorization in any of the requests I make - but it still works for the 3 first three sites.
I'm sure I've missed something, but I'm at a loss. Any help would be much appreciated.
There are two ways:
var webc = new WebClient();
webc.UseDefaultCredentials = true;
var x4 = webc.DownloadString("http://maps.google.ie");
or, put this in your app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.net>
<defaultProxy useDefaultCredentials="true" />
</system.net>
</configuration>
See tomfanning's answer here: Proxy Basic Authentication in C#: HTTP 407 error
I don't understand why "UseDefaultCredentials" does not default to true. If you work in a corporation that uses a proxy, any app that doesn't do this cannot get out of the LAN.
Moby Disk and Aron are both correct, in the sense that those are ways of specifying the proxy. But as mentioned in my question, using them didn't help.
For whatever reason, the web proxy required a User-Agent to be set. Once set, everything worked.
_client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0");
var webc = new WebClient
{
Proxy = new WebProxy
{
Credentials = new NetworkCredential(...),
}
};
var x1 = webc.DownloadString("http://www.google.com"); // Works
var x2 = webc.DownloadString("http://www.google.ie"); // Works
var x3 = webc.DownloadString("http://maps.google.com"); // Works
var x4 = webc.DownloadString("http://maps.google.ie"); // 403 Forbidden exception
Unfortunately .net is really annoying for programmatically setting the Proxy credentials. You expect you should be able to do this all in config, but it doesn't work out of the box. You can only set the Proxy address in config and not the credentials.

400 bad request invalid hostname only in android application

I have a asp.net mvc website deployed on a server, providing a few web interfaces to others. For example, getting the current user's information, my test C# console application looks like this:
using (var client = new WebClient())
{
try
{
var url = "http://api.fake.mysite.com/v1.0/user/current";
var token = "e0034e1c082de62b74e361b15f9c6471";
var encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(token));
client.Headers["Authorization"] = encoded;
client.Headers["Content-Type"] = "application/json";
Console.WriteLine(client.DownloadString(url));
}
catch (WebException e)
{
//log the exception
}
}
You can see the usage is pretty simple, just request the url via HTTP_GET, set the Authorization header to the encoded token. Actually it works fine in my machine. But some one else meets a strange issue when visiting this url in an android application, here is the java code:
HttpClient httpClient = new DefaultHttpClient();
String token = "e0034e1c082de62b74e361b15f9c6471";
String url = "http://api.fake.mysite.com/v1.0/user/current";
HttpGet httpGet = new HttpGet(url);
String encoded = Base64.encodeToString(token.getBytes(), Base64.DEFAULT);
httpGet.addHeader("Authorization", encoded);
httpGet.addHeader("Content-Type", "application/json");
try {
HttpResponse httpResponse = httpClient.execute(httpGet);
int responseCode = httpResponse.getStatusLine().getStatusCode();
String response = EntityUtils.toString(httpResponse.getEntity());
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
then he got "400 bad request invalid host name" error. I've tried:
(1) make sure the variable "encoded" has the same value in C# and Java code.
(2) make sure the website's domain name is correctly set in server IIS
(3) all PCs/mobile phones can visit the test index page(http://api.fake.mysite.com)
(4) ping api.fake.mysite.com works fine
(5) if removing httpGet.addHeader("Authorization", encoded);, the Java program got a 401 Unauthorized result as expected(the server code under my control returns the result)
(6) some other applications using C# and PHP can use the web methods well, only android application can't(tested in two totally different android mobile phones, the android emulator got 400 invalid host name either)
(7) use IP instead of domain name http://xx.xx.xx.xx/v1.0/user/current, everything is the same. (xx.xx.xx.xx stands for the ip address)
(8) checked the IIS log, all requests to /v1.0/user/current returns 200/401/500, no 400 results.
(9) make sure the android application has internet permissions(actually we've added all permissions)
Does anyone know the reason or help to find the reason? Thank you very much, this issue is driving me crazy.
Should be httpGet.addHeader("Authorization", "basic " + encoded); and String encoded = Base64.encodeToString(token.getBytes(), Base64.NO_WRAP);
I struggled the very same problem. I can send HTTP POST from Fiddler or any other tool to my asp.net web API in debug mode but I can not access from my android application.
I tried to be sure to connect from my computer browser to
web API interface.
I tried to be sure to connect from android emulator web
browser(AEWB). And then I deployed my web api to IIS so I can get certain address to access from AEWB.
I can accessed to this adres from my AEWB
http://10.0.0.2:8088/api/tran
http://10.0.0.2 -> this is your local host address seen from Android
8088 -> this is your port of web api hosted on IIS
/api -> this is web api
/tran -> this is your controller

Categories