Blazor webassembly: detect from which site the user came from - http

I am developing a Blazor Webassembly application. Based on the page the user came from, I should show different content. For example, the app should show Content A when the user came from Facebook and Content B otherwise. How can this feature achieved?
I red that one could do this by checking the referrer property of the request header, but I don't know how to access the http request on a razor page.

You can use javascript for this.
1) Create a javascript file on your blazor project (the front-end) with the following content:
function getReferrer() {
return document.referrer;
}
2) Add the previous file to your index.html file:
<script src="JavaScript.js"></script>
3) Consume the function using the IJSRuntime service:
var referrer = await js.InvokeAsync<string>("getReferrer");
This should get you the referrer.

Related

Angular Web Component http calls are not routing through clients http interceptor

Set-up:
I have a web component (Angular 10) being used in an Angular 10 Application. The web component makes an Httpclient call to a web API to get some data to populate a menu dropdown. The web component was made using the standard methods to make a web component using Angular 10.
The web component is loaded through a script in the main client application. This is from the angular.json file for the parent application.
1."scripts":
[
"projects/web-component-test/src/assets/plugin.bundle.js"
]
and all works fine except we get a 401 error (unauthorized) since the end point requires the user to be logged in. By working fine, there are other controls that display as required just the the dropdown list, which gets it data from the API call does not get populated.
The flow:
User goes to website and then is prompted to log in (using keycloak Auth).
Application loads fine, except for the 401 error when the web component tries to load the menu items.
Http calls from the parent app work fine; the jwt token is added to the header for the call to the protected API. Calls from the child web component do not have the jwt token in the header, and thus fail with a 401 error.
httpinterceptor: we have an httpinterecptor on the main client application (the parent of the web control). Http calls that are made from the main app are routed through the interceptor where the token is attached to the header if needed.
Calls made from the child Web Component DO NOT hit the interceptor in the parent app?
Question:
How do I make call from the child web component route through the http interceptor in the parent so the token can be added.
Things I have tried:
I can get the web component to work fine if I do this:
When the parent loads I store the token in local storage
using an http interceptor on the web component, retrieve the token from local storage and use it.
** works, but I DO NOT want to store a secure token in local storage.
Pass the token in an attribute on the child component when the parent loads the child component
** again, I can get it to work, but not very secure.
A web component is an independent piece of code from your main codebase, so when you hit a request from the web component, your main app won't be able to catch those requests in the interceptor.
For me, one thing it worked was creating different Custom Events per every request:
doGetRequest
doPostRequest
doPutRequest
doDeleteRequest
Let me quickly guide you through one example of these events.
From the main app, I'm listening if any of these events are triggered:
this.popupEl.addEventListener('doPostRequest', (info: HTMLElementEventMap | any) => {
this.performHttpRequest(info.detail);
});
Notice that all the info sent from your web component, can be found in the property 'detail' your main app receives.
From the web component, I execute the following:
this.doPostRequest.emit({
url: 'the URL to hit',
endpointParams: {
user: 'my user',
password: '******',
}
});
Note: You can change the structure of the params to sent. It's totally up to you.
This will trigger the execution of the API in the main app, and as the request was executed from the main app, your interceptor will do its work and add whatever JWT you have there. Once the main app receives the response, you will need to set a new property in your web component to pass the response to it. Something like this:
this.popupEl.apiResponse = {
webComponentInfo: { ...infoReceivedFromYourWebComponent },
apiDetails: { ...ResponseFromYourBackend}
};
Finally, in your web component, add a new input that listen for the apiResponse attribute:
#Input()
set apiResponse(apiResponse: RequestParams) {
if (apiResponse.webComponentInfo.url === 'the URL to hit') {
// Do what you want in your web component, as you know exactly which URL just got executed.
}
}
This way, you let your main app continue doing its work with your interceptor and the web component won't need to handle the JWT or actually perform the requests.
One thing you may want to consider is not allowing the Delete request from your web component unless you and only you have full control over the web component. You wouldn't want anything that can perform a successful DELETE request to a very important API.
Hope this helps.

How does SoapUI bypass CORS issue when my ajax call can't do it?

