Latest from the umbraco blog

We're more transparent than glass. Follow us on twitter and our blog.

 

Thursday, March 26, 2015 by Shannon Deminick

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.  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.

The defaults

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:

app.UseCookieAuthentication(new CookieAuthenticationOptions ....

app.UseExternalSignInCookie();

app.UseGoogleAuthentication(
              clientId: "123456789...",
              clientSecret: "987654321....");

Great, but I need 2 (or more) Google OAuth2 providers, so what now? I can’t just add 2 declarations of:

app.UseGoogleAuthentication(
              clientId: "123456789...",
              clientSecret: "987654321....");

app.UseGoogleAuthentication(
              clientId: "abcdef...",
              clientSecret: "zyxwv....");

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:

app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions
{
    AuthenticationType = "Google",
    ClientId = "123456789...",
    ClientSecret = "987654321....",
    Caption = "Google",
    CallbackPath = new PathString("/signin-google"),
    AuthenticationMode = AuthenticationMode.Passive,
    SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType(),
    BackchannelTimeout = TimeSpan.FromSeconds(60),
    BackchannelHttpHandler = new System.Net.Http.WebRequestHandler(),
    BackchannelCertificateValidator = null,
    Provider = new GoogleOAuth2AuthenticationProvider()
});

The AuthenticationType

One very important aspect of the default settings is the AuthenticationType. This is a unique identifier for the provider instance and this is one of the reasons why if you have 2 x UseGoogleAuthentication declarations with the defaults only one will ever be used.

Knowing this, it’s clear that each declaration of UseGoogleAuthentication needs to specify custom options and have the AuthenticationType unique amongst them. So we might end up with something like:

//keep defaults for front-end
app.UseGoogleAuthentication(
    clientId: "123456789...",
    clientSecret: "987654321....");

//custom options for back-office
app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions
{
    AuthenticationType = "GoogleBackOffice",
    ClientId = "abcdef...",
    ClientSecret = "zyxwv...."    
});

If you test this now, you’ll find out that only the first declaration is actually working even when you explicitly tell IOwinContext.Authentication.Challenge to use the “GoogleBackOffice” provider.

The CallbackPath

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 GoogleAuthenticationMiddleware will delegate to the GoogleAuthenticationHandler for each request and inspect the request to see if it should execute. For this logic it checks:

Since the CallbackPath 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.

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:

[Click through to see image]

Then we need to update the 2nd declaration with the custom CallbackPath so that it matches and activates properly:

app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions
{
    AuthenticationType = "GoogleBackOffice",
    ClientId = "abcdef...",
    ClientSecret = "zyxwv....",
    CallbackPath = new PathString("/custom-signin-google")
});

Hooray, now it should work!

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:

[Click through to see image]

if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
     //If the path matches, auth the request...
}

What is SignInAsAuthenticationType?

The last thing to point out is that by default the SignInAsAuthenticationType for each provider will resolve to: app.GetDefaultSignInAsAuthenticationType(), which by default is: DefaultAuthenticationTypes.ExternalCookie  = “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:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = "CustomExternal",
    AuthenticationMode = AuthenticationMode.Passive,
    CookieName = "MyAwesomeCookie",
    ExpireTimeSpan = TimeSpan.FromMinutes(5),
    //Additional custom cookie options....
});

And then you can link that up to your OAuth declaration like:

//custom options for back-office
app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions
{
    AuthenticationType = "GoogleBackOffice",
    ClientId = "abcdef...",
    ClientSecret = "zyxwv....",
    SignInAsAuthenticationType = "CustomExternal"
});

 

This post was cross posted from: http://shazwazza.com/post/configuring-aspnet-identity-oauth-login-providers-for-multi-tenancy/
Follow the link for comments.

Wednesday, March 25, 2015 by Tim Geyssens

