Copied to clipboard

Flag this post as spam?

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


  • Andy Felix 16 posts 97 karma points
    Dec 09, 2021 @ 16:11
    Andy Felix
    0

    Umbraco Azure Active Directory Login for Backend

    Hi, i want to integrate the Azure AD for Umbraco like described in this article: https://shazwazza.com/post/configuring-azure-active-directory-login-with-umbraco/

    I have also activated the auto-linking, but when i now want to login, i get the login screen from our Azure AD, but i will be redirected back to the login screen...

    it is possible, that someone here had the same problems? if it's needed, i can post some code of my integration to.

    thanks for your help and kind regards, andy

  • Andy Finn 51 posts 183 karma points
    Dec 11, 2021 @ 22:42
    Andy Finn
    0

    @andy , maybe post the code so we can have look, i also setup the azure ad for backoffice and little issues . Sounds like the redirect maybe in correct to redirect back to where the user login from , if your case website/umbraco .

    Maybe check what you have set

    <add key="azureAd:redirectUrl" value="http://localhost:7518/umbraco" />
    

    for example

    Andy

  • Andy Felix 16 posts 97 karma points
    Dec 13, 2021 @ 05:21
    Andy Felix
    0

    Hi Andy, thanks for your answer, here are some code:

    appSettings.config:

     <add key="owin:appStartup" value="UmbracoStandardOwinStartup" /> 
    

    UmbracoStandardOwinStartup.cs:

    public class UmbracoStandardOwinStartup : UmbracoDefaultOwinStartup
    {
    
        /// <summary>
        /// Configures the back office authentication for Umbraco
        /// </summary>
        /// <param name="app"></param>
        protected override void ConfigureUmbracoAuthentication(IAppBuilder app)
        {
    
            base.ConfigureUmbracoAuthentication(app);
    
            app.ConfigureBackOfficeAzureActiveDirectoryAuth(
                tenant: ConfigurationManager.AppSettings["azureAd:tenantId"],
                clientId: ConfigurationManager.AppSettings["azureAd:clientId"],
                postLoginRedirectUri: ConfigurationManager.AppSettings["azureAd:redirectUrl"],
                issuerId: new Guid(ConfigurationManager.AppSettings["azureAd:tenantId"]));
    
        }
    }
    

    UmbracoADAuthExtensions.cs

    public static class UmbracoADAuthExtensions
    {
    
        public static void ConfigureBackOfficeAzureActiveDirectoryAuth(this IAppBuilder app, 
            string tenant, string clientId, string postLoginRedirectUri, Guid issuerId,
            string caption = "Active Directory", string style = "btn-microsoft", string icon = "fa-windows")
        {         
    
            var authority = string.Format(
                CultureInfo.InvariantCulture,
                "https://login.microsoftonline.com/{0}",
                tenant);
    
            var adOptions = new OpenIdConnectAuthenticationOptions
            {
                SignInAsAuthenticationType = Constants.Security.BackOfficeExternalCookieName,
                ClientId = clientId,
                Authority = authority,                
                RedirectUri = postLoginRedirectUri,
            };
    
            adOptions.BackchannelHttpHandler = new HttpClientHandler
            {
                UseProxy = true,
                Proxy = new WebProxy
                {
                    Address = new Uri($"{ConfigurationManager.AppSettings["Our.ProxyServer"]}:{ConfigurationManager.AppSettings["Our.ProxyPort"]}"),
                    UseDefaultCredentials = true
                }
            };
    
    
            adOptions.SetBackOfficeExternalLoginProviderOptions(
                new BackOfficeExternalLoginProviderOptions
                {
                    AutoLinkOptions = new ExternalSignInAutoLinkOptions(
                        autoLinkExternalAccount: false,
    
                        defaultUserGroups: new[] { Constants.Security.EditorGroupAlias },
    
                        defaultCulture: null)
                        {
                            AllowManualLinking = true,
    
                            OnAutoLinking = (user, externalLogin) =>
                            {
                            },                      
                        },
    
                    DenyLocalLogin = false,
    
                    AutoRedirectLoginToExternalProvider = false
                });
    
            adOptions.ForUmbracoBackOffice(style, icon);            
            adOptions.Caption = caption;
            adOptions.AuthenticationType = string.Format(
                CultureInfo.InvariantCulture,
                "https://sts.windows.net/{0}/",
                issuerId);
    
    
            app.UseOpenIdConnectAuthentication(adOptions);
    
        }
    
    
    }
    

    I made the Azure Active Directory Settings like in the documentation. Must i define in AAD the allowed User-Groups?

    thanks and kind regards, Andy

  • Andy Finn 51 posts 183 karma points
    Dec 13, 2021 @ 09:11
    Andy Finn
    100

    HI Andy have a look at

    https://our.umbraco.com/forum/extending-umbraco-and-using-the-api/91070-azure-ad-for-user-login-unable-to-link-existing-accounts

    Especially the line from Shannon Mar 21, 2018 @ 01:01 . I am not using the cookie , which he says wont work

    SignInAsAuthenticationType = Constants.Security.BackOfficeExternalAuthenticationType,
    

    Is what i am using . Also you could put a break point on the redirect to see where is it redirecting to here is something i added to so i had more control over what was going on with the redirect

    SignInAsAuthenticationType = Constants.Security.BackOfficeExternalAuthenticationType,
                ClientId = clientId,
                Authority = authority,
                //RedirectUri = postLoginRedirectUri,
                Notifications = new OpenIdConnectAuthenticationNotifications
    

    Comment out the redirectUri and added :

                        RedirectToIdentityProvider = context =>
                    {
                        string uri = context.Request.Uri.AbsoluteUri; //to do to get the return uri
                        if (uri.Contains("ExternalLogin"))
                        {
                            uri = uri.Substring(0, uri.LastIndexOf('/'));
                        }
                        context.ProtocolMessage.RedirectUri = uri;
                        context.ProtocolMessage.PostLogoutRedirectUri = uri;
                        return Task.FromResult(0);
                    }
    

    In the notification Method , then put a break point on string uri = context.Request.Uri.AbsoluteUri; and you will see what Url it is redirecting to . ( i added the externallogin as mine was been appended with that but that maybe not the case for u)

    And Yes , i created a specific AZURE ad group and added the BackOffice users to it at the start with .

    Hope that helps Andy

  • Andy Felix 16 posts 97 karma points
    Dec 14, 2021 @ 08:18
    Andy Felix
    0

    Hi Andy, thanks for your help. I have added a azure ad group with the Backoffice Users, but i get still an error after Login - i think this happen before i come back to umbraco (i'm stand on thiss url after insert the user/pw - https://login.microsoftonline.com/login.srf).

    I think i must check the azure ad configuration again with our cloud team.

    enter image description here

    I will update this issue when i check this.

    thanks and kind regards, andy

  • Andy Finn 51 posts 183 karma points
    Dec 14, 2021 @ 08:48
    Andy Finn
    0

    The first question is easier to find out if you look at the url where the Anmelden is display it will show you the url is question < https://login.microsoftonline.com/xxx/oauth2/authorize?clientid=xxxx&responsemode=formpost&responsetype=code%20idtoken&scope=openid%20profile&state=OpenIdConnect.AuthenticationProperties%xxxxxx&redirecturi=https%3A%2F%2Fwww.xxxx.xx%2Fumbraco&postlogoutredirecturi=https%3A%2F%2Fwww.xxxxx.xx%2Fumbraco&x-client-SKU=IDNET461&x-client-ver=5.3.0.0

    it will be something like this , Pay attention to redirecturi and postlogout uri , this should match your editor page www.dfdsf.se/umbraco , if it doesnt then thats what they either need to update in Cloud team or ur app config . (more like your cloud team . Also notice the error said at the end "Reply address did not match because of trailing slash " ? Also get to add your localhost/umbraco ( while u are testing) , we setup a test azure ad group for development or test / as well as prod one .

    As for the the other error , i have not seen that one before , Maybe put some line breaks in the new owin and see where it is not getting the correct info.

    Andy ps : 2F is / , 3A is :

  • Andy Felix 16 posts 97 karma points
    Dec 14, 2021 @ 13:50
    Andy Felix
    0

    Hi, this are the url after click on login with azure ad - i insert my email and woudl be redirected:

    https://login.microsoftonline.com/35aa8c5b-ac0a-4b15-9788-ff6dfa22901f/oauth2/authorize?clientid=4e97ec48-cc66-4877-bff3-929116209117&redirecturi=https%3a%2f%2flogistiktransport-testadmin.service.migros.cloud%2fumbraco%2f&responsemode=formpost&responsetype=code+idtoken&scope=openid+profile&state=OpenIdConnect.AuthenticationProperties%3dWet5-oYj0YaXzpGIL8PqG5Ng6pAO7hYKDbtJy6ZqXW-ThDiOuDkWA6fSYBxmYX2khdQ8RGbFzpJTx3-3Fblscw8pRDtLxT50G-dr-2ZuTZPm68ApjSdj5mwsYU16vyqWN0ovcjYkkCqbEsUD5HbDf2biyCBqOUPM5znXsianvw6BuNJeJpjmIer4ovlFjxJFzd2WmwmLwERc7BuO-mbXuU4q7ATuQZHadvAvUxlE&nonce=637750864636564500.OGQxM2ZjMmItNTFkYy00NzY5LWE0NGItZDBiM2E4NTQ1ZDRkOTQ0ODg0N2MtOTVjNS00OTU3LTk3NzQtZWVmMjljZDFlZmNj&ssoreload=true

    https://azurests.agora.migros.ch/adfs/ls/wia?client-request-id=b7d0ef14-4a5a-4fff-925d-a036064146db&wa=wsignin1.0&wtrealm=urn%3afederation%3aMicrosoftOnline&wctx=LoginOptions%3D3%26estsredirect%3d2%26estsrequest%3drQIIARWSO2zTQABA46YEqPgUxMDYgQnpkvPv7ERCIomTkDSxm9ZpYkuo8jex47Md-5zfyAQLINiYgJGRBcTEClMlNlgQE4IBxMQG7fKmNz29m3m6SFducE5ZcCxOBJaFEOBEQQCm67KgzJRpGjHwhEJydWv72qjN3rnnLk7nNUqDavKWoY4r6TlGvNlLECgIPRcQhFvGI4yEsKq3-ssfofg-3iaw2p9oKQnmt8d1hA8qtNtGlmtdjGpys9mld2p8qah8q0hjKTI8o6qEvH0CoqAO2q05Zed0n-vAQ9zA16VmoGPZ7xxWalmZMKcIkq8tfNn47wbJfgojlLyLP9kQ4mdsG3XozB0LFI81ZyQeJZBvCjcS6LYSYjnpLeGDuFBpPlQM0bruNXuinuzFi-PUVxVhIm2K5mks0L6bDQE6kTylEyaDqvIPdBqS6yNmOnRxO6L-y2zuY476pIFbNMMUmshxvsS6S5VHraAnQBGz1R9DyOxGvsHtsjRaoNaDRfzYYyjI7mlq9NpWZ2UgHEnHlFzG9Fb12kwZ7PX4dThKPSOcL1AtkztOJZx20m4aB40WWnubaZIV7g7qKxbwm1TAHYHGUD7mgmVNWsr98x7Hl1PlgGjdf5GyxvGKLFm8CwoAE4k-ZBWRBF4LrIdg2GKUPaZidFIn9OydOIlcL3C-5a8Yob0quk7gLWjsVm0Jseb1INCzBfOXduazt3PbeT-7tJvTxzMsq97a-ffj59oDx6qG2-uPkh9FMqXFII9SzHRZwprYbXTGbZOUTL3exXB4YNTqxu6uXmYHIdu-Va7QjwvU40Lhd4G6fzb37nx1QkicVkqlIBp7KfGmJDHCNI4SAoiTEsPGXlhMnWTuWU4Re-MkSotWEGV2KcNmYlhR6fPWNQYyNKAZQHM7NFvhxApE-vuLuf81&cbcxt=&username=andy.felix%40mgb.ch&mkt=&lc=

    do you see a mistake in the url's?

    thanks for your help - kind regards, Andy

  • Andy Finn 51 posts 183 karma points
    Dec 14, 2021 @ 13:57
    Andy Finn
    0
    redirecturi=https%3a%2f%2flogistiktransport-testadmin.service.migros.cloud%2fumbraco%2f
    

    Yes you have / at the end . Remove the trailing / . In the azure service , (is what is there ) https://flogistiktransport-testadmin.service.migros.cloud/umbraco/ needs to be https://flogistiktransport-testadmin.service.migros.cloud/umbraco

    Andy

  • Andy Felix 16 posts 97 karma points
    Dec 14, 2021 @ 14:57
    Andy Felix
    0

    Hi Andy, i changed the the url on azure settings and now i will redirected after enter the login data back to the umbraco login page with the error message:

    Sequence contains more than one element InvalidOperationException: Sequence contains more than one element] System.Linq.Enumerable.SingleOrDefault(IEnumerable`1 source) +504 Microsoft.Owin.Security.

    have you please an idea what is my fault?

    thanks for your help and kind regards, andy

  • Andy Finn 51 posts 183 karma points
    Dec 14, 2021 @ 15:34
    Andy Finn
    0

    I would put a break point in UmbracoADAuthExtensions.cs file and to see if you can find out where it is breaking .

                var adOptions = new OpenIdConnectAuthenticationOptions
            {
                SignInAsAuthenticationType = Constants.Security.BackOfficeExternalAuthenticationType,
                ClientId = clientId,
                Authority = authority,
                //RedirectUri = postLoginRedirectUri,
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthorizationCodeReceived = async context =>
                    {
                        var userService = Umbraco.Core.Composing.Current.Services.UserService;
                        var email = context.JwtSecurityToken.Claims.First(x => x.Type == "upn").Value;
                        var issuer = context.JwtSecurityToken.Claims.First(x => x.Type == "iss").Value;
                        var providerKey = context.JwtSecurityToken.Claims.First(x => x.Type == "sub").Value;
                        var name = context.JwtSecurityToken.Claims.First(x => x.Type == "name").Value;
                        var userManager = context.OwinContext.GetUserManager<BackOfficeUserManager>();
    
                        var user = userService.GetByEmail(email);
    
                        if (user == null)
                        {
                            var writerUserType = userService.GetByEmail(email);
                            string[] country = email.Split('@');
                            user = userService.CreateUserWithIdentity(name, email);
    
                            userService.Save(user);
                        }
    
                        var identity = await userManager.FindByEmailAsync(email);
                        if (identity.Logins.All(x => x.ProviderKey != providerKey))
                        {
                            identity.Logins.Add(new IdentityUserLogin(issuer, providerKey, user.Id));
                            await userManager.UpdateAsync(identity);
                        }
    
                    },
                    RedirectToIdentityProvider = context =>
                    {
                        string uri = context.Request.Uri.AbsoluteUri; //to do to get the return uri
                        if (uri.Contains("ExternalLogin"))
                        {
                            uri = uri.Substring(0, uri.LastIndexOf('/'));
                        }
                        context.ProtocolMessage.RedirectUri = uri;
                        context.ProtocolMessage.PostLogoutRedirectUri = uri;
                        return Task.FromResult(0);
                    }
                }
            };
    

    this is how mine looks . ( now i do some work with new users so that they are created so ignore the user part ) But maybe you need to change from

    SignInAsAuthenticationType = Constants.Security.BackOfficeExternalCookieName,
    

    to

    SignInAsAuthenticationType = Constants.Security.BackOfficeExternalAuthenticationType,
    

    I am not sure about with Proxy's part of your code , did you have a look at https://our.umbraco.com/forum/extending-umbraco-and-using-the-api/91070-azure-ad-for-user-login-unable-to-link-existing-accounts

    But i would start with a break point so see what is failing . Andy

    PS did a quick google of the error and it seems to be related to Cookies https://stackoverflow.com/questions/27101402/sequence-contains-more-than-one-element-microsoft-owin-security-authenticationma so may change that to as above

  • Andy Felix 16 posts 97 karma points
    Dec 15, 2021 @ 06:59
    Andy Felix
    0

    Hi Andy,

    thanks for your help, i think now it works. Locally everything goes right, i test this now test-environment. One Problem was that i had register before a 2FA with Google Authenticator, i removed and with the correct settings it works.

    kind regards, andy

  • Andy Finn 51 posts 183 karma points
    Dec 15, 2021 @ 08:42
    Andy Finn
    0

    Great Andy ;) Enjoy

  • Andy Felix 16 posts 97 karma points
    Dec 14, 2021 @ 08:35
    Andy Felix
    0

    Hi Andy, sorry that i ask you again, now i get following error:

    Server Error in '/' Application. Sequence contains more than one element Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.InvalidOperationException: Sequence contains more than one element

    Source Error:

    An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

    Stack Trace:

    [InvalidOperationException: Sequence contains more than one element] System.Linq.Enumerable.SingleOrDefault(IEnumerable1 source) +504 Microsoft.Owin.Security.<AuthenticateAsync>d__20.MoveNext() +266 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 Umbraco.Web.Security.<GetExternalLoginInfoAsync>d__5.MoveNext() in D:\a\1\s\src\Umbraco.Web\Security\AuthenticationManagerExtensions.cs:118 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 Umbraco.Web.Editors.<RenderDefaultOrProcessExternalLoginAsync>d__24.MoveNext() in D:\a\1\s\src\Umbraco.Web\Editors\BackOfficeController.cs:379 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 Umbraco.Web.Editors.<Default>d__12.MoveNext() in D:\a\1\s\src\Umbraco.Web\Editors\BackOfficeController.cs:75 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult) +92 System.Web.Mvc.Async.<>c__DisplayClass8_0.<BeginInvokeAsynchronousActionMethod>b__1(IAsyncResult asyncResult) +22 System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +42 System.Web.Mvc.Async.<>c__DisplayClass11_0.<InvokeActionMethodFilterAsynchronouslyRecursive>b__0() +80 System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +396 System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +396 System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +396 System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +396 System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +42 System.Web.Mvc.Async.<>c__DisplayClass3_6.<BeginInvokeAction>b__4() +50 System.Web.Mvc.Async.<>c__DisplayClass3_1.<BeginInvokeAction>b__1(IAsyncResult asyncResult) +188 System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +38 System.Web.Mvc.<>c.<BeginExecuteCore>b__152_1(IAsyncResult asyncResult, ExecuteCoreState innerState) +29 System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +73 System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +52 System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +39 System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +38 System.Web.Mvc.<>c.<BeginProcessRequest>b__20_1(IAsyncResult asyncResult, ProcessRequestState innerState) +43 System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +73 System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +38 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +651 System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +220 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +134

    Have you please maybe an idea, what is wrong?

    thanks and kind regards, andy

  • Gurumurthy 52 posts 125 karma points
    Jul 21, 2022 @ 19:37
    Gurumurthy
    0

    Hi All,

    Any suggestions/inputs how to resolve Sequence contains more than one element exception ?

    I have followed the same above code changes.

    enter image description here

    Thanks, Gurumurthy J V

Please Sign in or register to post replies

Write your reply to:

Draft