This might be a silly question but here is my simple webapi 2 method
public class ProductsController : ApiController
{
Product[] products = new Product[]
{
new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
};
public IEnumerable<Product> GetAllProducts()
{
return products;
}
Now if I run it , on my pc it runs on http://localhost:3145/Products, and I can see the products as XML
It also works using soapui
But now if I try to access this with a html file and this javascript
<script type="text/javascript">
function GetProducts() {
$.ajax({
url: "http://localhost:3145/Products",
dataType: "json",
success: function (data) {
for (var i = 0; i < data.length; i++)
$('#myDiv').append(data[i].Category).append("<br/>");
},
error: function (xhr, status) {
alert(xhr);
}
});
}
</script>
</head>
<body onload="GetProducts()">
<h1>My App</h1>
<div id="myDiv"></div>
I get the CORS error
How is SOAP UI not getting an error here when it is using http as well?
Thanks
Put that index file into some server location, and then browse the page with server url , like, http://localhost/virtual_dir/index.html , else it will say it file:/// domain does not match with http://localhost:port . And you might face CORS issue if you deploy this page to some other domain and start using.
I have seen that you are using webapi , and you might face CORS issue if you place you JS in domain ( "example1.com"), i mean files served from example1.com will have ajax calls to webapi and that webapi may be hosted in example2.com. This will raise CORS issue. Browser restricts ajax call to other domains, unless that domain allow you to invoke. To achieve this, you can follow this link - Angular.js $resource with ASP.Net webapi? (don't go by the title)
I have answered there the same scenario.
I just experienced the same situation with a web page I was developing that needed to send a SOAP request to a web service that was served by a remote server that was not CORS-enabled. This was in a test environment; in production, the web page and web service are served from the same domain and port.
How is SOAP UI not getting an error here when it is using http as well?
Yes, SoapUI and a web browser both use HTTP. But SoapUI is not a web browser, and does not share the same restrictions.
A colleague solved this issue for me by pointing me to CORS Anywhere.
Install Node.js, if you don't already have it.
Install CORS Anywhere (npm install cors-anywhere).
Run CORS Anywhere (node cors-anywhere.js).
Instead of using your original non-CORS-enabled web service URL, use the domain and port in the resulting message from CORS Anywhere ("Running CORS Anywhere on ..."), with your original web service URL as the path component.
You can specify the CORS Anywhere port in an environment variable (or edit the default value in your local copy of cors-anywhere.js).
In my case, the production web service URL is hardcoded in the web page as a relative path. But I've added code that reads a URL from a parameter in the fragment identifier ("hash string"), overriding the default web service URL.
For example:
http://localhost:8081/mywebpage.html#url=http://localhost:8089/remote.domain.com:8085/servicename
where:
http://localhost:8081/mywebpage.html is my web page (I'm using http://, not file://, for this).
http://localhost:8089 is the CORS Anywhere proxy.
remote.domain.com:8085/servicename (you can drop the leading http://) is the remote, non-CORS-enabled web service.
I could point you 2 options to solve this:
Disable your browser CORS: Due the CORS enforcement is done by the browser you can just disable this during development in yourself browser. If you use Chrome, you must just set an parameter otherwise I may guess looking to the underneath image you are using Firefox, for this you have an extension to do this: https://addons.mozilla.org/pt-PT/firefox/addon/cors-everywhere/
Allow CORS in SOAP UI: It can take a little bit more effort than above solution but it fits very good when you need to share with mutiple teammates or just to make the solution attached to the mock service. To do this,you must add a response for the root of resource path that responds to OPTIONS and with headers you need for CORS with status 204 (or 200).
After, in the MockService you just need to add a script to grab these same headers in all calls that passes through.
Here is the article to solve this step-by-step:
https://medium.com/#andrelimamail/how-to-deal-with-cors-in-soap-ui-mock-services-or-anyother-f4cc55b3dccd

Using the facebook c# sdk in asp.net without a canvas application

Im trying to use the sdk without a canvas application, so have followed steps 1-7 in the quickstart guide up to adding the facebookSettings property in the Web.config.
I have added an image to my page and an onclick event that contains the below code. but when I click the button, it just takes me to the home page (CancelUrlPath).
Changing the Authorizer to a CanvasAuthorizer results in FB loading the login screen, but I get an error 404 not found on the call (even after inserting the handlers into the config)..
fbApp = new FacebookApp();
authorizer = new Authorizer(fbApp) {Perms = requiredAppPermissions};
authorizer.ReturnUrlPath = "http://localhost/User/UserRegister.aspx";
authorizer.CancelUrlPath = "http://localhost/";
if (authorizer.Authorize(this.Context))
{
Response.Write("hello");//never gets here
}
Can anyone help please?
Note: I've set the canvas and site url to http://localhost/ on the FB app settings.
If you are just building a simple connect website you really don't want to use the server side authentication tools to authenticate your user. Just use the Javascript SDK to athenticate the user. If you need to do anything on the server side, the FacebookApp class will automatically pick up the user's session from the values stored in the cookies.
See the Facebook documentation for more details: http://developers.facebook.com/docs/guides/web/#registration

Handling redirected URL within Flex app?

We have a Flex client and a server that is using the Spring/Blazeds project.
After the user logs in and is authenticated, the spring security layer sends a redirect to a new URL which is where our main application is located.
However, within the flex client, I'm currently using HTTPService for the initial request and I get the redirected page sent back to me in its entirety.
How can I just get the URL so that I can use navigatetourl to get where the app to go where it needs to?
Any help would greatly be appreciated. Thanks!
One solution would be to include a token inside a comment block on the returned page, for instance:
<!-- redirectPage="http://localhost/new-location" -->
then check for it's presence inside the HTTPService result handler. The token's value could then be used in your call to navigateToURL.
Another solution would be to examine the HTTP response headers and extract the value of the "Location" header using ActionScript. Consider using the AS3 HTTP Client lib.
From the examples page http://code.google.com/p/as3httpclientlib/wiki/Examples To determine the 'Location' header from the response:
var client:HttpClient = new HttpClient();
var uri:URI = new URI("http://localhost/j_security_check");
client.listener.onStatus = function(event:HttpStatusEvent):void {
var response:HttpResponse = event.response;
// Headers are case insensitive
var redirectLocation:String = response.header.getValue("Location");
// call navigateToURL with redirectLocation
// ...
};
// include username and password in the request
client.post(uri);
NOTE: AS3 HTTP Client depends on AS3 Core and AS3 Crypto libs.
You can also simply use the URLLoader class, no need for external code. One of the events it dispatches is HTTPStatusEvent.HTTP_RESPONSE_STATUS. Just plug into that and retrieve the redirected url:
urlLoader.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, onHTTPResponseStatus);
private function onHTTPResponseStatus(event:HTTPStatusEvent):void
{
var responseURL:String = event.responseURL;
}
I am (successfully) using this code right now, so if it doesn't work for some reason, let me know.

Asp.Net MVC routing diffrence in www.Mysite.com/Employee and www.Mysite.com/Employee/ while using JqGrid

I am using ASP.NEt MVC for one of my project.
In this I have Employee controller which can be called by www.Mysite.com/Employee/ url.
Also I have used JqGrid which uses followng to fetch data
url: "GetGridData"
While testing the same I found that
If i type www.Mysite.com/Employee/ in browser a call is made to
www.Mysite.com/Employee/GetGridData
If i type www.Mysite.com/Employee in browser a call is made to
www.Mysite.com/GetGridData
Note: the missing / at the end in second call.
How to rectify this as the chances are end user can type any of this url in browser.
I'd take a look at how you're asking JqGrid to make it's web service call - because it won't know anything about MVC's routing engine by default - and this is all happening client side.
Stepping outside of MVC for a minute, if I have a page:
example.com/page1.aspx
And have a relative link to another page on there:
Click here
The browser will look for page2.aspx at the same level as page1.aspx, i.e.
example.com/page2.aspx
If I move page1 to a new folder:
example.com/NewFolder/page1.aspx
The browser will ask for
example.com/NewFolder/page2.aspx
when a user clicks on the link.
The same thing is happening to your GetGridData call - these are being made by the web browser to your server based on the information it has available to it.
So if your page responds on:
example.com/Employee
And asks for a relative request to:
GetGridData
The browser will send that request to the same level that Employee appears to be on:
example.com/GetGriddata
Which then fails because the routing engine can't find a route for that request.
You should look at generating the URL for the GetGridData call dynamically through the routing system, which will ensure that it's built as:
url: "/Employee/GetGridData"
Final edit to add
Forgot to mention, you should probably use the UrlHelper Action methods for this:
url: <%=Url.Action("GetGridData")%>
This will generate a path to the GetGridData method on the current controller. If you need to access a different controller, or pass some values, there are overloads to help.
Try debugging your route:
Phil Haack's: ASP.NET Routing Debugger

Resources