<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.5">Jekyll</generator><link href="https://bchavez.bitarmory.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://bchavez.bitarmory.com/" rel="alternate" type="text/html" /><updated>2019-06-01T22:23:23+00:00</updated><id>https://bchavez.bitarmory.com/feed.xml</id><title type="html">Bit Armory Blog</title><subtitle>Blog by Brian Chavez, software developer at Bit Armory Inc.</subtitle><author><name>Brian Chavez</name><email>bchavez@bitarmory.com</email></author><entry><title type="html">The curious case of a Windows Explorer hang</title><link href="https://bchavez.bitarmory.com/the-curious-case-of-an-windows-explorer-freeze/" rel="alternate" type="text/html" title="The curious case of a Windows Explorer hang" /><published>2019-06-01T00:00:00+00:00</published><updated>2019-06-01T00:00:00+00:00</updated><id>https://bchavez.bitarmory.com/the-curious-case-of-an-windows-explorer-freeze</id><content type="html" xml:base="https://bchavez.bitarmory.com/the-curious-case-of-an-windows-explorer-freeze/">&lt;p&gt;I’ve had my main development PC for about 7 years now and it’s still going strong. Sure, it’s old but holy-smokes think of it as a finely-tuned and well-oiled machine. Every setting on this machine has some kind of thought geared toward developer productivity. For example, &lt;a href=&quot;https://github.com/bchavez/AutoHotKeyEmacs&quot;&gt;emacs key-bindings for all windows in the &lt;strong&gt;Windows OS&lt;/strong&gt;&lt;/a&gt;. You name it.&lt;/p&gt;

&lt;p&gt;But I had this one nagging problem with &lt;strong&gt;Google Chrome&lt;/strong&gt;: When I clicked on an HTML button to upload a file the &lt;strong&gt;USER32&lt;/strong&gt; &lt;em&gt;“Open Dialog”&lt;/em&gt; box would come up. I would select the file to upload and soon as the &lt;em&gt;“Open Dialog”&lt;/em&gt; box closed, &lt;strong&gt;Chrome&lt;/strong&gt; would freeze for a good 10 to 15 seconds. Clicking anywhere in &lt;strong&gt;Chrome&lt;/strong&gt; during this hang would produce a &lt;strong&gt;Windows OS&lt;/strong&gt; “ding” sound for each click made anywhere on the browser.&lt;/p&gt;

&lt;p&gt;The same issue would happen when I downloaded a small file. The &lt;strong&gt;USER32&lt;/strong&gt; &lt;em&gt;“Save as…”&lt;/em&gt; dialog box would come up. I would select the folder to save the file. Soon as the save dialog box closed I would not be able to open the file for a good 10 to 15 seconds because &lt;strong&gt;Chrome&lt;/strong&gt; would be non-responsive for that brief period of time.&lt;/p&gt;

&lt;p&gt;The issue wasn’t 100% reproducible either; maybe 1 out of 8 times &lt;strong&gt;Chrome&lt;/strong&gt; would lock up. The issue &lt;strong&gt;Drove. Me. Nuts.&lt;/strong&gt; I’ve lived with this annoying bug for a very long time and it was time to put in some effort into tracking this issue down.&lt;/p&gt;

&lt;p&gt;So, I started with the usual &lt;a href=&quot;https://docs.microsoft.com/en-us/sysinternals/&quot;&gt;&lt;strong&gt;System Internals&lt;/strong&gt; tools&lt;/a&gt; to try to track the issue down. At first, not much luck…&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer&quot;&gt;&lt;strong&gt;Process Explorer&lt;/strong&gt;&lt;/a&gt; - I didn’t see any abnormal activity during the “hang” event in &lt;strong&gt;Chrome&lt;/strong&gt; or any other system processes.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/sysinternals/downloads/procmon&quot;&gt;&lt;strong&gt;Process Monitor&lt;/strong&gt;&lt;/a&gt; - Didn’t help much either. A few obscure registry accesses, but again, not much to go on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then, one day, I started &lt;a href=&quot;https://docs.microsoft.com/en-us/sysinternals/downloads/debugview&quot;&gt;&lt;strong&gt;DebugView&lt;/strong&gt;&lt;/a&gt; which logs &lt;strong&gt;Kernel-mode&lt;/strong&gt; &lt;a href=&quot;https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-dbgprint&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;DbgPrint&lt;/code&gt;&lt;/a&gt; calls. And by golly, right at the &lt;strong&gt;&lt;em&gt;EXACT&lt;/em&gt;&lt;/strong&gt; moment the freeze happened, the following output printed to &lt;strong&gt;DebugView&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;[FFFFFA8041F3F3A0]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WskProIRPGetAddrInfo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;called&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[bind=FFFFFA803B923C10]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Binding&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;00000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;impersonation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8040AA4360]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8040AA4360]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RPC&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rpc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;succeeded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rpc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pending&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8040AA4360]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA803FBB2EE0]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WskProIRPGetAddrInfo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;called&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[bind=FFFFFA803B923C10]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Binding&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;00000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;impersonation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8030B03EB0]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8030B03EB0]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RPC&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rpc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;succeeded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rpc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pending&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8030B03EB0]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8030B03EB0]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WskKnrRpcComplete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rpc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calls&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;back&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;completion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8030B03EB0]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WskKnrCompletePending&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;complete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pending&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rpc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8030B03EB0]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8030B03EB0]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8030B03EB0]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WskKnrCompleteRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rpc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;completion&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;00000000&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;00000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8030B03EB0]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WskProAPIGetAddressInfo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;returned&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addrinfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FFFFF8A0366AC6C0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[bind=FFFFFA803B923C10]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Binding&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8030B03EB0]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WskKnrCompleteRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;complete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;irp&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;00000000.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[addr=FFFFF8A0366AC6C0]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WskProAPIFreeAddressInfo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;freed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addrinfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8040AA4360]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WskKnrRpcComplete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rpc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calls&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;back&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;completion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8040AA4360]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WskKnrCompletePending&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;complete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pending&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rpc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8040AA4360]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8040AA4360]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8040AA4360]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WskKnrCompleteRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rpc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;completion&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;00000000&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c0000272&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8040AA4360]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WskProAPIGetAddressInfo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;returned&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addrinfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0000000000000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[bind=FFFFFA803B923C10]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Binding&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8040AA4360]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WskKnrCompleteRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;complete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;irp&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c0000272&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8040C4CD80]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WskProIRPGetAddrInfo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;called&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[bind=FFFFFA803B923C10]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Binding&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;00000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;impersonation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8030C7B660]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8030C7B660]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RPC&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rpc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;succeeded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rpc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pending&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[FFFFFA8030C7B660]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Very nice. Very very nice.&lt;/strong&gt; The output is virtually the same every time the freeze occurs. But what does all this mean? Let’s try decoding it.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;WskProIRPGetAddrInfo&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Wsk&lt;/code&gt; - probably relates to &lt;a href=&quot;https://docs.microsoft.com/en-us/windows-hardware/drivers/network/introduction-to-winsock-kernel&quot;&gt;Winsock Kernel-mode&lt;/a&gt; network APIs.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;IRP&lt;/code&gt; - probably relates to processing a &lt;strong&gt;Windows&lt;/strong&gt; I/O request packet.
        &lt;blockquote&gt;
          &lt;p&gt;An IRP structure is a partially opaque structure that represents an I/O request packet.&lt;/p&gt;

          &lt;p&gt;https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_irp&lt;/p&gt;
        &lt;/blockquote&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;GetAddrInfo&lt;/code&gt; - probably relates to getting network &lt;strong&gt;Addr&lt;/strong&gt;ess &lt;strong&gt;Info&lt;/strong&gt;mation.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;RPC method type = 1&lt;/code&gt; - some kind of &lt;strong&gt;Remote Procedure Call (RPC)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Definitely getting a strong sense that the issue is something network related. Maybe a timeout of some kind.&lt;/p&gt;

&lt;p&gt;After endless &lt;code class=&quot;highlighter-rouge&quot;&gt;livekd&lt;/code&gt; kernel-debug sessions I finally opened &lt;a href=&quot;https://www.wireshark.org&quot;&gt;&lt;strong&gt;WireShark&lt;/strong&gt;&lt;/a&gt; on a low-traffic NIC and sure enough I found the culprit:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/screen_3302.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Turns out, every time I open a &lt;em&gt;“Save as…”&lt;/em&gt; or &lt;em&gt;“Open File”&lt;/em&gt; dialog box in &lt;strong&gt;Chrome&lt;/strong&gt; my PC is sending &lt;strong&gt;NetBIOS&lt;/strong&gt; broadcasts on all NIC interfaces. The &lt;strong&gt;NetBIOS&lt;/strong&gt; names attempting to be resolved are related to &lt;strong&gt;Network Shortcuts&lt;/strong&gt; in my &lt;strong&gt;Windows Explorer&lt;/strong&gt; that I only use when my &lt;strong&gt;Virtual Private Network (VPN)&lt;/strong&gt; is connected as shown in the picture below:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/chrome_3295.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To remove &lt;strong&gt;Network Shortcuts&lt;/strong&gt;, simply right-click the network shortcut you want to remove and click “Delete”. You can also delete &lt;strong&gt;Network Shortcuts&lt;/strong&gt; stored in the following location:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;C:\Users\ACCOUNT\AppData\Roaming\Microsoft\Windows\Network Shortcuts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After I deleted the &lt;strong&gt;Network Shortcuts&lt;/strong&gt; in &lt;strong&gt;Windows Explorer&lt;/strong&gt; the momentary hangs in &lt;strong&gt;Google Chrome&lt;/strong&gt; disappeared.&lt;/p&gt;

