C# Google Vision API - calling DetectText via proxy service - google-cloud-vision

I want to be able to call the API via a proxy service, but not sure which setting/settings need to be set. Is it a parameter in the ImageAnnotatorClientBuilder? Or in the ImageAnnotatorClient?
Here is my code:
var imageAnnotatorClientBuilder = new ImageAnnotatorClientBuilder();
if (!string.IsNullOrEmpty(serviceEndpoint))
{
imageAnnotatorClientBuilder.Endpoint = serviceEndpoint;
}
if (!string.IsNullOrEmpty(credentialsPath))
{
imageAnnotatorClientBuilder.CredentialsPath = credentialsPath;
}
Image image = Image.FromFile("D:\\test.jpg");
ImageAnnotatorClient = imageAnnotatorClientBuilder.Build();
ImageAnnotatorClient.DetectText(image);
I have tried setting programmaticaly the environment variable https_proxy via Environment.SetEnvironmentVariable("https_proxy", "https://XX.XX.XXX.XX:3128"); with the correct endpoint where my proxy service is running, but it seems that the request never goes via this endpoint but instead directly to google.

Related

GRPC call for a service which is inside a subdirectory? (Android grpc client)

This question is similar to below but my issue is with Android grpc client
How can I make a GRPC call for a service which is inside a subdirectory? (in .Net Framework)
I am getting 404 error while accessing the grpc streaming api :
UNIMPLEMENTED: HTTP status code 404
invalid content-type: text/html
headers: Metadata(:status=404,content-length=1245,content-type=text/html,server=Microsoft-IIS/10.0,request-id=5154500d-fb58-7903-65d6-3d3711129101,strict-transport-security=max-age=31536000; includeSubDomains; preload,alt-svc=h3=":443",h3-29=":443",x-preferredroutingkeydiagnostics=1,x-calculatedfetarget=PS2PR02CU003.internal.outlook.com,x-backendhttpstatus=404,x-calculatedbetarget=PUZP153MB0788.APCP153.PROD.OUTLOOK.COM,x-backendhttpstatus=404,x-rum-validated=1,x-proxy-routingcorrectness=1,x-proxy-backendserverstatus=404,x-feproxyinfo=MA0PR01CA0051.INDPRD01.PROD.OUTLOOK.COM,x-feefzinfo=MAA,ms-cv=DVBUUVj7A3ll1j03ERKRAQ.1.1,x-feserver=PS2PR02CA0054,x-firsthopcafeefz=MAA,x-powered-by=ASP.NET,x-feserver=MA0PR01CA0051,date=Tue, 11 Oct 2022 06:24:18 GMT)
The issue is that the /subdirectory_path is getting ignored by the service in the final outgoing call.
Here's the code I am using to create the grpc channel in android (gives 404)
val uri = Uri.parse("https://examplegrpcserver.com/subdirectory_path")
private val channel = let {
val builder = ManagedChannelBuilder.forTarget(uri.host+uri.path)
if (uri.scheme == "https") {
builder.useTransportSecurity()
} else {
builder.usePlaintext()
}
builder.executor(Dispatchers.IO.asExecutor()).build()
}
The uri is correct since it works with web client.
For web client the channel is defined like this (working)
var handler = new SubdirectoryHandler(httpHandler, "/subdirectory_path");
var userToken = "<token string>";
var grpcWebHandler = new GrpcWebHandler(handler);
using var channel = GrpcChannel.ForAddress("https://examplegrpcserver.com", new GrpcChannelOptions { HttpHandler = grpcWebHandler,
Credentials = ChannelCredentials.Create(new SslCredentials(), CallCredentials.FromInterceptor((context, metadata) =>
{
metadata.Add("Authorization", $"Bearer {userToken}");
return Task.CompletedTask;
}))
});
I tried to inject the subdirectory_path in the uri for my android client but unable to find appropriate api. grpc-kotlin doesn't expose the underlying http-client used in the channel.
Could someone please help me with this issue, how can I specify the subdirectory_path? (before the service and method name)
The path for an RPC is fixed by the .proto definition. Adding prefixes to the path is unsupported.
The URI passed to forTarget() points to the resource containing the addresses to connect to. So the fully-qualified form is normally of the form dns:///example.com. If you specified a host in the URI like dns://1.1.1.1/example.com, then that would mean "look up example.com at the DNS server 1.1.1.1." But there's no place to put a path prefix in the target string, as that path would only be used for address lookup, not actual RPCs.
If the web client supports path prefixes, that is a feature specific to it. It would also be using a tweaked grpc protocol that requires translation to normal backends.

