Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Bartosz Ladziński 20 posts 154 karma points
    Nov 30, 2015 @ 10:11
    Bartosz Ladziński
    0

    Auto create and link backoffice account (OAuth integration)

    I'm trying to integrate Umbraco with IdentityServer. I have managed to authenticate using the IdentityServer, but I still need to log in with Umbraco credentials and link the accounts to be able to use them interchangeably.

    I've encountered this post: http://issues.umbraco.org/issue/U4-6753, which pretty much says that using SetExternalSignAutoLinkOptions should do the trick, but it doesn't for me. Even when using it, with new ExternalSignInAutoLinkOptions(autoLinkExternalAccount: true) I still get the

    The requested provider has not been linked to to an account

    error, when trying to log in using the IdentityServer.

    My code is below:

    public static void Configuration(IAppBuilder app = null)
    {
        app.ConfigureUserManagerForUmbracoBackOffice(
            ApplicationContext.Current,
            Umbraco.Core.Security.MembershipProviderExtensions.GetUsersMembershipProvider().AsUmbracoMembershipProvider());
    
        app
            .UseUmbracoBackOfficeCookieAuthentication(ApplicationContext.Current)
            .UseUmbracoBackOfficeExternalCookieAuthentication(ApplicationContext.Current);
    
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie
        });
    
        var idAuth = new OpenIdConnectAuthenticationOptions
        {
            Authority = "https://localhost:12345",
            ClientId = "id",
            ClientSecret = "secret",
            RedirectUri = "http://localhost:1234/Umbraco",
            ResponseType = "id_token token",
            Scope = "openid profile roles email",
            Caption = "test",                   
    
            SignInAsAuthenticationType = Umbraco.Core.Constants.Security.BackOfficeExternalAuthenticationType
        };
    
        idAuth.ForUmbracoBackOffice("btn-google-plus", "fa-google-plus"); //just for now
        idAuth.SetExternalSignInAutoLinkOptions(new ExternalSignInAutoLinkOptions(autoLinkExternalAccount: true));
    
        app.UseOpenIdConnectAuthentication(idAuth);
    
        var configuration = WebApiConfig.Register();
    }
    
  • Bartosz Ladziński 20 posts 154 karma points
    Nov 30, 2015 @ 17:05
    Bartosz Ladziński
    101

    I've managed to get this working. There were two issues, first of all, the AuthenticationType gets "Umbraco." prepended, which then fails in BackOfficeController, because AuthenticationType is now "Umbraco.https://localhost:12345", while LoginProvider is still "https://localhost:12345"

    var authType = OwinContext.Authentication.GetExternalAuthenticationTypes().FirstOrDefault(x => x.AuthenticationType == loginInfo.Login.LoginProvider);
    if (authType == null)
    {
        Logger.Warn<BackOfficeController>("Could not find external authentication provider registered: " + loginInfo.Login.LoginProvider);
        return false;
    }
    

    What prepends the "Umbraco." bit is done in

    idAuth.ForUmbracoBackOffice("btn-google-plus", "fa-google-plus");
    

    , but adding the lower bit, after calling the upper method fixed the issue.

    idAuth.AuthenticationType = "https://localhost:12345";
    

    2nd problem was the null value of loginInfo.ExternalIdentity.Name, which was taken from ClaimsIdentity.Name (which was null itself).

    var autoLinkUser = new BackOfficeIdentityUser()
    {
        Email = loginInfo.Email,
        Name = loginInfo.ExternalIdentity.Name,
        UserTypeAlias = userType.Alias,
        AllowedSections = autoLinkOptions.GetDefaultAllowedSections(UmbracoContext, loginInfo),
        Culture = autoLinkOptions.GetDefaultCulture(UmbracoContext, loginInfo),
        UserName = loginInfo.Email
    };
    

    By claims transforming I now have a proper ClaimsIdentity object, with Name filled in:

    var idAuth = new OpenIdConnectAuthenticationOptions();
    idAuth.Notifications = new OpenIdConnectAuthenticationNotifications
    {
        SecurityTokenValidated = async n =>
            {
                var id = n.AuthenticationTicket.Identity;
    
                // we want to keep first name, last name, subject and roles
                var givenName = id.FindFirst(System.Security.Claims.ClaimTypes.GivenName);
                var familyName = id.FindFirst(System.Security.Claims.ClaimTypes.Surname);
                var roles = id.FindAll(System.Security.Claims.ClaimTypes.Role);
    
                // create new identity and set name and role claim type
                var nid = new ClaimsIdentity(
                    id.AuthenticationType,
                    System.Security.Claims.ClaimTypes.GivenName,
                    System.Security.Claims.ClaimTypes.Role);
    
                nid.AddClaim(givenName);
                nid.AddClaim(familyName);
                nid.AddClaims(roles);
                nid.AddClaim(id.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier));
                nid.AddClaim(id.FindFirst(System.Security.Claims.ClaimTypes.Email));
    
                n.AuthenticationTicket = new AuthenticationTicket(
                    nid,
                    n.AuthenticationTicket.Properties);
            }
    };
    
  • Shannon Deminick 1524 posts 5270 karma points MVP 2x
    Mar 07, 2016 @ 12:31
    Shannon Deminick
    0

    Great that you worked this out. There's a few providers that will require the same type of logic ... we need to get the official Umb docs updated with this info.

  • Milos 2 posts 73 karma points
    Nov 04, 2016 @ 16:22
    Milos
    1

    Hi, could you send me all code?

  • Doug Moore 48 posts 103 karma points c-trib
    Jun 05, 2020 @ 13:20
    Doug Moore
    0

    I am having the issue that users are being created with the Name claim, but that is "LastName, FirstName MI" and I want to use the givenname and surname. I tried to use this Notifications approach, but that has yet to prove successful. Any general advice on how to go about achieving my desired goal?

    I have tried sending just the givenname and surname in notifications, and I have tried sending a new name claimtype in notifications, and that has not been successful. I am connecting to ADFS.

    Notifications = new WsFederationAuthenticationNotifications { // from https://our.umbraco.com/forum/developers/api-questions/73317-auto-create-and-link-backoffice-account#comment-235064
                        SecurityTokenValidated = async n => {
                            var id = n.AuthenticationTicket.Identity;
    
                            // we want to keep first name, last name
                            var givenName = id.FindFirst(ClaimTypes.GivenName);
                            var familyName = id.FindFirst(ClaimTypes.Surname);
                            var name = new Claim(ClaimTypes.Name, $"{givenName} {familyName}");
    
                            // create new identity and set name and role claim type
                            var nid = new ClaimsIdentity(
                                id.AuthenticationType,
                                ClaimTypes.GivenName,
                                ClaimTypes.Role);
    
                            nid.AddClaim(givenName);
                            nid.AddClaim(familyName);
                            nid.AddClaim(name);
                            nid.AddClaim(id.FindFirst(ClaimTypes.NameIdentifier));
                            nid.AddClaim(id.FindFirst(ClaimTypes.Email));
    
                            n.AuthenticationTicket = new AuthenticationTicket(
                                nid,
                                n.AuthenticationTicket.Properties);
                        }
                    }
                };
    
  • Ian 178 posts 752 karma points
    Jan 20, 2016 @ 18:24
    Ian
    0

    Hi Bartosz, I'm also trying to use identity server within umbraco. Do you have an email address I could contact you on to ask just a couple of questions about the handling & maintaining the claims from the external provider.

    cheers

    my email is: [email protected]

Please Sign in or register to post replies

Write your reply to:

Draft