&lt;p&gt;Case closed. :smile: :clap: :tada:&lt;/p&gt;</content><author><name>Brian Chavez</name><email>bchavez@bitarmory.com</email></author><category term="Errors" /><summary type="html">Explorer hangs and freezes using Chrome save/open dialog box with network shortcuts.</summary></entry><entry><title type="html">Setting up ProxyCap, Fiddler, and fixing SSL/TLS errors</title><link href="https://bchavez.bitarmory.com/proxycap-fiddler-ssl-error/" rel="alternate" type="text/html" title="Setting up ProxyCap, Fiddler, and fixing SSL/TLS errors" /><published>2019-04-17T00:00:00+00:00</published><updated>2019-04-17T00:00:00+00:00</updated><id>https://bchavez.bitarmory.com/proxycap-fiddler-ssl-error</id><content type="html" xml:base="https://bchavez.bitarmory.com/proxycap-fiddler-ssl-error/">&lt;p&gt;The following diagram shows a &lt;strong&gt;Fiddler&lt;/strong&gt; proxy (MITM) approach for decrypting HTTPS traffic from a remote machine.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/POWERPNT_2968.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I installed &lt;a href=&quot;http://www.proxycap.com&quot;&gt;&lt;strong&gt;ProxyCap&lt;/strong&gt;&lt;/a&gt; on the &lt;strong&gt;&lt;em&gt;remote machine&lt;/em&gt;&lt;/strong&gt; to redirect HTTPS / SSL / TLS traffic through a &lt;a href=&quot;https://www.telerik.com/fiddler&quot;&gt;&lt;strong&gt;Fiddler&lt;/strong&gt;&lt;/a&gt; proxy on another machine.&lt;/p&gt;

&lt;p&gt;For those unfamiliar, &lt;strong&gt;ProxyCap&lt;/strong&gt; is a utility that allows users to define “proxy rules” on a per-application basis instead of setting a global machine-wide proxy on a computer.&lt;/p&gt;

&lt;p&gt;The application I was trying to proxy through &lt;strong&gt;Fiddler&lt;/strong&gt; displayed the following error:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Additionally, the &lt;strong&gt;Fiddler&lt;/strong&gt; proxy machine would pop up an error dialog as shown below:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/Fiddler_2960.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Session #2: The server (*) presented a certificate that did not validate, because it was issued to a different host.&lt;/p&gt;

  &lt;p&gt;SANs: …&lt;br /&gt;
SUBJECT: …&lt;/p&gt;

  &lt;p&gt;This warning can be disabled by clicking Tools &amp;gt; Fiddler Options.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;the-solution&quot;&gt;The solution&lt;/h2&gt;

&lt;p&gt;In Fiddler, click &lt;code class=&quot;highlighter-rouge&quot;&gt;Tools &amp;gt; Fiddler Options...&lt;/code&gt; and ensure &lt;strong&gt;Fiddler&lt;/strong&gt; is setup to “allow remote computers to connect” as shown below:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/Fiddler_2965.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Next, export the “root certificate” on the &lt;strong&gt;Fiddler&lt;/strong&gt; proxy.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/Fiddler_2966.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Copy the &lt;code class=&quot;highlighter-rouge&quot;&gt;FiddlerRoot.cer&lt;/code&gt; to the &lt;strong&gt;&lt;em&gt;remote machine&lt;/em&gt;&lt;/strong&gt;. &lt;strong&gt;Right-click&lt;/strong&gt; the &lt;code class=&quot;highlighter-rouge&quot;&gt;FiddlerRoot.cer&lt;/code&gt; file on the &lt;strong&gt;&lt;em&gt;remote machine&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;Install&lt;/strong&gt; the certificate on the &lt;strong&gt;&lt;em&gt;remote machine&lt;/em&gt;&lt;/strong&gt;. Be sure to install the certificate into the &lt;strong&gt;“Trusted Root Certification Authorities”&lt;/strong&gt; store as shown below:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/certstore_2969.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Last but not least, on the &lt;strong&gt;remote machine&lt;/strong&gt;, be sure to define proxy rules with “Resolve names remotely” checked in &lt;strong&gt;ProxyCap&lt;/strong&gt; rules. This setting avoids IP and certificate mismatches.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/pcapui_2959.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And that’s all! Success!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/Fiddler_2970.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Happy debugging,&lt;br /&gt;
Brian Chavez&lt;/p&gt;</content><author><name>Brian Chavez</name><email>bchavez@bitarmory.com</email></author><summary type="html">Using ProxyCap and Fiddler to decrypt HTTPS traffic.</summary></entry><entry><title type="html">How to disable Skype v8 Automatic Updates</title><link href="https://bchavez.bitarmory.com/how-to-disable-skype-v8-automatic-updates/" rel="alternate" type="text/html" title="How to disable Skype v8 Automatic Updates" /><published>2019-02-07T00:00:00+00:00</published><updated>2019-02-07T00:00:00+00:00</updated><id>https://bchavez.bitarmory.com/how-to-disable-skype-v8-automatic-updates</id><content type="html" xml:base="https://bchavez.bitarmory.com/how-to-disable-skype-v8-automatic-updates/">&lt;p&gt;To disable Skype v8 updates. Simply browse to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;%AppData%\Microsoft\Skype for Desktop&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Right-click, &lt;code class=&quot;highlighter-rouge&quot;&gt;Skype-Setup.exe&lt;/code&gt; if present, and select &lt;strong&gt;Properties&lt;/strong&gt;.
    &lt;ul&gt;
      &lt;li&gt;If you don’t have this file, create a new text file named &lt;code class=&quot;highlighter-rouge&quot;&gt;Skype-Setup.exe&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Once you have the property window open, select the &lt;strong&gt;Security&lt;/strong&gt; tab.&lt;/li&gt;
  &lt;li&gt;In the &lt;strong&gt;Security&lt;/strong&gt; tab, &lt;strong&gt;Edit…&lt;/strong&gt; the permissions for your user account and others listed in the &lt;strong&gt;Groups or user names&lt;/strong&gt; and deny &lt;strong&gt;Full control&lt;/strong&gt; to the &lt;code class=&quot;highlighter-rouge&quot;&gt;Skype-Setup.exe&lt;/code&gt; file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After you complete the steps above, you should have a &lt;strong&gt;Security&lt;/strong&gt; tab that looks similar to the following:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/JPEGView_2760.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Then finally click &lt;strong&gt;Apply&lt;/strong&gt; and &lt;strong&gt;OK&lt;/strong&gt; to close the window. That’s it!&lt;/p&gt;</content><author><name>Brian Chavez</name><email>bchavez@bitarmory.com</email></author><summary type="html">Instructions on how to disable Skype v8 automatic updates.</summary></entry><entry><title type="html">New Blog Migrated from SubText to Jekyll and hosted on GitLab</title><link href="https://bchavez.bitarmory.com/blog-migrated-from-subtext-to-gitlab/" rel="alternate" type="text/html" title="New Blog Migrated from SubText to Jekyll and hosted on GitLab" /><published>2019-01-24T00:00:00+00:00</published><updated>2019-01-24T00:00:00+00:00</updated><id>https://bchavez.bitarmory.com/blog-migrated-from-subtext-to-gitlab</id><content type="html" xml:base="https://bchavez.bitarmory.com/blog-migrated-from-subtext-to-gitlab/">&lt;p&gt;Finally migrated off &lt;strong&gt;SubText&lt;/strong&gt; blog engine and migrated to a static generated &lt;strong&gt;Jekyll&lt;/strong&gt; format hosted on GitLab Pages. Pretty sweet so far. I can finally decommission that noob-ish blog of mine. :sunglasses:&lt;/p&gt;

&lt;p&gt;The main benefit of migrating to &lt;strong&gt;Jekyll&lt;/strong&gt; is having the ability to write Markdown for my blog posts. I’m a big fan of Markdown; especially GitHub flavored Markdown.&lt;/p&gt;