Sitecore hosted on IIS, API returned 404 but has content

I have a Sitecore site and I'm trying to make API calls from a controller. For some reason API always returns the 404 not found, but it also executes the code correctly and returns the content. I tried to call the same API endpoint via Postman and returned the 200 code with content.
Here's my RouteConfig:
routes.MapRoute("Feature.DataIntegration.Api", "api/dataintegration/{action}",
new
{
controller = "DataIntegration"
});
Here's my API (I tried to use [HttpGet] attribute, but it didn't work):
public string test1()
{
return "Asdas";
}
This is my RestSharp code:
var url = "http://tdev.xxx.cd.local/api/dataintegration/test1";
var client = new RestClient(url);
var request = new RestRequest();
IRestResponse response = client.Execute(request);
This is Postman's return:
This is when the result from RestSharp (I also tried with httpclient, the same result):
I have tried to disable my firewall, but doesn't work neither.
How can I fix the 404 not found? If I don't fix this, does this affect the API once deployed to a real server?

Endpoint belongs to different authority

trying to use Azure AD as OpenID provider with IdentityModel package
However the problem is that it produces wrong endpoint configuration
var client = new HttpClient();
const string identityUrl = "https://login.microsoftonline.com/00edae13-e792-4bc1-92ef-92a02ec1d939/v2.0";
const string restUrl = "https://localhost:44321";
var disco = await client.GetDiscoveryDocumentAsync(identityUrl);
if (disco.IsError)
{
Console.WriteLine(disco.Error);
return;
}
returns error
Endpoint belongs to different authority:
https://login.microsoftonline.com/00edae13-e792-4bc1-92ef-92a02ec1d939/oauth2/v2.0/authorize
openid-configuration output is
{"authorization_endpoint":"https://login.microsoftonline.com/00edae13-e792-4bc1-92ef-92a02ec1d939/oauth2/v2.0/authorize",
"token_endpoint":"https://login.microsoftonline.com/00edae13-e792-4bc1-92ef-92a02ec1d939/oauth2/v2.0/token" ... }
oauth2 is added between the tenatID and version. I suppose this is why openid metadata validation fails.
Is it possible to configure AzureAD to return correct metadata for the openid-configuration ?
Regards
could you find a solution for this? The only way I could figure out (far to be the optimal solution) is to add the endpoints to a list of additional endpoint base addresses. Otherwise you have to set the validations to false as stated in the comments above.
var client = httpClientFactory.CreateClient();
var disco = await client.GetDiscoveryDocumentAsync(
new DiscoveryDocumentRequest
{
Address = "https://login.microsoftonline.com/00edae13-e792-4bc1-92ef-92a02ec1d939/v2.0",
Policy =
{
ValidateIssuerName = true,
ValidateEndpoints = true,
AdditionalEndpointBaseAddresses = { "https://login.microsoftonline.com/00edae13-e792-4bc1-92ef-92a02ec1d939/oauth2/v2.0/token",
"https://login.microsoftonline.com/00edae13-e792-4bc1-92ef-92a02ec1d939/oauth2/v2.0/authorize",
"https://login.microsoftonline.com/00edae13-e792-4bc1-92ef-92a02ec1d939/discovery/v2.0/keys",
"https://login.microsoftonline.com/00edae13-e792-4bc1-92ef-92a02ec1d939/oauth2/v2.0/devicecode",
"https://graph.microsoft.com/oidc/userinfo",
"https://login.microsoftonline.com/00edae13-e792-4bc1-92ef-92a02ec1d939/oauth2/v2.0/logout"
}
},
}
);
If you take a look at the code inside IdentityModel repository, you can see that the default validation of the endpoints validates them by doing a "starts with" method. https://github.com/IdentityModel/IdentityModel/blob/1db21e2677de6896bc11227c70b927c502e20898/src/Client/StringComparisonAuthorityValidationStrategy.cs#L46
Then the only two required AdditionalEndpointBaseAddresses inside the DiscoveryDocumentRequest Policy field you need to add are "https://login.microsoftonline.com/<guid>" and "https://graph.microsoft.com/oidc/userinfo".
I had the same problem as well and when i upgraded IdentityModel to version 2.16.1 the problem was solved
Azure AD seems to need Additional Endpoints configuration as #flacid-snake suggested. Setting validate endpoints to False is a security threat and should be avoided.
The best way is to make it configurable, preferable in the UI when you configure the SSO server. Endpoints can change and they should be easy to change. It will also make it easier if you later decide to support Okta or other providers and they require additional endpoints.
As of June 2021 you also need to include Kerberos endpoint like:
https://login.microsoftonline.com/888861fc-dd99-4521-a00f-ad8888e9ecc8bfgh/kerberos (replace with your directory tenant id).

