umbracoexternallogincontrollerexternallogin not working as expected when hosting on azure app service Using Umbraco And Getting Started (2024)

Greetings,

I have implemented an external login provider (not for the backoffice, but it connects to it using autolinking, implemented using this example) and it works perfectly when running the Umbraco site locally.

I click on the button, it redirects to the okta login page, then redirects back to the homepage of my site after login. I can see that I am logged in because I display a welcome message with the name of the user.

My problem arises when I host this website on Azure App Service.

I click on the button, I get redirected to the okta login page, then i get redirected back to: mydomain/?ufprt=CfDJ8LXoX0ANCN5BnQZS4V14uiXzehm3idER69mD-aAkGsOiqZRnB1QorygvC25AfZodnBxEdtOTXwNgfUTDPkO_RJFr9yvI8XJQiFphdItEM6nm3SUK_urKsSiCbnFS4hKrxyaLCTNm1UCqom-v06Jx5r9z0JjLA1ghiYZg6NUQftKeGj6bkE_R03oS_1UrdSWL4A and I am not logged in.

I already did some searching and it turns out that this is what Umbraco uses to find the right controller action (correct me if i'm wrong) when using an UmbracoForm. It adds this to the homepage url of my website and it doesn't log me in.

Here is the code for the button/form:

foreach(var login in await _memberExternalLoginProviders.GetMemberProvidersAsync()){using (Html.BeginUmbracoForm<UmbExternalLoginController>(nameof(UmbExternalLoginController.ExternalLogin), new {ReturnUrl = "/"}, new { @class = "align-self-end ml-4" })){ <button type="submit" class="btn btn-outline-warning" name="provider" value="@login.ExternalLoginProvider.AuthenticationType"> Sign in </button>}}

This is my .AddOpenIdConnect extension:

 public static IUmbracoBuilder AddOpenIdConnectAuthentication(this IUmbracoBuilder builder){ builder.Services.ConfigureOptions<OpenIdConnectMemberExternalLoginProviderOptions>(); builder.AddMemberExternalLogins(logins => { logins.AddMemberLogin( memberAuthenticationBuilder => { memberAuthenticationBuilder.AddOpenIdConnect( // The scheme must be set with this method to work for the umbraco members memberAuthenticationBuilder.SchemeForMembers(OpenIdConnectMemberExternalLoginProviderOptions.SchemeName), options => { var config = builder.Config; options.ResponseType = "code"; options.Scope.Add("openid"); options.Scope.Add("profile"); options.RequireHttpsMetadata = true; options.MetadataAddress = config["OpenIdConnect:MetadataAddress"]; options.ClientId = config["OpenIdConnect:ClientId"]; options.CallbackPath = "/authorization-code/callback"; options.ClientSecret = config["OpenIdConnect:ClientSecret"]; options.SaveTokens = true; options.TokenValidationParameters.SaveSigninToken = true; options.GetClaimsFromUserInfoEndpoint = true; options.SignedOutCallbackPath = "/signout/callback"; options.Events.OnTokenValidated = async context => { var claims = context?.Principal?.Claims.ToList(); var email = claims?.SingleOrDefault(x => x.Type == ClaimTypes.NameIdentifier); if (email != null) { // The email claim is required for auto linking. // So get it from another claim and put it in the email claim. claims?.Add(new Claim(ClaimTypes.Email, email.Value)); } var name = claims?.SingleOrDefault(x => x.Type == "name"); if (name != null) { // The name claim is required for auto linking. // So get it from another claim and put it in the name claim. claims?.Add(new Claim(ClaimTypes.Name, name.Value)); } if (context != null) { // Since we added new claims create a new principal. var authenticationType = context.Principal?.Identity?.AuthenticationType; context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, authenticationType)); } await Task.FromResult(0); }; options.Events.OnRedirectToIdentityProviderForSignOut = async notification => { var protocolMessage = notification.ProtocolMessage; // Since we're in a static extension method we need this approach to get the member manager. var memberManager = notification.HttpContext.RequestServices.GetService<IMemberManager>(); if (memberManager != null) { var currentMember = await memberManager.GetCurrentMemberAsync(); // On the current member we can find all their login tokens from the external login provider. // These tokens are stored in the umbracoExternalLoginToken table. var idToken = currentMember?.LoginTokens.FirstOrDefault(x => x.Name == "id_token"); if (idToken != null && !string.IsNullOrEmpty(idToken.Value)) { // Some external login providers need the IdTokenHint. // By setting the IdTokenHint the user can be redirected back from the external login provider to this website. protocolMessage.IdTokenHint = idToken.Value; } } await Task.FromResult(0); }; }); }); }); return builder;}}

This is my OpenIdConnectMemberExternalLoginProviderOptions class:

 public static IUmbracoBuilder AddOpenIdConnectAuthentication(this IUmbracoBuilder builder){ builder.Services.ConfigureOptions<OpenIdConnectMemberExternalLoginProviderOptions>(); builder.AddMemberExternalLogins(logins => { logins.AddMemberLogin( memberAuthenticationBuilder => { memberAuthenticationBuilder.AddOpenIdConnect( // The scheme must be set with this method to work for the umbraco members memberAuthenticationBuilder.SchemeForMembers(OpenIdConnectMemberExternalLoginProviderOptions.SchemeName), options => { var config = builder.Config; options.ResponseType = "code"; options.Scope.Add("openid"); options.Scope.Add("profile"); options.RequireHttpsMetadata = true; options.MetadataAddress = config["OpenIdConnect:MetadataAddress"]; options.ClientId = config["OpenIdConnect:ClientId"]; options.CallbackPath = "/authorization-code/callback"; options.ClientSecret = config["OpenIdConnect:ClientSecret"]; options.SaveTokens = true; options.TokenValidationParameters.SaveSigninToken = true; options.GetClaimsFromUserInfoEndpoint = true; options.SignedOutCallbackPath = "/signout/callback"; options.Events.OnTokenValidated = async context => { var claims = context?.Principal?.Claims.ToList(); var email = claims?.SingleOrDefault(x => x.Type == ClaimTypes.NameIdentifier); if (email != null) { // The email claim is required for auto linking. // So get it from another claim and put it in the email claim. claims?.Add(new Claim(ClaimTypes.Email, email.Value)); } var name = claims?.SingleOrDefault(x => x.Type == "name"); if (name != null) { // The name claim is required for auto linking. // So get it from another claim and put it in the name claim. claims?.Add(new Claim(ClaimTypes.Name, name.Value)); } if (context != null) { // Since we added new claims create a new principal. var authenticationType = context.Principal?.Identity?.AuthenticationType; context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, authenticationType)); } await Task.FromResult(0); }; options.Events.OnRedirectToIdentityProviderForSignOut = async notification => { var protocolMessage = notification.ProtocolMessage; // Since we're in a static extension method we need this approach to get the member manager. var memberManager = notification.HttpContext.RequestServices.GetService<IMemberManager>(); if (memberManager != null) { var currentMember = await memberManager.GetCurrentMemberAsync(); // On the current member we can find all their login tokens from the external login provider. // These tokens are stored in the umbracoExternalLoginToken table. var idToken = currentMember?.LoginTokens.FirstOrDefault(x => x.Name == "id_token"); if (idToken != null && !string.IsNullOrEmpty(idToken.Value)) { // Some external login providers need the IdTokenHint. // By setting the IdTokenHint the user can be redirected back from the external login provider to this website. protocolMessage.IdTokenHint = idToken.Value; } } await Task.FromResult(0); }; }); }); }); return builder;}}

I am getting very desperate so any help would be appreciated! I am absolutely stumped why this behaviour would occur when hosting it on azure. I am certain my okta config is correct so I have already ruled that out. I am using Umbraco 12 if that makes a difference.

umbracoexternallogincontrollerexternallogin not working as expected when hosting on azure app service 


            Using Umbraco And Getting Started (2024)
Top Articles
Latest Posts
Article information

Author: Dong Thiel

Last Updated:

Views: 5562

Rating: 4.9 / 5 (79 voted)

Reviews: 94% of readers found this page helpful

Author information

Name: Dong Thiel

Birthday: 2001-07-14

Address: 2865 Kasha Unions, West Corrinne, AK 05708-1071

Phone: +3512198379449

Job: Design Planner

Hobby: Graffiti, Foreign language learning, Gambling, Metalworking, Rowing, Sculling, Sewing

Introduction: My name is Dong Thiel, I am a brainy, happy, tasty, lively, splendid, talented, cooperative person who loves writing and wants to share my knowledge and understanding with you.