&lt;p&gt;I originally tried hosting the blog on &lt;strong&gt;GitHub Pages&lt;/strong&gt; but found some limitations. For one, your repository must be &lt;strong&gt;public&lt;/strong&gt;; not &lt;em&gt;private&lt;/em&gt; for GitHub pages to work. I prefer to keep my blog source private for now; so the GitHub option was off the table.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/chrome_2721.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Luckily, &lt;strong&gt;GitLab&lt;/strong&gt; has a similar feature called &lt;a href=&quot;https://about.gitlab.com/product/pages/&quot;&gt;GitLab Pages&lt;/a&gt;. &lt;strong&gt;GitLab Pages&lt;/strong&gt; works just like &lt;strong&gt;GitHub Pages&lt;/strong&gt; except you can keep your repo private.&lt;/p&gt;

&lt;p&gt;Migrating from &lt;strong&gt;SubText&lt;/strong&gt; wasn’t easy. The migration took several days. In general, the steps I took are as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Export the &lt;strong&gt;SubText&lt;/strong&gt; blog to BlogML/XML format. Make sure &lt;strong&gt;SubText&lt;/strong&gt; is updated to the latest version before extracting your first export.&lt;/li&gt;
  &lt;li&gt;Next, I followed the instructions here for &lt;a href=&quot;https://about.gitlab.com/product/pages/&quot;&gt;GitLab pages&lt;/a&gt;.
    &lt;ul&gt;
      &lt;li&gt;I forked the &lt;a href=&quot;https://gitlab.com/pages/jekyll&quot;&gt;https://gitlab.com/pages/jekyll&lt;/a&gt; example repo.&lt;/li&gt;
      &lt;li&gt;Added &lt;a href=&quot;https://mmistakes.github.io/minimal-mistakes/&quot;&gt;minimal-mistakes gem&lt;/a&gt; gem to the fork by modifying the &lt;code class=&quot;highlighter-rouge&quot;&gt;Gemfile&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;Configured &lt;code class=&quot;highlighter-rouge&quot;&gt;_config.yaml&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Read the Blog ML/XML format and extracted the blog content to the fork’s &lt;code class=&quot;highlighter-rouge&quot;&gt;_posts&lt;/code&gt; folder. The &lt;strong&gt;SubText&lt;/strong&gt;/BlogML XML content is base64 encoded. After the base64 decoding, I then used &lt;a href=&quot;https://pandoc.org&quot;&gt;Pandoc&lt;/a&gt; to convert the HTML into Markdown.
    &lt;ul&gt;
      &lt;li&gt;@pcibraro’s &lt;code class=&quot;highlighter-rouge&quot;&gt;BlogMLtoMarkdown&lt;/code&gt; provided a &lt;a href=&quot;https://github.com/pcibraro/BlogMLToMarkdown&quot;&gt;great start&lt;/a&gt; on the process.&lt;/li&gt;
      &lt;li&gt;Extracted the comments from BlogML/XML and wrote them out as YAML files. Basically, I’ve followed the &lt;code class=&quot;highlighter-rouge&quot;&gt;staticman&lt;/code&gt; YAML format.&lt;/li&gt;
      &lt;li&gt;Extracted redirects from the old blog so I wouldn’t break permalinks. I had to add a jekyll redirect gem.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Modified the dark theme heavily.&lt;/li&gt;
  &lt;li&gt;Modified the code highlight heavily.&lt;/li&gt;
  &lt;li&gt;Added &lt;strong&gt;Google Tag Manager&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Added &lt;strong&gt;Google Analytics&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Added &lt;strong&gt;reCAPTCHA v3 - Invisible&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Create my own version of &lt;code class=&quot;highlighter-rouge&quot;&gt;staticman&lt;/code&gt; in ASP.NET Core. Basically, the code processes blog comments and verifies the invisible reCAPTCHA tokens anytime someone leaves a comment.
    &lt;ul&gt;
      &lt;li&gt;If the reCAPTCHA score of the comment is &amp;gt; .89, I don’t moderate the comment.&lt;/li&gt;
      &lt;li&gt;If the score falls between 0.5 and 0.89, a pull-request is created for moderation.&lt;/li&gt;
      &lt;li&gt;If the score falls below 0.5, the comment is rejected.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The motivations for writing my own self-hosted ASP.NET clone of &lt;code class=&quot;highlighter-rouge&quot;&gt;staticman&lt;/code&gt; was:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;The public server for &lt;code class=&quot;highlighter-rouge&quot;&gt;staticman&lt;/code&gt; is API rate-limited by GitHub.&lt;/li&gt;
  &lt;li&gt;Doesn’t work with GitLab.&lt;/li&gt;
  &lt;li&gt;Requires exposing a REST endpoint with &lt;code class=&quot;highlighter-rouge&quot;&gt;node.js&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For now, I’ve tentatively named my ASP.NET Core clone of &lt;code class=&quot;highlighter-rouge&quot;&gt;staticman&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;ButlerBob&lt;/code&gt;. I’ll probably open-source it soon.&lt;/p&gt;

&lt;p&gt;In the end, lots of work. Happy to be blogging again. :sunglasses:&lt;/p&gt;</content><author><name>Brian Chavez</name><email>bchavez@bitarmory.com</email></author><summary type="html">Finally migrated off SubText blog engine and migrated to a static generated Jekyll format hosted on GitLab Pages. Pretty sweet so far. I can finally decommission that noob-ish blog of mine. :sunglasses:</summary></entry><entry><title type="html">List of Online Competitors Best Buy Price Matches</title><link href="https://bchavez.bitarmory.com/list-of-online-competitors-best-buy-price-matches/" rel="alternate" type="text/html" title="List of Online Competitors Best Buy Price Matches" /><published>2018-08-11T00:00:00+00:00</published><updated>2018-08-11T00:00:00+00:00</updated><id>https://bchavez.bitarmory.com/list-of-online-competitors-best-buy-price-matches</id><content type="html" xml:base="https://bchavez.bitarmory.com/list-of-online-competitors-best-buy-price-matches/">&lt;h4 id=&quot;as-of-8112018&quot;&gt;As of 8/11/2018:&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://www.amazon.com/&quot;&gt;Amazon.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.walmart.com/&quot;&gt;Walmart&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.newegg.com/&quot;&gt;Newegg.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.tigerdirect.com/&quot;&gt;TigerDirect.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.frys.com/&quot;&gt;Fry’s&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.microcenter.com/&quot;&gt;MicroCenter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.gamestop.com/&quot;&gt;Gamestop&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.officedepot.com/&quot;&gt;Office Depot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.staples.com/&quot;&gt;Staples&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.sears.com/&quot;&gt;Sears&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.target.com/&quot;&gt;Target&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.radioshack.com/&quot;&gt;RadioShack&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.costco.com/&quot;&gt;Costco&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.samsclub.com/&quot;&gt;Sam’s Club&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.homedepot.com/&quot;&gt;Home Depot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.lowes.com/&quot;&gt;Lowes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.bedbathandbeyond.com/&quot;&gt;Bed Bath &amp;amp; Beyond&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kohls.com/&quot;&gt;Kohl’s&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.macys.com/&quot;&gt;Macy’s&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.jcpenney.com/&quot;&gt;Jc Penney&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.guitarcenter.com/&quot;&gt;Guitar Center&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.videoandaudiocenter.com/main/&quot;&gt;Video and Audio Center&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.bhphotovideo.com/&quot;&gt;Bhphotovideo.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.crutchfield.com&quot;&gt;Crutchfield.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.dell.com&quot;&gt;Dell.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://hp.com&quot;&gt;HP.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.abcwarehouse.com/&quot;&gt;ABC Warehouse&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.abt.com/&quot;&gt;Abt&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.adorama.com/&quot;&gt;Adorama&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.ajmadison.com/&quot;&gt;AJ Madison&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.appliancesmart.com/&quot;&gt;Appliance Smart&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.badcock.com/&quot;&gt;Badcock&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.billsmith.com/&quot;&gt;Bill Smith Electronics&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.bjorns.com/&quot;&gt;Bjorn’s&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.bjs.com/&quot;&gt;BJ’s&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.brandsmartusa.com/&quot;&gt;BrandsMart USA&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.conns.com/&quot;&gt;Conn’s&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://cowboy-maloney.com&quot;&gt;Cowboy Maloney’s&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.herbergers.com&quot;&gt;Herbergers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://icuracao.com/&quot;&gt;Curacao&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.electronicexpress.com/&quot;&gt;Electronic Express&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.electronicsexpo.com/&quot;&gt;Electronics Expo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.fredmeyer.com/&quot;&gt;Fred Meyer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.goedekers.com/&quot;&gt;Goedekers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.hawthorneonline.com/&quot;&gt;Hawthorne&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://hhgregg.com/&quot;&gt;HHGregg&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://huppins.com/&quot;&gt;Huppin’s&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.kingsgreatbuys.com/&quot;&gt;King’s Great Buys Plus&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.listenup.com/&quot;&gt;Listen Up, Inc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.meijer.com/&quot;&gt;Meijer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.menards.com&quot;&gt;Menards&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://modia.com/&quot;&gt;Modia&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.nfm.com/&quot;&gt;Nebraska Furniture Mart&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.newenglandappliance.com/&quot;&gt;New England Appliance&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.pcrichard.com/&quot;&gt;PC Richard &amp;amp; Son&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.plessers.com/&quot;&gt;Plesser’s&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.queencityonline.com/&quot;&gt;Queen City&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.rcwilley.com/&quot;&gt;RCWilley&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.shopko.com/&quot;&gt;Shopko&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.thebigscreenstore.com/&quot;&gt;The Big Screen Store&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.valueelectronics.com/#gsc.tab=0&quot;&gt;Value Electronics&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vanns.com/&quot;&gt;Vann’s&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.videoonly.com/&quot;&gt;Video Only&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.walts.com/&quot;&gt;Walt’s TV&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.warnersstellian.com/&quot;&gt;Warners Stellian&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.worldwidestereo.com/&quot;&gt;World Wide Stereo&lt;/a&gt;&lt;/p&gt;</content><author><name>Brian Chavez</name><email>bchavez@bitarmory.com</email></author><summary type="html">As of 8/11/2018:</summary></entry><entry><title type="html">JSPM &amp;amp; third party library shims</title><link href="https://bchavez.bitarmory.com/jspm-third-party-library-shims/" rel="alternate" type="text/html" title="JSPM &amp; third party library shims" /><published>2015-09-10T00:00:00+00:00</published><updated>2015-09-10T00:00:00+00:00</updated><id>https://bchavez.bitarmory.com/jspm-third-party-library-shims</id><content type="html" xml:base="https://bchavez.bitarmory.com/jspm-third-party-library-shims/">&lt;p&gt;&lt;img src=&quot;/assets/images_old/1804632_a2eb7328-9feb-4dfa-9462-156611ec2186.jpg&quot; alt=&quot;1804632&quot; title=&quot;1804632&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I was hitting a LOT of friction trying to get unregistered
third-party packages to work with &lt;a href=&quot;http://jspm.io/&quot;&gt;JSPM&lt;/a&gt;. “Frictionless
browser package management” is the tag line, but only if you remain in
the “jspm universe”.&lt;/p&gt;

