<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="https://shazwazza.com/rss/xslt"?>
<rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>Shazwazza</title>
    <link>https://shazwazza.com/</link>
    <description>My blog which is pretty much just all about coding</description>
    <generator>Articulate, blogging built on Umbraco</generator>
    <image>
      <url>/media/0libq25y/frog.png?rmode=max&amp;v=1da0e911f4e6890</url>
      <title>Shazwazza</title>
      <link>https://shazwazza.com/</link>
    </image>
    <item>
      <guid isPermaLink="false">1297</guid>
      <link>https://shazwazza.com/post/easily-lock-out-umbraco-back-office-users/</link>
      <category>Umbraco</category>
      <title>Easily lock out Umbraco back office users</title>
      <description>&lt;p&gt;Want an easy way to lock out all back office users?&lt;/p&gt;
&lt;p&gt;Maybe you are performing an upgrade and want to make sure there’s no back office activity?&lt;/p&gt;
&lt;h2&gt;Here’s a handy script to do this&lt;/h2&gt;
&lt;pre class="lang-csharp"&gt;&lt;code&gt;
using System;
using Microsoft.Owin;
using Owin;
using Umbraco.Web;

[assembly: OwinStartup("AuthDisabledOwinStartup", typeof(MyWebsite.AuthDisabledOwinStartup))]