Get full URL inside SignalR hub

I'm developing an user tracking solution using SignalR, as a fun project to learn SignalR, for ASP.NET MVC applications.
Currently i can track logged users and how long are they on a specific page. If they move to another page i track that also and the timer that SignalR is updating resets... Many other features are implemented or partially implemented.
The problem i'm facing is how to get the full url Controller/Action/Parameters
inside SignalR hub?
When i use HttpContext.Current.Request.Url the url is always /signalr/connect.
NOTE:
var hub = $.connection.myHub;
$.connection.hub.start();
is in the _Layout.cshtml.
UPDATE:
I've tried to use
var location = '#HttpContext.Current.Request.Url';
var hub = $.connection.myHub;
$.connection.hub.start().done(function () {
hub.setLocation(location);
});
And the location is passed correctly but I need it on the Connect() task not later.
Is it possible to do this?
UPDATE 2:
This approach doesn't work
var hub = $.connection.myHub;
$.connection.hub.start(function(){hub.setLocation(location)});
as the Connect() is called before.
In my hub i have several methods but i would like pass a value (in my case a location) to the Connect(), is that possible?
public class MyHub : Hub, IDisconnect, IConnected
{
public Task Connect()
{
//do stuff here
//and i would like to have the **location** value
}
public Task Disconnect()
{
//do stuff here
}
}
Update 3
Use QueryString to pass data before the Connect() occurs.
var location = '#HttpContext.Current.Request.Url';
var hub = $.connection.myHub;
$.connection.hub.qs = "location= + location;
$.connection.hub.start();
Passing data like your location value to Connect() is possible via a querystring parameter: SignalR: How to send data to IConnected.Connect()
Using query-string is not very secure, cause a hacker can forge JS code and send you wrong location breaking whatever logic you have behind it.
You can try to get this from owin-enviromment variables
var underlyingHttpContext =
Context.Request.Environment[typeof(HttpContextBase).FullName] as HttpContextBase;
Then extract whatever you need.
It will work on IIS, for non-IIS hosting look for other OWIN stuff https://github.com/aspnet/AspNetKatana/wiki/OWIN-Keys
You could pass it from your client js call to your hub as a parameter.

Set up dummy proxy server on a dev environment

There is a proxy server on the clients site that all external request must go through. I am calling an external web service that needs the proxy settings.
The code I am using to set up the proxy for the web request can be seen below.
How would I go about setting up a test proxy server on my developer environment to verify that my code works?
string url = String.Format("http://currencyconverter.kowabunga.net/converter.asmx/GetConversionAmount?CurrencyFrom={0}&CurrencyTo={1}&RateDate={2}&Amount={3}", CurrencyFrom.Text, CurrencyTo.Text, formattedDate, amount);
WebRequest request = WebRequest.Create(url);
if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["proxyLogin"]))
{
WebProxy proxy = new WebProxy();
string proxyUrl = ConfigurationManager.AppSettings["proxyUrl"];
if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["proxyPort"]))
{
proxyUrl += ":" +ConfigurationManager.AppSettings["proxyPort"];
}
// Associate the newUri object to 'myProxy' object so that new myProxy settings can be set.
proxy.Address = new Uri(proxyUrl);
// Create a NetworkCredential object and associate it with the
// Proxy property of request object.
proxy.Credentials = new NetworkCredential(ConfigurationManager.AppSettings["proxyLogin"], ConfigurationManager.AppSettings["proxyPassword"]);
request.Proxy = proxy;
}
WebResponse response = request.GetResponse();
You can install a proxy server in your development environment and configure the machines in such a way that the service is deployed beyond the firewall and you need to connect to the service through the proxy server only.

Resources