&lt;p&gt;In other words, if you try using a package that is not in the jspm
registry, you’re going to eventually run into vague dependency related
issues.&lt;/p&gt;

&lt;h3 id=&quot;the-example&quot;&gt;The example&lt;/h3&gt;

&lt;p&gt;Let’s suppose there’s a JavaScript library you want to use that’s not in
the &lt;a href=&quot;https://github.com/jspm/registry&quot;&gt;jspm registry&lt;/a&gt;. Let’s take
&lt;a href=&quot;https://github.com/corinis/jsForm&quot; title=&quot;https://github.com/corinis/jsForm&quot;&gt;https://github.com/corinis/jsForm&lt;/a&gt;
for example. jsForm is a jQuery plugin that’s dependent on jQuery, but
not registered or part of the jspm universe. You can manually install
jsForm from JSPM via “&lt;strong&gt;jspm install github:cornis/jsForm&lt;/strong&gt;” and jspm
will be happy to do your bidding.&lt;/p&gt;

&lt;p&gt;Unfortunately, if you try importing jsForm in a ES6 module like
this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import &quot;corinis/jsForm&quot;;
 
@autoinject
export class Login {
    private auth:AuthManager;
    router:Router;
    providers: any[];
 
    email:string;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You might run the risk of having jsFrom loading in an incorrect order
(where jsForm loads first, before jQuery is loaded). In order to
overcome this problem you have two choices:&lt;/p&gt;

&lt;h3 id=&quot;1-manual-import&quot;&gt;1. Manual Import&lt;/h3&gt;

&lt;p&gt;This step means modifying your initial SystemJS import statement like
this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
 
    System.import(&quot;jquery&quot;).then(function() {
        System.import(&quot;aurelia-bootstrapper&quot;);
    });
 
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This ensures jQuery is loaded before everything else. This method feels
like a hack and probably wont scale if we run into more dependency
related issues. So looking for a better way …. we find&lt;/p&gt;

&lt;h3 id=&quot;2-the-proper-shim-method&quot;&gt;2. The ‘proper’ Shim Method&lt;/h3&gt;

&lt;p&gt;The proper way is to use a shim. Basically, what we have to do is write
an override (aka shim) that “explicitly” defines the dependencies for
our non-registered jsForm jspm package. We do that by writing something
similar
to:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
   registry: 'jspm',
   main: 'js/jquery.jsForm',
   shim: {
    'js/jquery.jsForm': {
        deps: ['jquery']
     }
   },
   dependencies: { jquery: '*' }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And we’ll need to smash all this into a single line like so:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;jspm install github:corinis/jsForm -o “{ registry: ‘jspm’, main:
‘js/jquery.jsForm’, shim: { ‘js/jquery.jsForm’: { deps: [‘jquery’] }
}, dependencies: { jquery: ‘*’ } }”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ugh. Yes, ugly. This is the friction I’m talking about. It’s not very
friendly.&lt;/p&gt;

&lt;p&gt;A little bit about the override schema:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;main&lt;/strong&gt; - path to the main JS file in your
library to load. In our case “jspm_pacakges\github\corinis\jsForm@1.3.1\&lt;strong&gt;js\jquery.jsForm&lt;/strong&gt;.js”. Notice this is a relative path from the extracted package (in bold).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;shim&lt;/strong&gt;: { ‘js/jquery.jsForm’ : { deps:[‘jquery’]
} }&amp;lt;/span&amp;gt; - our dependency, notice here we’re using the aliased name to
“jquery” as defined in our config.js file.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;dependencies:&lt;/strong&gt; - any version of jquery will do.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;registry:&lt;/strong&gt; - wont work without it.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, if you execute the above JSPM command with the shim override,
you’ll see &lt;strong&gt;config.js&lt;/strong&gt; configuration changed and additional dependency
listed for
jsForm:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;github:corinis/jsForm@1.3.1&quot;: {
      &quot;jquery&quot;: &quot;github:components/jquery@2.1.4&quot;
    },
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Happy days. :)&lt;/p&gt;

&lt;p&gt;HTH,&lt;br /&gt;
Brian Chavez&lt;/p&gt;</content><author><name>Brian Chavez</name><email>bchavez@bitarmory.com</email></author><summary type="html"></summary></entry><entry><title type="html">Enabling Decorators Support in TypeScript 1.5, Visual Studio 2015</title><link href="https://bchavez.bitarmory.com/enabling-decorators-support-in-typescript-1-5-visual-studio-2015/" rel="alternate" type="text/html" title="Enabling Decorators Support in TypeScript 1.5, Visual Studio 2015" /><published>2015-07-24T00:00:00+00:00</published><updated>2015-07-24T00:00:00+00:00</updated><id>https://bchavez.bitarmory.com/enabling-decorators-support-in-typescript-1-5-visual-studio-2015</id><content type="html" xml:base="https://bchavez.bitarmory.com/enabling-decorators-support-in-typescript-1-5-visual-studio-2015/">&lt;p&gt;Finally installed VS2015, I got the following error in my TypeScript
project:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Error    TS1219    Experimental support for decorators is a feature that is subject
 to change in a future release. Specify '--experimentalDecorators' to remove this warning.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok. So, how exactly do you do this if you’re not the one invoking the
TSC compile action? Visual Studio TypeScript plugin is invoking the
compiler option. &lt;strong&gt;Hmm. tsconfig.json&lt;/strong&gt; compiler config doens’t seem to
be picked up by the TypeScript plug-in.&lt;/p&gt;

&lt;p&gt;To enable decorator support, unload your TypeScript project. Right
click, Edit Project .csproj. Find the TypeScript compiler option section
and add the following (&lt;strong&gt;Line 14 and
15&lt;/strong&gt;):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;PropertyGroup&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Condition=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;'$(Configuration)' == 'Debug'&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptModuleKind&amp;gt;&lt;/span&gt;amd&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TypeScriptModuleKind&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptCompileOnSaveEnabled&amp;gt;&lt;/span&gt;True&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TypeScriptCompileOnSaveEnabled&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptTarget&amp;gt;&lt;/span&gt;ES5&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TypeScriptTarget&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptNoImplicitAny&amp;gt;&lt;/span&gt;False&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TypeScriptNoImplicitAny&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptRemoveComments&amp;gt;&lt;/span&gt;False&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TypeScriptRemoveComments&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptOutFile&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptOutDir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptGeneratesDeclarations&amp;gt;&lt;/span&gt;False&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TypeScriptGeneratesDeclarations&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptNoEmitOnError&amp;gt;&lt;/span&gt;True&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TypeScriptNoEmitOnError&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptSourceMap&amp;gt;&lt;/span&gt;True&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TypeScriptSourceMap&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptMapRoot&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptSourceRoot&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptEmitDecoratorMetadata&amp;gt;&lt;/span&gt;True&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TypeScriptEmitDecoratorMetadata&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptExperimentalDecorators&amp;gt;&lt;/span&gt;True&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TypeScriptExperimentalDecorators&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Also, seems like the TypeScript 1.5 RTM plugin will respect the
decorator compile options when you use SAVE-ON-COMPILE. :)&lt;/p&gt;