namespace MyWebsite
{
    public class AuthDisabledOwinStartup : UmbracoDefaultOwinStartup
    {
        protected override void ConfigureUmbracoAuthentication(IAppBuilder app)
        {
            //Don't do anything, this will mean all cookie authentication is disabled which means
            //that no requests from the back office user will be authenticated and therefore 
            //all requests will fail and the user will be logged out.
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you can just update your web.config appSetting to&lt;/p&gt;
&lt;pre class="lang-xml"&gt;&lt;code&gt;
&amp;lt;add value="AuthDisabledOwinStartup" key="owin:appStartup"&amp;gt;&amp;lt;/add&amp;gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When you want to allow back office access again, just update your web.config with your original &lt;em&gt;owin:appStartup&lt;/em&gt; value&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:52 Z</pubDate>
      <a10:updated>2023-03-23T15:08:52Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1330</guid>
      <link>https://shazwazza.com/post/owin-cookie-authentication-with-variable-cookie-paths/</link>
      <category>ASP.Net</category>
      <title>OWIN Cookie Authentication with variable cookie paths</title>
      <description>&lt;p&gt;By default OWIN Cookie Authentication let’s you specify a single configurable cookie path that does not change for the lifetime of the application, for example&lt;/p&gt;
&lt;pre class="csharpcode"&gt;app.UseCookieAuthentication(&lt;span class="kwrd"&gt;new&lt;/span&gt; CookieAuthenticationOptions
{                
    CookiePath = &lt;span class="str"&gt;"/Client1"&lt;/span&gt;,
    CookieSecure = CookieSecureOption.SameAsRequest,
    CookieHttpOnly = &lt;span class="kwrd"&gt;true&lt;/span&gt;
});&lt;/pre&gt;
&lt;p&gt;This is going to only allow cookie authentication to occur when the request is for  any path under &lt;em&gt;/Client1. &lt;/em&gt;But what if you wanted this same cookie and cookie authentication provider to work for other variable paths, what if we wanted it to execute for multiple configured paths like: /Client1, /Client2/Secured, /Client3/Private ? Or what if we wanted wanted this Cookie Authentication Provider to execute dynamically based on the request object?&lt;/p&gt;
&lt;h2&gt;ICookieManager to the rescue&lt;/h2&gt;
&lt;p&gt;The &lt;em&gt;CookieAuthenticationOptions&lt;/em&gt; has a property: &lt;em&gt;CookieManager&lt;/em&gt; which you can set to any instance of &lt;em&gt;ICookieManager&lt;/em&gt;. &lt;em&gt;ICookieManager&lt;/em&gt; contains these methods: &lt;em&gt;GetRequestCookie&lt;/em&gt;, &lt;em&gt;AppendResponseCookie&lt;/em&gt;, &lt;em&gt;DeleteCookie&lt;/em&gt; but all we really need to worry about &lt;em&gt;GetRequestCookie&lt;/em&gt;. It turns out that the &lt;em&gt;CookieAuthenticationHandler&lt;/em&gt; will detect if this method returns null and if so it will just not continue trying to authenticate the request. To make things easy we’ll just inherit from the default OWIN &lt;em&gt;ICookieManager&lt;/em&gt; which is &lt;em&gt;ChunkingCookieManager&lt;/em&gt;, although it’s methods are not marked as virtual we can still override them by explicitly implementing the &lt;em&gt;ICookieManager.GetRequestCookie&lt;/em&gt; method (Pro Tip! You can always override a non virtual method if you explicitly implement an interfaces method).&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;//explicit implementation&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; ICookieManager.GetRequestCookie(IOwinContext context, &lt;span class="kwrd"&gt;string&lt;/span&gt; key)
{
    &lt;span class="rem"&gt;//TODO: Given what is in the context, we can check pretty much anything, if we don't want&lt;/span&gt;
    &lt;span class="rem"&gt;//this request to continue to be authenticated, just return null. Example:&lt;/span&gt;
    var toMatch = &lt;span class="kwrd"&gt;new&lt;/span&gt;[] {&lt;span class="str"&gt;"/Client1"&lt;/span&gt;, &lt;span class="str"&gt;"/Client2/Secured"&lt;/span&gt;, &lt;span class="str"&gt;"/Client3/Private"&lt;/span&gt;};
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (!toMatch.Any(m =&amp;gt; context.Request.Uri.AbsolutePath.StartsWith(m, StringComparison.OrdinalIgnoreCase)))
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;null&lt;/span&gt;;
    }

    &lt;span class="rem"&gt;//if we don't want to ignore it then continue as normal:&lt;/span&gt;
    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;base&lt;/span&gt;.GetRequestCookie(context, key);            
}&lt;/pre&gt;
&lt;p&gt;The last step is to not worry about the &lt;em&gt;CookiePath&lt;/em&gt; since the custom &lt;em&gt;ICookieManager.GetRequestCookie&lt;/em&gt; is going to deal with whether the middleware receives a cookie value or not so in that case, the &lt;em&gt;CookiePath&lt;/em&gt; for the &lt;em&gt;CookieAuthenticationOptions&lt;/em&gt; will remain the default of &lt;em&gt;“/”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We’ve been doing this in Umbraco CMS core for quite some time, I meant to blog about this then but just didn’t find the time. In Umbraco we have a few custom request paths that we need authenticated with our custom back office cookie, for reference the &lt;em&gt;BackOfficeCookieManager&lt;/em&gt; source is found here: &lt;a href="https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Web/Security/Identity/BackOfficeCookieManager.cs" title="https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Web/Security/Identity/BackOfficeCookieManager.cs"&gt;https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Web/Security/Identity/BackOfficeCookieManager.cs&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:23 Z</pubDate>
      <a10:updated>2023-03-23T15:08:23Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1278</guid>
      <link>https://shazwazza.com/post/configuring-aspnet-identity-oauth-login-providers-for-multi-tenancy/</link>
      <category>ASP.Net</category>
      <title>Configuring ASP.Net Identity OAuth login providers for multi-tenancy</title>
      <description>&lt;p&gt;Say for example you have a CMS :) You want to give full control to the developer to manage how their front-end members with authenticate, which could of course include ASP.Net Identity OAuth login providers. At the same time you want to easily allow your CMS to be configured so that ASP.Net Identity OAuth providers can be used for logging into the back office.&amp;nbsp; In this scenario, the same OAuth provider might be used for both front-end and back-office authentication but authenticated under 2 different OAuth accounts. Another example might be if you have multi-tenancy set up for your front-end site and perhaps you want to use the same OAuth login provider but have members authenticate with different OAuth accounts for different domain names. &lt;/p&gt; &lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;  &lt;h2&gt;The defaults&lt;/h2&gt; &lt;p&gt;As an example, lets assume that front-end members are configured to authenticate with the ASP.Net Identity Google OAuth2 provider. This is easily done by just following one of the many tutorials out there. Your startup code might look like:&lt;/p&gt;&lt;pre class="csharpcode"&gt;app.UseCookieAuthentication(&lt;span class="kwrd"&gt;new&lt;/span&gt; CookieAuthenticationOptions ....

app.UseExternalSignInCookie();

app.UseGoogleAuthentication(
              clientId: &lt;span class="str"&gt;"123456789..."&lt;/span&gt;,
              clientSecret: &lt;span class="str"&gt;"987654321...."&lt;/span&gt;);&lt;/pre&gt;
&lt;p&gt;Great, but I need 2 (or more) Google OAuth2 providers, so what now? I can’t just add 2 declarations of:&lt;/p&gt;&lt;pre class="csharpcode"&gt;app.UseGoogleAuthentication(
              clientId: &lt;span class="str"&gt;"123456789..."&lt;/span&gt;,
              clientSecret: &lt;span class="str"&gt;"987654321...."&lt;/span&gt;);

app.UseGoogleAuthentication(
              clientId: &lt;span class="str"&gt;"abcdef..."&lt;/span&gt;,
              clientSecret: &lt;span class="str"&gt;"zyxwv...."&lt;/span&gt;);&lt;/pre&gt;
&lt;p&gt;you’ll quickly realize that doesn’t work and only one provider instance will actually be used. This is because of the default underlying settings that get used to instantiate the Google provider. Let’s have a look at what the default options are in this case. The above code is equivalent to this:&lt;/p&gt;&lt;pre class="csharpcode"&gt;app.UseGoogleAuthentication(&lt;span class="kwrd"&gt;new&lt;/span&gt; GoogleOAuth2AuthenticationOptions
{
    AuthenticationType = &lt;span class="str"&gt;"Google"&lt;/span&gt;,
    ClientId = &lt;span class="str"&gt;"123456789..."&lt;/span&gt;,
    ClientSecret = &lt;span class="str"&gt;"987654321...."&lt;/span&gt;,
    Caption = &lt;span class="str"&gt;"Google"&lt;/span&gt;,
    CallbackPath = &lt;span class="kwrd"&gt;new&lt;/span&gt; PathString(&lt;span class="str"&gt;"/signin-google"&lt;/span&gt;),
    AuthenticationMode = AuthenticationMode.Passive,
    SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType(),
    BackchannelTimeout = TimeSpan.FromSeconds(60),
    BackchannelHttpHandler = &lt;span class="kwrd"&gt;new&lt;/span&gt; System.Net.Http.WebRequestHandler(),
    BackchannelCertificateValidator = &lt;span class="kwrd"&gt;null&lt;/span&gt;,
    Provider = &lt;span class="kwrd"&gt;new&lt;/span&gt; GoogleOAuth2AuthenticationProvider()
});&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;h2&gt;The AuthenticationType&lt;/h2&gt;
&lt;p&gt;One very important aspect of the default settings is the &lt;em&gt;AuthenticationType&lt;/em&gt;. This is a &lt;strong&gt;unique &lt;/strong&gt;identifier for the provider instance and this is one of the reasons why if you have 2 x &lt;em&gt;UseGoogleAuthentication&lt;/em&gt; declarations with the defaults only one will ever be used.&lt;/p&gt;
&lt;p&gt;Knowing this, it’s clear that each declaration of &lt;em&gt;UseGoogleAuthentication&lt;/em&gt; needs to specify custom options and have the &lt;em&gt;AuthenticationType&lt;/em&gt; unique amongst them. So we might end up with something like:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;//keep defaults for front-end&lt;/span&gt;
app.UseGoogleAuthentication(
    clientId: &lt;span class="str"&gt;"123456789..."&lt;/span&gt;,
    clientSecret: &lt;span class="str"&gt;"987654321...."&lt;/span&gt;);

&lt;span class="rem"&gt;//custom options for back-office&lt;/span&gt;
app.UseGoogleAuthentication(&lt;span class="kwrd"&gt;new&lt;/span&gt; GoogleOAuth2AuthenticationOptions
{
    AuthenticationType = &lt;span class="str"&gt;"GoogleBackOffice"&lt;/span&gt;,
    ClientId = &lt;span class="str"&gt;"abcdef..."&lt;/span&gt;,
    ClientSecret = &lt;span class="str"&gt;"zyxwv...."&lt;/span&gt;    
});&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;If you test this now, you’ll find out that only the first declaration is actually working even when you explicitly tell &lt;em&gt;IOwinContext.Authentication.Challenge&lt;/em&gt; to use the “GoogleBackOffice” provider.&lt;/p&gt;
&lt;h2&gt;The CallbackPath&lt;/h2&gt;
&lt;p&gt;The reason that the default (first) declaration is the one that activates is because the response from Google is sending the request to the path: “/signin-google”, which is the default. The &lt;em&gt;GoogleAuthenticationMiddleware &lt;/em&gt;will delegate to the &lt;em&gt;GoogleAuthenticationHandler &lt;/em&gt;for each request and inspect the request to see if it should execute. For this logic it checks: &lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (Options.CallbackPath.HasValue &amp;amp;&amp;amp; Options.CallbackPath == Request.Path)
{
     &lt;span class="rem"&gt;//If the path matches, auth the request...&lt;/span&gt;
}&lt;/pre&gt;
&lt;p&gt;Since the &lt;em&gt;CallbackPath&lt;/em&gt; will be the same by default on both above declarations, the first one that is registered will match and the other registered authenticators will be ignored. To fix this we’ll need to update the path that Google sends back and then update the second declaration to match that path. &lt;/p&gt;
&lt;p&gt;To tell Google to send the request back on a different path, in your Google Developers Console change the REDIRECT URIS value for the second provider:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://shazwazza.com/media/articulate/windows-live-writer-connet-identity-oauth-login-providers-f_a1ef-image_thumb_2.png"&gt;&lt;img title="image_thumb" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image_thumb" src="http://shazwazza.com/media/articulate/windows-live-writer-connet-identity-oauth-login-providers-f_a1ef-image_thumb_thumb.png" width="244" height="216"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Then we need to update the 2nd declaration with the custom &lt;em&gt;CallbackPath&lt;/em&gt; so that it matches and activates properly:&lt;/p&gt;&lt;pre class="csharpcode"&gt;app.UseGoogleAuthentication(&lt;span class="kwrd"&gt;new&lt;/span&gt; GoogleOAuth2AuthenticationOptions
{
    AuthenticationType = &lt;span class="str"&gt;"GoogleBackOffice"&lt;/span&gt;,
    ClientId = &lt;span class="str"&gt;"abcdef..."&lt;/span&gt;,
    ClientSecret = &lt;span class="str"&gt;"zyxwv...."&lt;/span&gt;,
    CallbackPath = &lt;span class="kwrd"&gt;new&lt;/span&gt; PathString(&lt;span class="str"&gt;"/custom-signin-google"&lt;/span&gt;)
});&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;Hooray, now it should work!&lt;/p&gt;
&lt;p&gt;This concept is the same for most external login providers. For example for the Facebook one the default value is “/signin-facebook”, you’d need to configure Facebook’s “Valid OAuth redirect URIs” property with the correct callback path in Facebook’s developer portal:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://shazwazza.com/media/articulate/windows-live-writer-connet-identity-oauth-login-providers-f_a1ef-image_thumb1_2.png"&gt;&lt;img title="image_thumb1" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image_thumb1" src="http://shazwazza.com/media/articulate/windows-live-writer-connet-identity-oauth-login-providers-f_a1ef-image_thumb1_thumb.png" width="184" height="244"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;What is SignInAsAuthenticationType?&lt;/h2&gt;
&lt;p&gt;The last thing to point out is that by default the &lt;em&gt;SignInAsAuthenticationType &lt;/em&gt;for each provider will resolve to: &lt;em&gt;app.GetDefaultSignInAsAuthenticationType()&lt;/em&gt;, which by default is: &lt;em&gt;DefaultAuthenticationTypes.ExternalCookie&lt;/em&gt;&amp;nbsp; = “ExternalCookie”. Each OAuth provider is linked to another middleware that is responsible for actually issuing a user’s ClaimsIdentity, so by default this will be “ExternalCookie”. In some cases you won’t want the default external cookie authentication middleware to assign the ClaimsIdentity for your OAuth provider, you might need to issue a different ClaimsIdentity or just have more granular control over what happens with the callback for each OAuth provider. In this case you’ll need to specify another custom cookie authentication declaration, for example:&lt;/p&gt;&lt;pre class="csharpcode"&gt;app.UseCookieAuthentication(&lt;span class="kwrd"&gt;new&lt;/span&gt; CookieAuthenticationOptions
{
    AuthenticationType = &lt;span class="str"&gt;"CustomExternal"&lt;/span&gt;,
    AuthenticationMode = AuthenticationMode.Passive,
    CookieName = &lt;span class="str"&gt;"MyAwesomeCookie"&lt;/span&gt;,
    ExpireTimeSpan = TimeSpan.FromMinutes(5),
    &lt;span class="rem"&gt;//Additional custom cookie options....&lt;/span&gt;
});&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;And then you can link that up to your OAuth declaration like:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;//custom options for back-office&lt;/span&gt;
app.UseGoogleAuthentication(&lt;span class="kwrd"&gt;new&lt;/span&gt; GoogleOAuth2AuthenticationOptions
{
    AuthenticationType = &lt;span class="str"&gt;"GoogleBackOffice"&lt;/span&gt;,
    ClientId = &lt;span class="str"&gt;"abcdef..."&lt;/span&gt;,
    ClientSecret = &lt;span class="str"&gt;"zyxwv...."&lt;/span&gt;,
    SignInAsAuthenticationType = &lt;span class="str"&gt;"CustomExternal"&lt;/span&gt;
});&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:15 Z</pubDate>
      <a10:updated>2023-03-23T15:08:15Z</a10:updated>
    </item>
  </channel>
</rss>