Windows-Live-Writer_Codegarden-2014_86DE_Avatar_2_2In the build up to Codegarden 15 we'll be announcing the full schedule in the coming weeks! We must says it’s been hard to make a choice from the many submitted proposals (btw you still have a couple of days to submit your proposal). We are pleased to announce another session, Securing Your Umbraco by Chris Gaskell.

Codegarden takes place in Copenhagen, June 10th-12th, get your tickets today!

The Session

So you’ve built your lovely new Umbraco powered site and you’re ready to push it up onto your production servers and switch that DNS. Victory at last.

But wait!

Are you sure that your website is secured against those web nasties? In this session we’ll look at the steps you can take to secure your Umbraco installation. From simple steps you can take in adding items into your web.config through to running penetration tests. Have you thought about those HTTP headers exposing your platform, sql injection, session hijacking, encrypting cookie content or cross site scripting?

In this session we’ll take a simple site using Umbraco, demonstrate it’s vulnerabilities then go through and sort them.

The Speaker

Chris Gaskell is a North West UK based .NET developer working under Detangled Digital. He has been coding for over 12 years, has been a freelance developer for over 7 years and has been using Umbraco since version 3. Over the last couple of years Chris has led large scale Umbraco installs and has a keen eye for optimisation & performance.

In 2011 Chris founded the Manchester Umbraco Meet Up which is going strong with over 200 members and recently had a visit from the chief unicorn himself!

Tuesday, March 24, 2015 by Tim Geyssens

1378780_10100246013045062_3324094218285233991_nCodegarden, our 11th annual conference will be running from the 10th - 12th of June in Copenhagen. We are currently laying out the blueprints for this years edition. In preparation we’ve asked some of our early bird ticket holders why they are counting the days. Here is why Brittany Dufort can’t wait to attend her first CG!

Get your early bird tickets today and save €150!

Who are you and why is Umbraco and CodeGarden relevant to you?

I’m Brittany Dufort, and I’m a .NET web developer for Genuine. We are a full-service digital agency in the great city of Boston, MA, USA (except when we’re under 108 inches of snow).

I joined Genuine’s growing .NET team in October 2014 without any knowledge of Umbraco. Thankfully, my desk mate, Shivani, taught me the ropes and before I knew it, I was creating Umbraco sites! We work on a portfolio of websites for global brands including RB’s (formerly Reckitt Benckiser) Lysol and Mucinex.

CodeGarden is a must-attend for me because I want to become the best Umbraco developer that I’m capable of being, which means total immersion in the Umbraco community and learning from other skilled developers.

Why did you already purchase your cg 15 ticket?

I knew I was going to CodeGarden during my first master class. As the week went on, the love of the community grew and it was a sure thing. I had to learn more, meet more people, see old friends, and get the ideas flowing. I decided to put in a proposal to talk on an issue I’m dealing with on a current project. Might as well go big at my first CodeGarden, right?

What's your best memory from previous CodeGardens?

Since this will be my first CodeGarden, I’ll share some memories from uWestFest 2015. I’m still new to the Umbraco community, so I took the master certifications in Orlando, FL. The classes led up to uWestFest giving me a weeklong knowledge-gathering and pre-conference festivities.

I think everyone knows this already, but the Umbraco community is amazing. At uWestFest, I made so many new friends that I remain in contact with quite frequently. I was adopted into the family with my first “High Five You Rock!” after my first class and now understand what #h5yr means. uWestFest was an abundance of knowledge sharing...and having a good time with my new family. There were definitely times where I just couldn’t wait to get back to work and fix everything I had been doing differently.

Anything else that you wish to add/share?

I take great pride in pursuing a career as not only a developer but also a female developer in the technology industry. I hope my presence at CodeGarden will give me the opportunity to represent the few female developers and encourage other women to be more involved through attending training and conferences like CodeGarden.

And, for those new and old to the community, you may have heard and/or experienced the
“Niels Negroni” initiation… which if you’re like me is not a drink I enjoy. But, fear not, I’ve been named the CodeGarden Cocktail Chair. So, get your party pants on – I’ll be creating some bomb drinks!

1