&lt;p&gt;Hope that helps,&lt;br /&gt;
Brian Chavez&lt;/p&gt;</content><author><name>Brian Chavez</name><email>bchavez@bitarmory.com</email></author><category term="ASP.NET" /><summary type="html">Finally installed VS2015, I got the following error in my TypeScript project:</summary></entry><entry><title type="html">ASP.NET Identity, OAuth 2 Social Login, Web API 2, and MVC 5 SPAs</title><link href="https://bchavez.bitarmory.com/asp-net-identity-oauth-2-social-login-web-api-2-and-mvc-5-spas/" rel="alternate" type="text/html" title="ASP.NET Identity, OAuth 2 Social Login, Web API 2, and MVC 5 SPAs" /><published>2015-07-20T00:00:00+00:00</published><updated>2015-07-20T00:00:00+00:00</updated><id>https://bchavez.bitarmory.com/asp-net-identity-oauth-2-social-login-web-api-2-and-mvc-5-spas</id><content type="html" xml:base="https://bchavez.bitarmory.com/asp-net-identity-oauth-2-social-login-web-api-2-and-mvc-5-spas/">&lt;p&gt;&lt;img src=&quot;/assets/images_old/image_649518b5-4ca3-49d9-a5f6-6b64cfb237ad.png&quot; alt=&quot;image&quot; title=&quot;image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wow, that’s a mouthful. I feel like that lady on the right
sometimes.&lt;/p&gt;

&lt;p&gt;So, I spent a few days studying SPA applications and how to use external
social logins like Facebook and Google with Web API 2.&lt;/p&gt;

&lt;p&gt;It’s not for the faint of heart, especially when Microsoft’s Web API
template with VS 2013 is broken. Microsoft’s template implementation is
about 70% right.&lt;/p&gt;

&lt;p&gt;Pile on top, all the inconsistent Web API login routes to think about.
See &lt;a href=&quot;http://www.nakov.com/blog/2014/12/22/webapi-owin-identity-custom-login-service/&quot;&gt;this
post&lt;/a&gt;
for what’s broken. I mostly agree to some extent. In addition, it seems
like most “Web API” tutorials out there are outdated. Most of the
tutorials have a user’s browser parsing an obscure “auth_token”
somewhere along the OAuth login flow. Surprise! In MVC5 + WebAPI2 +
Social Login, there is no auth token homie! Now, it’s all handled by
the middleware. LoL. Eh, well, whatever, I didn’t want to expose a scary
sensitive auth token to the user’s browser anyway. But I digress.&lt;/p&gt;

&lt;h3 id=&quot;before-we-begin-some-articles--references-that-will-help-you&quot;&gt;Before we begin, some articles &amp;amp; references that will help you&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;IETF’s RFC on OAuth 2 Spec:
&lt;a href=&quot;http://tools.ietf.org/html/rfc6749#section-4.1&quot; title=&quot;http://tools.ietf.org/html/rfc6749#section-4.1&quot;&gt;http://tools.ietf.org/html/rfc6749#section-4.1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Great Stack Overflow Question on why &lt;a href=&quot;http://stackoverflow.com/questions/3487991/why-does-oauth-v2-have-both-access-and-refresh-tokens&quot;&gt;Auth Tokens &amp;amp; Refresh
Tokens&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Using &lt;a href=&quot;http://bitoftech.net/2014/08/11/asp-net-web-api-2-external-logins-social-logins-facebook-google-angularjs-app/&quot;&gt;Web API 2 external logins with Facebook &amp;amp;
Google&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Distilled down to a single blog post, I present to you, ASP.NET
Identity’s OAuth2 Social Login flow with Web API
2:&lt;/p&gt;

&lt;h3 id=&quot;so-it-begins-a-new-user-arrives&quot;&gt;So it begins, a new user arrives&lt;/h3&gt;

&lt;h2 id=&quot;figure-a&quot;&gt;Figure A:&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images_old/image_43509d6e-49db-484f-aca9-73175b053fd2.png&quot; alt=&quot;image&quot; title=&quot;image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Figure A, the user arrives and hits your MVC app. Your MVC app sends
down your SPA. The user navigates to a login page and Figure B
happens.&lt;/p&gt;

&lt;h2 id=&quot;figure-b&quot;&gt;Figure B:&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images_old/image_ea9f1075-30b3-4810-812c-f96739d6e2d0.png&quot; alt=&quot;image&quot; title=&quot;image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Your SPA app consumes the JSON from ExternalLogins call and renders some
choices. In Figure B, Google and Facebook are configured on the server’s
OWIN middleware.
Cool.&lt;/p&gt;

&lt;h2 id=&quot;figure-c&quot;&gt;Figure C:&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images_old/image_2d857fe7-36b3-46ca-b585-58c5e833fb43.png&quot; alt=&quot;image&quot; title=&quot;image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The user decides to login with “Facebook”. In Figure C, it’s a full-page
navigation to the URL of &lt;strong&gt;/ExternalLogin?provider=Facebook&lt;/strong&gt;. &lt;em&gt;Not an
AJAX call&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AuthController.cs&lt;/strong&gt; (originally &lt;strong&gt;AccountController.cs&lt;/strong&gt; from the
original template) sees this request, and processing goes up to a
&lt;strong&gt;ChallengeResult&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-cs highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// GET api/auth/ExternalLogin &lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[OverrideAuthentication]&lt;/span&gt; 
&lt;span class=&quot;na&quot;&gt;[HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]&lt;/span&gt; 
&lt;span class=&quot;na&quot;&gt;[AllowAnonymous]&lt;/span&gt; 
&lt;span class=&quot;na&quot;&gt;[Route(&quot;ExternalLogin&quot;, Name = &quot;ExternalLogin&quot;)]&lt;/span&gt; 
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IHttpActionResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetExternalLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Redirect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;~/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;#error=&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;EscapeDataString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;c1&quot;&gt;//ANONYMOUS will always get trapped here. &lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Identity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsAuthenticated&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ChallengeResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A &lt;strong&gt;ChallengeResult&lt;/strong&gt; is returned to the anonymous user. A
&lt;strong&gt;ChallengeResult&lt;/strong&gt; looks
like:&lt;/p&gt;

&lt;div class=&quot;language-cs highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ChallengeResult&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IHttpActionResult&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ChallengeResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loginProvider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ApiController&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;LoginProvider&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loginProvider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LoginProvider&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpRequestMessage&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HttpResponseMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ExecuteAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CancellationToken&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cancellationToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetOwinContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Authentication&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Challenge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LoginProvider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;HttpResponseMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HttpStatusCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Unauthorized&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
            &lt;span class=&quot;n&quot;&gt;RequestMessage&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt; 
        &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FromResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;ChallengeResult&lt;/strong&gt; has an HTTP Status Code of &lt;strong&gt;Unauthorized&lt;/strong&gt;. When
MVC is executing the &lt;strong&gt;ChallengeResult,&lt;/strong&gt; MVC notifies the OWIN
middleware of an &lt;strong&gt;Authentication.Challenge(“Facebook”)&lt;/strong&gt;. The
unauthorized status code triggers the OWIN middleware to wake up and
process the pending &lt;strong&gt;Authorization.Challenge&lt;/strong&gt;, and transform the
unauthorized status into a 302 redirect to an off-site login provider
(Facebook in this case) for authorization as shown in &lt;strong&gt;Step 7 in Figure
C&lt;/strong&gt; above. Take note, in particular, the 302 redirect to Facebook has
“&lt;strong&gt;redirect_uri=http://webapp.com/signin-facebook&lt;/strong&gt;”. This is a
callback into the middleware that the user’s browser will hit after they
are finished authenticating and authorizing your web app on Facebook. In
addition, &lt;em&gt;&lt;span class=&quot;underline&quot;&gt;take 2nd note&lt;/span&gt;&lt;/em&gt;, the middleware
has instructed the browser to set a &lt;strong&gt;Correlation.Facebook&lt;/strong&gt; cookie in
&lt;strong&gt;Step 7 in Figure C&lt;/strong&gt; above.&lt;/p&gt;

&lt;p&gt;The user’s browser follows the redirect as shown in Figure D
below:&lt;/p&gt;

&lt;h2 id=&quot;figure-d&quot;&gt;Figure D:&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images_old/image_63bc1d5e-a49d-4f94-a4e7-52938481de11.png&quot; alt=&quot;image&quot; title=&quot;image&quot; /&gt; &lt;/p&gt;

&lt;p&gt;In Figure D Step 8 above, the user authenticates with Facebook and
authorizes WebApp.&lt;/p&gt;

