Log into Umbraco with Google authentication
In this real-life example, we have two things:
- a Google Apps account for a domain
- an Umbraco website for which we want all Google Apps users in our organization to be able to log into the backoffice
As the first step, we need to ask Google for a ClientId and a secret by creating an OAuth client and give us some secret keys for that. Below is a short video that shows how to set this up.
Once you have the ClientId and secret from the Google OAuth integration you go to you Umbraco Visual Studio solution and install 2 NuGet Packages:
Install-Package UmbracoCms.IdentityExtensions Install-Package UmbracoCms.IdentityExtensions.Google
A few readme files will pop up to tell you what to do with the new files that are now present in your App_Start folder. The most important one is UmbracoStandardOwinStartup.cs which will need to know about the Google ClientId and secret. In this example, they will be read from the web.config, where they're stored as appSettings.
var clientId = WebConfigurationManager.AppSettings["GoogleOAuthClientID"]; var secret = WebConfigurationManager.AppSettings["GoogleOAuthSecret"]; app.ConfigureBackOfficeGoogleAuth(clientId, secret);
In order for the Umbraco Backoffice to know that we can now also log in with a Google account, we need to change the owin:appStartup appSetting to:
<add key="owin:appStartup" value="UmbracoStandardOwinStartup" />
After doing this, we can log in to Umbraco with our existing Umbraco account and link that account to a Google login.
Once you click on "Link your Google account" you will be taken to Google and can link any account you want. From that point forward you can use the Google button on the login screen to log into the backoffice!
Nice.. but a little cumbersome too, we still need to create a local account first and then link it to a Google account. What if we wanted to allow all people on our Google Domains account in by default?
When you installed the NuGet packages you also received a UmbracoGoogleAuthExtensions.cs file in your App_Start folder which we can alter a little bit. Just before the last line of code (app.UseGoogleAuthentication(googleOptions);) in this class we can set it up to automatically create an Umbraco account for anybody using the Google button to sign in.
googleOptions.SetExternalSignInAutoLinkOptions( new ExternalSignInAutoLinkOptions( autoLinkExternalAccount: true, defaultUserType: "admin", defaultAllowedSections: new[] { "content", "media", "settings", "developer", "users", "member" }));
By default, if we don't change the defaultUserType and defaultAllowedSections, a new user would be created as an editor and would only have access to the content/media section. But in the example above, more access is granted because we trust users in our domain.
Speaking of domains.. doing the above will give anybody in the world(!) with a Google account access to our backoffice. That's probably not what you want unless you like a bit of chaos in your life.
So as our final step, we need to only allow people in who's email ends with our actual domain name. In UmbracoGoogleAuthExtensions.cs we define a variable googleOptions in which we can add the following, just after the "CallbackPath":
CallbackPath = new PathString("/umbraco-google-signin"), Provider = new GoogleOAuth2AuthenticationProvider { OnAuthenticated = context => { if (context.Email.EndsWith("umbraco.dk") || context.Email.EndsWith("umbraco.com")) // All good, return as usual return Task.FromResult(0); // Whoa, this one doesn't belong in our backoffice, throw exception, this will return a nulled out Auth Ticket var errorMessage = string.Format("User tried to log in with {0}, which does not end with an accepted domain name.", context.Email); throw new AuthenticationException(errorMessage); } }
Looks good, right? Not so fast! What if someone made a email address like.. admin@myumbraco.com? The e-mail address still ends with umbraco.com so they will be let in as well. So we change it to:
var emailParts = context.Email.Split('@'); if (emailParts.Last() == "umbraco.dk" || emailParts.Last() == "umbraco.com")
Much better!
That's all there is to it:
- Enable OAuth in your Google account
- Install the UmbracoCms.IdentityExtensions & UmbracoCms.IdentityExtensions.Google NuGet packages
- Update UmbracoStandardOwinStartup.cs with the ClientId and secret you got from Google
- Set the owin:appStartup appSetting in web.config to UmbracoStandardOwinStartup
- Update UmbracoGoogleAuthExtensions.cs to auto-link accounts and limit that to logins from your domain only
This is exactly what we've done for Our Umbraco, if you want to check out the code, have a look at the following two commits:
- https://github.com/umbraco/OurUmbraco/commit/948eea9c51d1342604b228554cf185b302a8d138
- https://github.com/umbraco/OurUmbraco/commit/04a25a84f70f53d802e6e2b99c6d9d7c63535837
- https://github.com/umbraco/OurUmbraco/commit/640d6ab4adb6d4a0f79c3eb488b08eaea743fae6
Note: The "Link your Google account" button has a bug in Umbraco 7.4 and 7.5 beta which can be fixed as follows:
- In Umbraco 7.4.x, update the "externalLoginForm" in the file ~\Umbraco\Views\common\dialogs\user.html
- In Umbraco 7.5 beta/beta2 update the "externalLoginForm" in the file ~\Umbraco\Views\common\overlays\user\user.html