ADFS 3.0 - Extending functionality - javascript

I'm currently implementing a solution consisting in ADFS 3.0 with multifactor authentication. I've followed the steps in TechNet (https://msdn.microsoft.com/en-GB/Library/dn783423.aspx?f=255&MSPPError=-2147217396) to setup the sample adapter, which works fine.
I now want to extend it and have face a few issues. I've search the web and stackoverflow for something similar but couldn't find anything so I'm posting them all here. Not sure if I need to split this into different questions:
I need to extend the adapter so that part of the html is rendered by an external script, i.e. I need to add an extra script to be loaded when the adfs adapter html is rendered.
From what I could find, one could modify the Theme to include additional javascript in the onload.js, but I don't want to go down this road, since the script really needs to be loaded externally.
The only way I can think of, and kind of works, is to inject javascript in html that loads the script dinamically, something like this:
var script =document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", <my_script_loaded_over_http>)
fileref.onload =
function() {
//call script method
};
But because the external script depends on the "onload" event of the window for some of it's logic, it doesn't work since it's loaded too late..
Is this possible at all?
Is it possible for the adapter to inject new response headers? (I'm assuming it isn't)
Is there a standard way to provide a configuration file to the adapter dll, so that some values can be changed at runtime without having to deploy a new dll? If not, is it safe to write the said configuration file to the adfs folder and read from there?
Thank you very much

I managed to figure this out by myself:
1- The interface IAdapterPresentationForm provides a method to return whatever scripts or css I want to include: string GetFormPreRenderHtml(int lcid) e.g.:
public string GetFormPreRenderHtml(int lcid){
StringBuilder sb = new StringBuilder();
sb.Append("<script src='http://myjs.js' type='text/javascript'></script>");
sb.Append("<link rel='stylesheet' type='text/css' href='http://mycss.css' />");
return sb.ToString();
}
2- Not at all
3- It's possible to pass a configuration file when registering the adapter using:
Register-AdfsAuthenticationProvider -TypeName $typeName -Name -Verbose -ConfigurationFilePath .
The pipeline will open a stream for you, and pass it in:
void OnAuthenticationPipelineLoad(IAuthenticationMethodConfigData configData)
Reference: http://blogs.recneps.net/category/ADFS

Related

Is there a way to do custom resource loading in the Windows WebView2 component? Like a custom URL scheme, for instance?

I'm looking into using the WebView2 component for rendering some UI things on Windows, and I have a question about resource loading: for loading "normal" resources (i.e. HTML, CSS, images, JavaScript, whatever), the component mostly takes care of handling the loading of those resources itself. But I wonder if there is a way to hook into that loading process and control it yourself with WebView2?
As an example: say you want to load an image that is procedurally generated on native side of the WebView2, i.e. it is not in a file or on a server. How would you do that? Another example would be if you stored all your resources in a zip file or a SQLite database or something like that, and you wanted the WebView2 component to load resources directly from it (with you writing the "bridge" code yourself), how would you do that?
The reason I'm asking is because on macOS, WKWebView provides exactly this functionality by allowing you to create custom url schemes and hooking up handlers to them. This is exactly what I want, and it allows you to do something like this in your HTML:
<script type="text/javascript" src="my-scheme://test.js"/>
And on the Objective-C side, you can do a thing like this (leaving out boilerplate for hooking up my-scheme to this handler, this is the meat of the code for handling the response):
const char* data = "function testFunction() { return 18; }";
[task didReceiveResponse: [[NSURLResponse alloc]
initWithURL: task.request.URL
MIMEType: #"text/javascript"
expectedContentLength: strlen(data)
textEncodingName: #"ASCII"]];
[task didReceiveData: [NSData
dataWithBytes: data
length:strlen(data)]];
[task didFinish];
I.e. by registering the custom url scheme handler, I could send over my C string there as a JavaScript file. It doesn't have to be a hard-coded C string, obviously, as I mentioned the most relevant uses for me would be to provide procedurally generated resources, as well as loading things that are not necessarily stored as files (or on a web server). How would you do this with WebView2?
One way I have sent any type of file from native code to a browser is by converting the file to Base64 and then sending it to the browser. In the case of WebView2 you could use ExecuteScriptAsync. Once the Base64 string is received you could have javascript code (which you have previously injected) to convert it into a blob/file and then you can add it to any part of the DOM you want.

How to setup QWebChannel JS API for use in a QWebEngineView?

As Qt's documentation is far from complete, which are the ways to setup QWebChannel and are there different ones from adding a <script> tag in your HTML page like recommended in the documentation?
There are different options to load the needed script accessible at the URL qrc:///qtwebchannel/qwebchannel.js:
Notice:
you can only use that URL if you are viewing the page from within QWebEngineView. Otherwise you might need to load the API file to your webserver.
Prerequisites:
add QT += webchannel to your .pro file and run qmake
Using runJavaScript() to execute the code in Qt's QWebChannel JS API:
My prefered method because it seems simple and has been reliable so far.
Keep in mind the possibility that the API might not be set up by the time this code has finished as the runJavaScript() method does not block the current thread until the JS code has been executed.
QFile apiFile(":/qtwebchannel/qwebchannel.js"); //load the API from the resources
if(!apiFile.open(QIODevice::ReadOnly))
qDebug()<<"Couldn't load Qt's QWebChannel API!";
QString apiScript = QString::fromLatin1(apiFile.readAll());
apiFile.close();
QWebEngineView view; //your custom QWebEngineView
view.page().runJavaScript(apiScript);
Using runJavaScript() to execute code to load Qt's QWebChannel JS API:
Although I didn't try these methods they should still work, as they aim to load external JS files.
One of the methods suggested here might come in handy depending on which other libraries you use.
Using a <script> tag in the web page:
This is the default method recommended by Qt's documentation. It has the advantage of providing the API immediatly after the page was loaded.
The downside of this is that you need to modify the HTML of the web page which can be painful if you are not the owner of the site.
Don't forget create a QWebChannel object on the C++ side:
QWebChannel* channel_ = new QWebChannel(view.page());
//attach it to the QWebEnginePage
view.page()->setWebChannel(channel_);
//register a QObject to be exposed to JavaScript
channel_->registerObject(QStringLiteral("jshelper"), this);
Set up the QWebChannel on the JavaScript code:
As pointed out in the comments in order to share objects between C++ and JavaScript you need to initialize the QWebChannel.
new QWebChannel(qt.webChannelTransport, function (channel) {
var sharedObject = channel.objects.sharedObject;
});
This answer was thought as an addition to Qt's documentation, so if you want to add something feel free to do so.
Version: Qt 5.6.1
Sources:
QT QWebEnginePage::setWebChannel() transport object
How do I include a JavaScript file in another JavaScript file?
How to use Qt WebEngine and QWebChannel?
http://doc.qt.io/qt-5/qtwebchannel-javascript.html

How to Return static HTML and/or Javascript in OpenRasta

I am using OpenRasta 2.0, and am hosting within a console application.
I would like to be able to return some static HTML pages and JavaScript files from this setup, for example:
/index.html
/jquery.js
The files are entirely static, i.e. no Handler or Resource is required.
I have added the appropriate files to the project, and initially tried the following syntax:
ResourceSpace.Has
.ResourcesOfType<object>()
.AtUri("/")
.HandledBy<HtmlHandler>()
.RenderedByAspx("~/Views/IndexView.aspx");
The .aspx file is added to the project under a folder 'Views', and is set the build action to 'Embedded Resource'. This results in a NullReferenceException at runtime when attempting to resolve the virtual path. If I set the build action of the file to 'Compile', then it will not compile, I'm guessing because the console project does not understand ASPX.
I have also tried the following shorthand syntax for this available if referencing the WebForms codec:
ResourceSpace.Has
.TheUri("/jquery.js")
.ForThePage("~/Views/jquery.js");
But this suffers from the same issues as my initial approach, although does remove the need for a dummy Handler. So as far as I can tell, the WebForms codec cannot be used within a console application because the ASPX files cannot be compiled.
I was able to return HTML using the Razor codec as this expects the view templates to be embedded. However - I was not able to return a JavaScript file with the appropriate media type using the same technique, and I had to turn my otherwise static files into .cshtml files with a #resource defined.
I can't find any examples online of returning static HTML and/or JavaScript using OpenRasta. I would expect to find a dedicated configuration API for this like the "TheUri" syntax but independent of the WebForms codec.
I could create my own 'EmbeddedFileHandler' to return the content of a static embedded file, but I feel like I'm missing something since this is such a simple use case...
Anything that depends on the asp.net pipeline being initialized (such as aspx webforms pages) cannot compile because the BuildProvider is not there to do it, mostly because webforms is too tightly coupled to the asp.net pipeline.
OR 2 was not really designed to be used as a full web stack outside of asp.net for serving static content, as usually the host environment is better suited at doing it, but that's definitly something we're going to address in 3.0.
What I'd suggest is something along the lines of registering FileInfo as a resource, create a handler that can scan the file system for the files you want, and provide your own codec that either stream the data itself or call the API for the host http listener. It should be about 20 lines of code tops and would make a great blog post. :)

Embedding a JS file in Silverlight Class Library

I am trying to create a Silverlight class library which needs to call a few Javascript methods. I have put these methods in a single .js file and have added it to the project. But when I try to call any of the methods in the js file, I get a FailedtoInvoke error. I understand that this problem can be solved by adding a reference of the JS file in the head section of ASPX or HTML page. But I am developing a class library and so that is not possible. Does someone know how to tackle this issue? I am using Silverlight 4 and Visual Studio 2010.
Add the .js file to your library probject as it sounds you have done, make sure it Build Action is "Resource".
You can retrieve this content with Application.GetResourceStream :-
StreamResourceInfo sriJS = Application.GetResourceStream(new Uri("YourAssemblyName;component/MyStuff.js", UriKind.Relative));
Note the structure of the Uri, the assembly name of your class library is needed followed by the literal ";component". This tells Silverlight to look for a resource inside your dll that will be included in a final application's Xap.
Now you need to turn the content of the info's Stream property into a string:-
StreamReader reader = new StreamReader(sriJS.Stream, System.Text.Encoding.UTF8);
string js = reader.ReadToEnd();
Finally you can inject that javascript into the current page with:-
HtmlPage.Window.Eval(js);
Thats it, any global functions defined in the js may now be invoked with HtmlPage.Window.Invoke.
Try something like:
string myScriptCodeString = GetScriptCodeStringFromSomewhere();
System.Windows.Browser.HtmlPage.Window.Eval(myScriptCodeString);
Then the methods defined in myScriptCodeString should be available.

How do I stop js files being cached in IE?

I've created a page that uses the CKEditor javascript rich edit control.
It's a pretty neat control, especially seeing as it's free, but I'm having serious issues with the way it allows you to add templates.
To add a template you need to modify the templates js file in the CKEditor templates folder. The documentation page describing it is here.
This works fine until I want to update a template or add a new one (or anything else that requires me to modify the js file).
Internet Explorer caches the js file and doesn't pick up the update. Emptying the cache allows the update to be picked up, but this isn't an acceptable solution. Whenever I update a template I do not want to tell all of the users across the organisation to empty their IE cache. There must be a better way!
Is there a way to stop IE caching the js file? Or is there another solution to this problem?
Update
Ok, I found this section in the CKEditor API that will allow me to use the "insert timestamp into the url" solution suggested by several people.
So the script now looks like this:
config.templates_files =
[
'/editor_templates/site_default.js?time=' + utcTimeMilliseconds
];
Thanks for your help guys.
You can add rand seed to your js file. I mean <script src='jsFile.js?seed=12345'
And every time you want to empty cache - change seed number
Update:
as I understood you have to write like this config.templates_files = [ '/mytemplates.js?seed=12345' ];
Youo can add a timestamp query parameter when you include your .js file..
so instead of <script type="text/javascript" src="somefile.js"></script> you can <script type="text/javascript" src="somefile.js?timestampgoeshere"></script>
this should make the file to always get reloaded (the timestamp needs to be dynamic and changing for each load of the page..)
I am afraid you'll have to hack into the FCKEditor code and force the client JavaScript to load fresh copy of the XML file. You can do so by appending a ?random=<a random number> to the URL of the XML file being requested. FCKEditor is opensource so you should be able to locate the lines the request the XML and modify accordingly.
Set Expires-Header accordingly, e.g. in Apache
ExpiresActive On
ExpiresByType text/javascript access
This is not recommended for a real web application, only for intranet scenarios because the files will not be cachable.
every time you load the js file, pass a variable of a random number as a variable.
src='/libs/js/myfile.js?4859487594573
same trick for ajax loaded files.
Multiple methods (don't need to do them all):
press ^F5 (control + F5) - that'll load without cache
set pragma/cache headers on sending
use a random variable in the GET query string
.NET / C# :
public static void DisallowBrowserCache( )
{
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetAllowResponseInBrowserHistory(false);
}
You could make ASP.NET write a js file to the outputstream (http://server.com/jsFile.aspx, set http headers), and control the caching behavior of the response with the above method.

Categories