&lt;p&gt;Then, Figure D Step 9, Facebook issues a 302 redirect to the user’s
browser back on the OWIN middleware endpoint &lt;strong&gt;/signin-facebook.&lt;/strong&gt; The
browser follows the redirect shown in &lt;strong&gt;Figure E Step 10
below&lt;/strong&gt;:&lt;/p&gt;

&lt;h2 id=&quot;figure-e&quot;&gt;Figure E:&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images_old/image_1847001f-73a1-4c50-86cf-e89bb43c7cd8.png&quot; alt=&quot;image&quot; title=&quot;image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Side Note:&lt;/em&gt;&lt;/strong&gt; When the middleware receives the &lt;strong&gt;/signin-facebook&lt;/strong&gt;
callback, the middleware needs to check if the current callback
originated from the WebApp to prevent a CSRF attack. The Facebook
middleware inspects &lt;strong&gt;Correlation.Facebook&lt;/strong&gt; cookie and matches the
cookie with some encrypted state inside the callback that was part of
the query string on the way out to Facebook and on the way back in from
Facebook. Hewf. Stay with me now…&lt;/p&gt;

&lt;p&gt;Next, the OWIN middleware uses the &lt;strong&gt;code&lt;/strong&gt; query string to setup a
backchannel with Facebook. The &lt;strong&gt;code=AQABC…&lt;/strong&gt; from &lt;strong&gt;Figure E, Step
10,&lt;/strong&gt; is a &lt;strong&gt;code&lt;/strong&gt; to get a &lt;strong&gt;&lt;em&gt;real&lt;/em&gt;&lt;/strong&gt; &lt;strong&gt;access_token.&lt;/strong&gt; The &lt;strong&gt;access
token&lt;/strong&gt; is then used to query Facebook’s Open Graph to get some claims
about the user, like their Name, picture, email, etc … &lt;strong&gt;Step 11 and
Step 12 in Figure E&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Finally, the OWIN middleware has enough information to create a
&lt;strong&gt;ClaimsIdentity&lt;/strong&gt; of an e&lt;em&gt;xternal login&lt;/em&gt;, and does so by granting an
&lt;strong&gt;AuthenticationTicket&lt;/strong&gt; associated with an &lt;strong&gt;ExternalCookie&lt;/strong&gt;
authentication type. The Facebook middleware packs all the claims from
the Facebook backchannel into this cookie called
&lt;strong&gt;.AspNet.ExternalCookie&lt;/strong&gt; as shown in &lt;strong&gt;Step 13 in Figure E&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, the OWIN middleware redirects the user’s browser *back* into
the MVC layer (remember our old URL that originally kicked off the
process? &lt;strong&gt;/api/auth/ExternalLogin&lt;/strong&gt;). Yep. I know. But, this time,
we’re going to &lt;em&gt;&lt;span class=&quot;underline&quot;&gt;get past&lt;/span&gt;&lt;/em&gt; the original
&lt;strong&gt;ChallengeResult&lt;/strong&gt; because were coming back as an externally
authenticated user with the help of [&lt;strong&gt;OverrideAuthentication&lt;/strong&gt;]+
[&lt;strong&gt;HostAuthentication(ExternalCookie)&lt;/strong&gt;], which sets up the
&lt;strong&gt;User.Identity.IsAuthenticated&lt;/strong&gt; to return
&lt;em&gt;&lt;span class=&quot;underline&quot;&gt;true&lt;/span&gt;&lt;/em&gt; skipping the challenge as shown
below:&lt;/p&gt;

&lt;div class=&quot;language-cs highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// GET api/auth/ExternalLogin &lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[OverrideAuthentication]&lt;/span&gt; 
&lt;span class=&quot;na&quot;&gt;[HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]&lt;/span&gt; 
&lt;span class=&quot;na&quot;&gt;[AllowAnonymous]&lt;/span&gt; 
&lt;span class=&quot;na&quot;&gt;[Route(&quot;ExternalLogin&quot;, Name = &quot;ExternalLogin&quot;)]&lt;/span&gt; 
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IHttpActionResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetExternalLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Redirect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;~/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;#error=&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;EscapeDataString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;c1&quot;&gt;//ANONYMOUS will always get trapped here. &lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Identity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsAuthenticated&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ChallengeResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;externalLogin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExternalLoginData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FromIdentity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ClaimsIdentity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;externalLogin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;InternalServerError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;externalLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LoginProvider&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;Authentication&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SignOut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DefaultAuthenticationTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ExternalCookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ChallengeResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UserManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FindAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;UserLoginInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;externalLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LoginProvider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;externalLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ProviderKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; 

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasRegistered&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasRegistered&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;Authentication&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SignOut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DefaultAuthenticationTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ExternalCookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 

        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oAuthIdentity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UserManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GenerateUserIdentityAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OAuthDefaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AuthenticationType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cookieIdentity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UserManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GenerateUserIdentityAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CookieAuthenticationDefaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AuthenticationType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 

        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UserManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CreateProperties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 

        &lt;span class=&quot;n&quot;&gt;Authentication&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SignIn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oAuthIdentity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cookieIdentity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Redirect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;~/app#home&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;c1&quot;&gt;//so even if we get here, ANONYMOUS will never get this far. &lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//The browser has been authorized by an external provider. &lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//The next step is for the browser to call /RegisterExternal &lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//to register an account. We'll throw up an authorized splash to confirm. &lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Redirect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;~/app#/authorized&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This time, we hit the bottom of the &lt;strong&gt;/api/ExternalLogin&lt;/strong&gt; call.  This
is the part where you can customize the login process. The OWIN
middleware has already done the hard work for you. In the case where the
user has never registered on WebApp, you have a small window of time to
use the &lt;strong&gt;ExternalCookie&lt;/strong&gt; login information for purposes of
registration. We redirect the user’s browser to &lt;strong&gt;~/app#/authorized,&lt;/strong&gt;
where we throw up a screen and ask for a username. The user clicks
“Register” which then calls our Web API endpoint
&lt;strong&gt;/api/auth/RegisterExternal&lt;/strong&gt;.&lt;/p&gt;

&lt;div class=&quot;language-cs highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// POST api/auth/RegisterExternal &lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;[OverrideAuthentication]&lt;/span&gt; 
&lt;span class=&quot;na&quot;&gt;[HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]&lt;/span&gt; 
&lt;span class=&quot;na&quot;&gt;[Route(&quot;RegisterExternal&quot;)]&lt;/span&gt; 
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IHttpActionResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RegisterExternal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RegisterExternalBindingModel&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ModelState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsValid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;BadRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ModelState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;info&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Authentication&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetExternalLoginInfoAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;info&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;InternalServerError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UserManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FindAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Login&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
     
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasRegistered&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
     
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasRegistered&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;BadRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;External user already registered.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UserName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Email&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Email&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt; 

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UserManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CreateAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Succeeded&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetErrorResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UserManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddLoginAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Login&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Succeeded&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetErrorResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And our user now has a local account.&lt;/p&gt;

&lt;p&gt;Next blog post I’ll will show how to transform the &lt;strong&gt;ExternalCookie&lt;/strong&gt;
AuthenticationType into a &lt;em&gt;local&lt;/em&gt; usable &lt;strong&gt;access_token&lt;/strong&gt; for &lt;strong&gt;Token
Barer Authentication&lt;/strong&gt; for Web API during the life time of the SPA
application.&lt;/p&gt;

&lt;p&gt;HTH,&lt;br /&gt;
Brian Chavez&lt;/p&gt;</content><author><name>Brian Chavez</name><email>bchavez@bitarmory.com</email></author><category term="ASP.NET" /><category term="C#" /><summary type="html"></summary></entry><entry><title type="html">Newbies Guide to Aurelia and TypeScript</title><link href="https://bchavez.bitarmory.com/newbies-guide-to-aurelia-and-typescript/" rel="alternate" type="text/html" title="Newbies Guide to Aurelia and TypeScript" /><published>2015-07-03T00:00:00+00:00</published><updated>2015-07-03T00:00:00+00:00</updated><id>https://bchavez.bitarmory.com/newbies-guide-to-aurelia-and-typescript</id><content type="html" xml:base="https://bchavez.bitarmory.com/newbies-guide-to-aurelia-and-typescript/">&lt;p&gt;&lt;img src=&quot;/assets/images_old/aurelia_ts_meme.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So, after about 24 hours trying to understand and establish
a workflow for a new JS framework called &lt;a href=&quot;http://aurelia.io/&quot;&gt;Aurelia&lt;/a&gt;
and &lt;a href=&quot;http://www.typescriptlang.org/&quot;&gt;TypeScript&lt;/a&gt;, I think I’ve finally
forged a path to use both in harmony in Visual Studio 2013.&lt;/p&gt;

&lt;h3 id=&quot;first-some-important-concepts&quot;&gt;First, some important concepts&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://aurelia.io/&quot;&gt;Aurelia&lt;/a&gt; is written in ES6/ES7. Aurelia is
distributed through &lt;a href=&quot;http://jspm.io/&quot;&gt;jspm&lt;/a&gt;. The Aurelia distribution
through &lt;a href=&quot;http://kasperlewau.github.io/registry/#/&quot;&gt;jspm&lt;/a&gt; is ES5 code.
Aurelia ES5 via jspm is runnable inside your browser.&lt;/p&gt;

