How do I convert an external OAuth Identity into a local identity in Umbraco?

456 views Asked by At

I am attempting to develop a proof-of-concept using my company's website as an OAuth authorization server to be consumed by Umbraco via OWIN/Katana. All of the OAuth plumbing appears to be working just fine but Umbraco isn't converting the external identity into a local identity. Instead of being logged into the Umbraco backend, the user lands back on the login page. The only change once the OAuth flow has completed is that Umbraco has created an UMB_EXTLOGIN cookie containing a long encrypted string.

If I login using a local identity directly (i.e. user name and password on the Umbraco backend login page) Umbraco creates 4 cookies: UMB_UCONTEXT, UMB_UPDCHK, XSRF-TOKEN and XSRF-V. I assume I'm missing something that converts the external identity into a local one, but I'm not sure what that is.

Startup.Auth.cs

public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        app.ConfigureBackOfficeMyCompanyAuth(Properties.Settings.Default.ClientId, Properties.Settings.Default.ClientSecret);
    }
}

UmbracoMyCompanyAuthExtensions.cs

public static class UmbracoMyCompanyAuthExtensions
{
    public static void ConfigureBackOfficeMyCompanyAuth(this IAppBuilder app, string clientId, string clientSecret,
        string caption = "My Company", string style = "btn-mycompany", string icon = "fa-rebel")
    {
        var options = new MyCompanyAuthenticationOptions
        {
            ClientId = clientId,
            ClientSecret = clientSecret,
            SignInAsAuthenticationType = Constants.Security.BackOfficeExternalAuthenticationType,
            Provider = new MyCompanyAuthenticationProvider(),
            CallbackPath = new PathString("/MyCompanySignIn")
        };

        options.ForUmbracoBackOffice(style, icon);
        options.Caption = caption;
        app.UseMyCompanyAuthentication(options);
    }
}

MyCompanyAuthenticationExtension.cs

public static class MyCompanyAuthenticationExtensions
{
    public static IAppBuilder UseMyCompanyAuthentication(this IAppBuilder app, MyCompanyAuthenticationOptions options)
    {
        if (app == null)
        {
            throw new ArgumentNullException("app");
        }
        if (options == null)
        {
            throw new ArgumentNullException("options");
        }
        app.Use(typeof(MyCompanyAuthenticationMiddleware), new object[] { app, options });
        return app;
    }

    public static IAppBuilder UseMyCompanyAuthentication(this IAppBuilder app, string clientId, string clientSecret)
    {
        MyCompanyAuthenticationOptions options = new MyCompanyAuthenticationOptions
        {
            ClientId = clientId,
            ClientSecret = clientSecret
        };
        return app.UseMyCompanyAuthentication(options);
    }
}

My custom implementation of AuthenticationHandler<T>.AuthenticateCoreAsync() returns an AuthenticationTicket with the following claims and properties.

Claims

  1. GivenName = My First Name
  2. FamilyName = My Last Name
  3. Name = My Full Name
  4. Email = My Email Address

Properties

  1. .redirect = /umbraco/
2

There are 2 answers

0
denford mutseriwa On

Dont have any code ready at hand but from past experiences, using Facebook OAuth, you will have to wire in your own logic to basically either or both, convert you OAuth object (user) into an umbraco one.

When we done it previously the first time a user does it (checking by email), it creates a new user then every subsequent login get the umbraco user by their email and log them in in code. This was the same for both backend users and front end members.

0
Ray Saltrelli On

So after much wheel spinning, I finally figured it out. The resulting ClaimsIdentity didn't contain a NameIdentifier claim. I had my OAuth middleware include that claim using the email address as the value and it started working.

FYI, if you're looking to autolink external and local accounts upon external login, here's a really good example that worked for me.