&lt;p&gt;If you plan on writing view models in TypeScrypt then all you need to be
concerned about is transpiling your &lt;strong&gt;App.ts (*.ts)&lt;/strong&gt; &lt;strong&gt;View Models&lt;/strong&gt;
into ES5 code.&lt;/p&gt;

&lt;h3 id=&quot;get-the-tools&quot;&gt;Get the Tools&lt;/h3&gt;

&lt;p&gt;To get setup, you’re going to need:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://nodejs.org/&quot;&gt;NodeJS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nodejs.org/&quot;&gt;Git&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Be sure you can access &lt;strong&gt;git&lt;/strong&gt; and &lt;strong&gt;npm&lt;/strong&gt; from the command line before
continuing.&lt;/p&gt;

&lt;h3 id=&quot;setup-the-framework&quot;&gt;Setup the Framework&lt;/h3&gt;

&lt;p&gt;Next, in a command prompt make sure you have the following installed:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;npm install jspm -g&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;npm install tsd -g&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, you should go to your github account and create an
&lt;strong&gt;access token&lt;/strong&gt; for jspm because jspm will hit a lot of github repos
when resolving dependencies. This means you can run up against an
anonymous rate limit rather quickly. I did! Also, ensure the token you
generate also has “public_repo” permission with it; otherwise you’ll
run up against the same rate limit as an anonymous user and jspm
requests will get 404s &amp;amp; projects not found. &lt;strong&gt;Do not skip this step&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Use the following command to configure jspm and github:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;jspm registry config github&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a working folder for your project, and:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;tsd init&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;jspm install aurelia-framework&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;jspm install aurelia-bootstrapper&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Copy all the *.d.ts type definitions inside “jspm_packages\github\aurelia” into a new folder “\typings\aurelia”.&lt;/p&gt;

&lt;p&gt;Then run in the root of your project folder:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;tsd rebundle&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &amp;gt;&amp;gt; added:  
     - aurelia/aurelia-binding.d.ts  
     - aurelia/aurelia-dependency-injection.d.ts  
     - aurelia/aurelia-event-aggregator.d.ts  
     - aurelia/aurelia-framework.d.ts  
     - aurelia/aurelia-history-browser.d.ts  
     - aurelia/aurelia-history.d.ts  
     - aurelia/aurelia-loader-default.d.ts  
     - aurelia/aurelia-loader.d.ts  
     - aurelia/aurelia-logging-console.d.ts  
     - aurelia/aurelia-logging.d.ts  
     - aurelia/aurelia-metadata.d.ts  
     - aurelia/aurelia-path.d.ts  
     - aurelia/aurelia-route-recognizer.d.ts  
     - aurelia/aurelia-router.d.ts  
     - aurelia/aurelia-task-queue.d.ts  
     - aurelia/aurelia-templating-binding.d.ts  
     - aurelia/aurelia-templating.d.ts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Your “typings\tsd.d.ts” file should have all the necessary references
now. (&lt;strong&gt;TIP&lt;/strong&gt;: Setup a gulp script to automate this process, You’ll need
to re-do this every time you update Aurelia).&lt;/p&gt;

&lt;p&gt;Almost there …&lt;/p&gt;

&lt;p&gt;Get &lt;a href=&quot;https://github.com/cmichaelgraham/aurelia-typescript/tree/typescript-1-5-port/skel-nav-esri-gulp/typings&quot;&gt;corejs.d.ts&lt;/a&gt; and
&lt;a href=&quot;https://github.com/cmichaelgraham/aurelia-typescript/tree/typescript-1-5-port/skel-nav-esri-gulp/typings&quot;&gt;es6.d.ts&lt;/a&gt; from &lt;a href=&quot;https://github.com/cmichaelgraham/aurelia-typescript/tree/typescript-1-5-port/skel-nav-esri-gulp/typings&quot;&gt;this repo&lt;/a&gt; (or if using gulp/npm typescript:
node_modules\typescript\bin\lib.es6.d.ts) and add both into “typings\”. You will need to reference these in your &lt;strong&gt;*.ts&lt;/strong&gt; files.&lt;/p&gt;

&lt;p&gt;At this point, you can create an empty MVC project inside your working
folder at root level. Configure your routes and add a simple view with
(no layout). Your .csproj file should be in the same directory with your
proejct.json and config.js file.&lt;/p&gt;

&lt;p&gt;If you’re using Visual Studio, make sure your TypeScript compiler
“Module system” is set to AMD. Project &amp;gt; Properties &amp;gt; TypeScript
Build: Module
system&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images_old/image_1ec3edff-1ac0-43ee-8e2e-7f2130e02a56.png&quot; alt=&quot;image&quot; title=&quot;image&quot; /&gt; &lt;/p&gt;

&lt;p&gt;Create an &lt;strong&gt;app.ts&lt;/strong&gt; file in the root project
folder:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/// &amp;lt;reference path=&quot;typings/tsd.d.ts&quot; /&amp;gt; 
/// &amp;lt;reference path=&quot;typings/es6.d.ts&quot; /&amp;gt; 
/// &amp;lt;reference path=&quot;typings/core-js.d.ts&quot; /&amp;gt; 

import {Router} from 'aurelia-router'; 

export class App { 
    constructor() { 
        this.message = &quot;Hello World&quot;; 
    } 

    message:string; 
} 

console.log(&quot;THIS APP RAN!&quot;);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;SAVE. Your &lt;strong&gt;app.ts -&amp;gt; app.js&lt;/strong&gt; should have AMD module layout.&lt;/p&gt;

&lt;p&gt;Create an &lt;strong&gt;app.html&lt;/strong&gt; view in the root project folder:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt; 
     
    &amp;lt;h2&amp;gt;My App&amp;lt;/h2&amp;gt; 
     
    &amp;lt;span&amp;gt;${message}&amp;lt;/span&amp;gt; 

&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Save.&lt;/p&gt;

&lt;p&gt;Create an &lt;strong&gt;index.cshtml&lt;/strong&gt; file (Razor / No Shared Layout):&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt; 

&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt; 
&lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt; 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;viewport&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;width=device-width&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt; 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;~/jspm_packages/system.js&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt; 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;~/config.js&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt; 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;&lt;/span&gt; 
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt; 
&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;aurelia-app&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; 
     
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt; 
        &lt;span class=&quot;nx&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;aurelia-bootstrapper&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt; 
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt; 
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;SAVE.&lt;/p&gt;

&lt;p&gt;Run the app, make a request for the application index and
poof!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images_old/image_d3bf27b5-a5ea-4676-b9a9-17744c2935e5.png&quot; alt=&quot;image&quot; title=&quot;image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Much success.
:)&lt;/p&gt;

&lt;h3&gt; &lt;/h3&gt;

&lt;h3 id=&quot;pro-tip-going-the-extra-mile-to-get-decorators-working-with-dependency-injection&quot;&gt;PRO TIP: Going the extra mile to get decorators working with Dependency Injection&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;SEE &lt;a href=&quot;http://bchavez.bitarmory.com/archive/2015/07/23/enabling-decorators-support-in-typescript-1-5-visual-studio-2015.aspx&quot;&gt;UPDATE: Using TypeScript 1.5 RTM and
VS2015&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re using Gulp, this is really easy, use a &lt;strong&gt;tsconfig.json&lt;/strong&gt;  and
enable &lt;strong&gt;emitDecoratorMetadata&lt;/strong&gt; CompilerOptions flag. If you’re using
&lt;strong&gt;gulp-typescript&lt;/strong&gt; pass a configure options object with
&lt;strong&gt;emitDecoratorMetadata : true&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you’re using Visual Studio 2013, unload your &lt;strong&gt;.csproj&lt;/strong&gt;, and edit
the configuration. Locate the following MSBuild props and add
&lt;strong&gt;TypeScriptAdditionalFlags&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;PropertyGroup&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Condition=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;'$(Configuration)' == 'Debug'&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptModuleKind&amp;gt;&lt;/span&gt;amd&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TypeScriptModuleKind&amp;gt;&lt;/span&gt; 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptAdditionalFlags&amp;gt;&lt;/span&gt; $(TypeScriptAdditionalFlags) --emitDecoratorMetadata &lt;span class=&quot;nt&quot;&gt;&amp;lt;/TypeScriptAdditionalFlags&amp;gt;&lt;/span&gt; 
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;SAVE. Reload the project. Restart Visual Studio to make sure these
changes really take effect. Hit the “Rebuild” on your project and you
should now see your decorators working. How? You should see
&lt;strong&gt;__metadata&lt;/strong&gt; in the
output:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images_old/image_c45e706b-50e5-404a-b6f3-c54f614bdfb5.png&quot; alt=&quot;image&quot; title=&quot;image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, modifying your .csproj will only work with “MSBuild”
invocations like “Build/Rebuild”. This will not work with
compile-on-SAVE option inside VS. If you want a workflow of
compile-on-SAVE, you’ll ultimately need to use gulp. I really tried
hunting for the compiler options VS uses for compiling-on-SAVE but I
couldn’t find the hook point. I suspect it’s somewhere deep inside
Microsoft’s closed-source TypeScript plug-in for VS2013.
&lt;span style=&quot;color: #e1795f&quot;&gt;&lt;strong&gt;TypeScriptAdditionalFlags&lt;/strong&gt;&lt;/span&gt; is
simply not picked up by the VS 2013 TypeScript plug-in. Hopefully, this
changes in TypeScript 1.5 RTM.&lt;/p&gt;

&lt;p&gt;If you decide to use gulp for compile-on-SAVE ensure you DISABLE
compile-on-save inside Visual Studio your project
options:&lt;/p&gt;

&lt;p&gt; &lt;img src=&quot;/assets/images_old/image_2a2e3bea-16bf-447f-90ca-08c0efe10ba2.png&quot; alt=&quot;image&quot; title=&quot;image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Otherwise, both gulp and VS will overwrite each
other.&lt;/p&gt;

&lt;h3 id=&quot;pro-tip-using-jspm-to-use-packages-that-are-not-officially-in-the-global-registry&quot;&gt;PRO TIP: Using jspm to use packages that are not “officially” in the global registry&lt;/h3&gt;

&lt;p&gt;Credits to &lt;a href=&quot;https://github.com/grofit&quot;&gt;@grofit&lt;/a&gt; for the tip:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://kasperlewau.github.io/registry/#/&quot;&gt;jspm&lt;/a&gt;’s global register is
rather limited compared to something like &lt;a href=&quot;http://bower.io/&quot;&gt;bower.io&lt;/a&gt;.
For example, &lt;a href=&quot;https://github.com/CodeSeven/toastr&quot;&gt;toastr&lt;/a&gt; isn’t inside
the jspm registry, but you could do this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jspm install github:CodeSeven/toastr
     Looking up github:CodeSeven/toastr 
     Updating registry cache... 
     Downloading github:CodeSeven/toastr@2.1.1 
ok   Installed CodeSeven/toastr as github:CodeSeven/toastr@^2.1.1 (2.1.1) 
ok   Install tree has no forks.

ok   Install complete.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;pro-tip-understanding-aurelia-value-converters&quot;&gt;PRO TIP: Understanding Aurelia Value Converters&lt;/h3&gt;

&lt;p&gt;See this:
&lt;a href=&quot;http://jdanyow.github.io/aurelia-converters-sample/&quot; title=&quot;http://jdanyow.github.io/aurelia-converters-sample/&quot;&gt;http://jdanyow.github.io/aurelia-converters-sample/&lt;/a&gt;.
Really good tutorial on value
converters.&lt;/p&gt;

&lt;h3 id=&quot;pro-tip-using-jquery-plugins-with-aurelia&quot;&gt;PRO TIP: Using jQuery Plugins with Aurelia&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images_old/image_4246bc16-3e13-499a-aa3b-d56c00c0bb01.png&quot; alt=&quot;image&quot; title=&quot;image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;pro-tip-dont-use-systemjs-to-load-css&quot;&gt;PRO TIP: Don’t use SystemJS to load CSS&lt;/h3&gt;

&lt;p&gt;Use SystemJS for importing JavaScript that is &lt;strong&gt;&lt;em&gt;compatible with jspm
and bundled for jspm**.&lt;/em&gt;.. using SystemJS’s CSS plug-in to load CSS will
get you in a world of mess. Basically, don’t use **import
“bootstrap.css!“&lt;/strong&gt; in your ES6 modules. The reason for this is the
ES6/SystemJS loader standard was recently changed so CSS ordering is not
guaranteed. If you need to load CSS resources in some specified order,
use Aurelia’s &lt;strong&gt;&amp;lt;require from=”…”&amp;gt;&lt;/strong&gt; to load your CSS resources.&lt;/p&gt;

&lt;p&gt;If you installed JavaScript libraries manually using “&lt;strong&gt;jspm
github:user/somerepo&lt;/strong&gt;” (that isn’t part of jspm’s universe nor jspm
aware) there’s a good chance that jspm wont setup dependencies (ie:
jQuery) required by “&lt;strong&gt;user/somerepo&lt;/strong&gt;”.  Your third-party library can
be loaded out of order relative to its dependency (for the exact reason
above) because JSPM doesn’t know the package’s dependencies by default
if they are not specified. See this blog post for more info: &lt;a href=&quot;http://bchavez.bitarmory.com/archive/2015/09/10/jspm-amp-third-party-library-shims.aspx&quot; title=&quot;http://bchavez.bitarmory.com/archive/2015/09/10/jspm-amp-third-party-library-shims.aspx&quot;&gt;How to
deal with dependencies with non-registry JSPM
packages&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3 id=&quot;pro-tip-careful-of-camelcase-names-in-view-models&quot;&gt;PRO TIP: Careful of camelCase names in View Models&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images_old/image_7ad7fddd-f41b-4347-a7dc-afae941626f3.png&quot; alt=&quot;image&quot; title=&quot;image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Has to do with hyphenations and DOM
elements:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://aurelia.io/docs.html#custom-attributes&quot; title=&quot;http://aurelia.io/docs.html#custom-attributes&quot;&gt;http://aurelia.io/docs.html#custom-attributes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;* Since it’s a dom attribute it’s not valid html so Aurelia will
automatically hyphenate and try match an attribute.&lt;/p&gt;

&lt;p&gt;* Simply put when you have a name that camel case you need to separate
it with -&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Have fun :)&lt;/p&gt;

&lt;p&gt;Brian Chavez&lt;/p&gt;</content><author><name>Brian Chavez</name><email>bchavez@bitarmory.com</email></author><category term="ASP.NET" /><category term="Tips and Tricks" /><summary type="html"></summary></entry><entry><title type="html">Date Recurrence Library for .NET/C#</title><link href="https://bchavez.bitarmory.com/date-recurrence-library-for-net-c/" rel="alternate" type="text/html" title="Date Recurrence Library for .NET/C#" /><published>2015-05-25T00:00:00+00:00</published><updated>2015-05-25T00:00:00+00:00</updated><id>https://bchavez.bitarmory.com/date-recurrence-library-for-net-c</id><content type="html" xml:base="https://bchavez.bitarmory.com/date-recurrence-library-for-net-c/">&lt;p&gt; &lt;/p&gt;

&lt;p&gt;It’s quite unfortunate stackoverflow is closing down questions like
this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/4517376/recurrence-library-for-date-calculations-for-net&quot; title=&quot;http://stackoverflow.com/questions/4517376/recurrence-library-for-date-calculations-for-net&quot;&gt;&lt;strong&gt;Recurrence Library for date calculations for .Net
[closed]&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Actually, I wish they changed this policy since the field of “what’s
best” is constantly changing. Normally, I’d contribute to the question
and others would vote on that suggestion. The best answer usually
bubbles up to the top and *that* is useful. New libraries are created
all the time.&lt;/p&gt;

&lt;p&gt;Anyway, for those of you looking for a date recurrence library, I’d like
to recommend:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/EWSoftware/PDI&quot;&gt;EWSoftware PDI Library&lt;/a&gt; and
&lt;a href=&quot;https://www.nuget.org/packages/EWSoftware.PDI/&quot;&gt;NuGet Here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are others, but I’ve used this before and works really well. The
main class you’ll need to work with is the &lt;strong&gt;Recurrence&lt;/strong&gt;  in the
&lt;strong&gt;EWSoftware.PDI&lt;/strong&gt; name space. For
example:&lt;/p&gt;

&lt;div class=&quot;language-cs highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;[Test]&lt;/span&gt; 
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Recurrence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RecurDaily&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;starting&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DateTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Today&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ending&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DateTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Today&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddDays&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dates&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;InstancesBetween&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;starting&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ending&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;occurrence&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dates&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;occurrence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;OUTPUT:

5/25/2015 12:00:00 AM  
5/27/2015 12:00:00 AM  
5/29/2015 12:00:00 AM  
5/31/2015 12:00:00 AM
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Also, if you find it useful, consider making a &lt;a href=&quot;https://github.com/EWSoftware/PDI/wiki#making-a-donation&quot;&gt;donation&lt;/a&gt; to him. I actually bought a license to his PDI library way back when before he open-sourced it. He’s also the author of the &lt;a href=&quot;https://visualstudiogallery.msdn.microsoft.com/a23de100-31a1-405c-b4b7-d6be40c3dfff&quot;&gt;VS2013 spell checker plug-in&lt;/a&gt;.
Legit.&lt;/p&gt;</content><author><name>Brian Chavez</name><email>bchavez@bitarmory.com</email></author><summary type="html"> </summary></entry></feed>