Azure AD for user login - unable to link existing accounts
Hi all,
I'm looking to integrate Azure AD for user login to the back-office (v76.1). I've followed the instructions in this blog post and I'm using the IdentityExtensions and IdentityExtensions.AzureActiveDirectory packages.
I'm able to see that I connect through to Azure AD and it returns some data back to Umbraco. It also creates a new user if there isn't one there already, but it always then fails with A user with this email address already exists locally. You will need to login locally to Umbraco and link this external provider.
When I then login normally and press the Link your Active Directory account, it goes off to Azure AD and returns back, but the accounts aren't linked. The setup is following the guidance here so I'm not sure what's missing?
Nothing ever gets written to the umbracoExternalLogin table either - I presume that should be used here?
You'll need to first diagnose the simpler case. Before adding any auto-linking options and custom auto-linking code, you need to first ensure that you can actually link your OAuth provider to an existing account.
So first thing to do is:
Remove the callback AuthorizationCodeReceived
Remove the call to SetExternalSignInAutoLinkOptions
So that you have the simplest code possible (least moving parts). You need to make sure this works before doing any auto-linking.
So now create a new back office user and log in as them, then try to link their account to your AD OAuth provider in the dialog when you click on your Avatar in the back office.
If this doesn't work then some debugging needs to happen. Because Azure AD is a bit odd, it uses the 'issuer path' as the auth type ... though it's been a very long time since I last tested this, I'm unsure if this has changed. I suspect that if this is not working that perhaps the auth-type isn't matching. In which case, you can have a look at the DB table contents: umbracoExternalLogin to see what information was recorded and take note of the data that was entered for the user you just tried to link your AD too, that might yield why this isn't working.
Thanks for this. I've stripped the code back to the basics, but we're getting the same result. If I log in as a local user and then try to link accounts, I just get redirected back to /umbraco with the option still there to link. If I then log out and try to log in with Azure AD, I get the message The requested provider has not been linked to an account. At no point is anything written to the umbracoExternalLogin table either.
We can pick up a response from Azure AD with the expected results, but this then seems to disappear within Umbraco. There is an empty UMB_EXTLOGIN cookie being set, and there's a second cookie that is only there for a split second before the login redirect to Microsoft occurs, but neither persist with any data.
I've also tried changing the AuthenticationType to Cookie and Bearer with no luck (same responses), and the current type is using the https://sts.windows.net/{tenantId}. Where would you recommend I look from here?
In many cases people have just forgotten an ending '/' on the login redirect Url or other character mistakes with the above since they need to be exact.
The next step is that you'll need to debug the callbacks. Sorry but this is the only way to know what data is coming and going into your app which is something that you'll need to do to try to figure out where the problem lies. To do that you can use the Notifications on the OpenIdConnectAuthenticationOptions, then set callbacks for each available callback method and put a breakpoint there to see what is happening.
Also make sure you check your logs! I think I've just discovered an issue with the linking when the auth type doesn't match, when this happens you should get a warning in your log file like: Could not find external authentication provider registered... but when that happens the code should terminate, instead it continues which will result in a ysod.
Also make sure you have your chome dev tools open when doing this to see if you are getting any 500 responses in your network tab
I've double checked the values to make sure they match. If one of them doesn't, we pick up errors and/or the Microsoft callbacks don't complete.
Checking the logs, we only see one message: WARN Umbraco.Core.Logging.OwinLogger - Event Id: 0, state: The state field is missing or invalid. I'm trying to trace this back but I can't pick up where it's directly coming from - I get the impression state isn't directly related to Azure AD, but I'm not 100% sure?
For the callbacks, they get hit in this order at the moment, and don't appear to list any errors (and do include my details back from Azure AD): MessageReceived, RedirectToIdentityProvider, MessageReceived, SecurityTokenReceived, SecurityTokenValidated, AuthorizationCodeReceived. Is there something specific I should look for in one of these that can further point me to the issue?
As a side note, almost all of the ASP.NET Identity implementation and debugging I've done has been by reading through source code. This source code site is nice, but otherwise you can go directly to https://github.com/aspnet/AspNetKatana
and I managed to get to the point of it failing on obtaining the email addr.
In another post somewhere on the web, I read that the email was in a prop called 'upn'
var email = context.JwtSecurityToken.Claims.First(x => x.Type == "upn").Value;
So i now have AD auth and auto linking, so thanks for the help - although this does not solve reason behind
Umbraco.Core.Logging.OwinLogger - Event Id: 0, state: The state field is missing or invalid.
you can add these rows and it will solve your problem:
var adOptions = new OpenIdConnectAuthenticationOptions
{
SignInAsAuthenticationType = Constants.Security.BackOfficeExternalAuthenticationType,
ClientId = clientId,
Authority = authority,
AuthenticationMode = AuthenticationMode.Passive,
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = async notification =>
{
var id = notification.AuthenticationTicket.Identity;
// we want to keep first name, last name, subject and roles
var givenName = id.FindFirst(ClaimTypes.GivenName);
if(givenName==null) givenName= id.FindFirst("name");
var familyName = id.FindFirst(ClaimTypes.Surname);
if (familyName == null) familyName= id.FindFirst("name");
var email = id.FindFirst(ClaimTypes.Email);
if (email == null) email= id.FindFirst(ClaimTypes.Upn);
var roles = id.FindAll(ClaimTypes.Role);
// 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.AddClaims(roles);
nid.AddClaim(id.FindFirst(ClaimTypes.NameIdentifier));
var emailclaim = new Claim(ClaimTypes.Email, email.Value);
nid.AddClaim(emailclaim);
notification.AuthenticationTicket = new AuthenticationTicket(
nid,
notification.AuthenticationTicket.Properties);
},
}
};
another way:
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = async context =>
{
var userService = ApplicationContext.Current.Services.UserService;
var email = context.JwtSecurityToken.Claims.First(x => x.Type == "upn" || x.Type == "email").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
Azure AD for user login - unable to link existing accounts
Hi all,
I'm looking to integrate Azure AD for user login to the back-office (v76.1). I've followed the instructions in this blog post and I'm using the
IdentityExtensions
andIdentityExtensions.AzureActiveDirectory
packages.I'm able to see that I connect through to Azure AD and it returns some data back to Umbraco. It also creates a new user if there isn't one there already, but it always then fails with
A user with this email address already exists locally. You will need to login locally to Umbraco and link this external provider
.When I then login normally and press the
Link your Active Directory account
, it goes off to Azure AD and returns back, but the accounts aren't linked. The setup is following the guidance here so I'm not sure what's missing?Nothing ever gets written to the
umbracoExternalLogin
table either - I presume that should be used here?For reference, here's my current
ConfigureBackOfficeAzureActiveDirectoryAuth
method:You'll need to first diagnose the simpler case. Before adding any auto-linking options and custom auto-linking code, you need to first ensure that you can actually link your OAuth provider to an existing account.
So first thing to do is:
AuthorizationCodeReceived
SetExternalSignInAutoLinkOptions
So that you have the simplest code possible (least moving parts). You need to make sure this works before doing any auto-linking.
So now create a new back office user and log in as them, then try to link their account to your AD OAuth provider in the dialog when you click on your Avatar in the back office.
If this doesn't work then some debugging needs to happen. Because Azure AD is a bit odd, it uses the 'issuer path' as the auth type ... though it's been a very long time since I last tested this, I'm unsure if this has changed. I suspect that if this is not working that perhaps the auth-type isn't matching. In which case, you can have a look at the DB table contents:
umbracoExternalLogin
to see what information was recorded and take note of the data that was entered for the user you just tried to link your AD too, that might yield why this isn't working.Hi Shannon,
Thanks for this. I've stripped the code back to the basics, but we're getting the same result. If I log in as a local user and then try to link accounts, I just get redirected back to
/umbraco
with the option still there to link. If I then log out and try to log in with Azure AD, I get the messageThe requested provider has not been linked to an account
. At no point is anything written to theumbracoExternalLogin
table either.We can pick up a response from Azure AD with the expected results, but this then seems to disappear within Umbraco. There is an empty
UMB_EXTLOGIN
cookie being set, and there's a second cookie that is only there for a split second before the login redirect to Microsoft occurs, but neither persist with any data.I've also tried changing the
AuthenticationType
toCookie
andBearer
with no luck (same responses), and the current type is using thehttps://sts.windows.net/{tenantId}
. Where would you recommend I look from here?I'm not sure why you are trying to change
AuthenticationType
to cookie or bearer, that is definitely not going to work ;)What information are you passing into this method for
tenant
,clientId
postLoginRedirectUri
this also needs to match exactly what you have configured in your AD
other docs https://github.com/umbraco/UmbracoIdentityExtensions/blob/master/src/App_Start/UmbracoADAuthExtensions.cs#L25
issuerId
see https://github.com/umbraco/UmbracoIdentityExtensions/blob/master/src/App_Start/UmbracoADAuthExtensions.cs#L28In many cases people have just forgotten an ending '/' on the login redirect Url or other character mistakes with the above since they need to be exact.
The next step is that you'll need to debug the callbacks. Sorry but this is the only way to know what data is coming and going into your app which is something that you'll need to do to try to figure out where the problem lies. To do that you can use the
Notifications
on theOpenIdConnectAuthenticationOptions
, then set callbacks for each available callback method and put a breakpoint there to see what is happening.Also make sure you check your logs! I think I've just discovered an issue with the linking when the auth type doesn't match, when this happens you should get a warning in your log file like:
Could not find external authentication provider registered...
but when that happens the code should terminate, instead it continues which will result in a ysod.Also make sure you have your chome dev tools open when doing this to see if you are getting any 500 responses in your network tab
Thanks again, Shannon!
I've double checked the values to make sure they match. If one of them doesn't, we pick up errors and/or the Microsoft callbacks don't complete.
Checking the logs, we only see one message:
WARN Umbraco.Core.Logging.OwinLogger - Event Id: 0, state: The state field is missing or invalid.
I'm trying to trace this back but I can't pick up where it's directly coming from - I get the impression state isn't directly related to Azure AD, but I'm not 100% sure?For the callbacks, they get hit in this order at the moment, and don't appear to list any errors (and do include my details back from Azure AD):
MessageReceived
,RedirectToIdentityProvider
,MessageReceived
,SecurityTokenReceived
,SecurityTokenValidated
,AuthorizationCodeReceived
. Is there something specific I should look for in one of these that can further point me to the issue?That warning message is interesting. The string "The state field is missing or invalid" doesn't come from Umbraco, but it does come from Microsoft's OpenId middleware, see http://sourcebrowser.io/Browse/aspnet/AspNetKatana/src/Microsoft.Owin.Security.OpenIdConnect/OpenidConnectAuthenticationHandler.cs#245
Based on this code, you should be able to see what information is missing. Just above this line of code you can see a call back is executed that you can bind to
MessageReceived
which gets passed themessageReceivedNotification
which contains theProtocolMessage
which contains aState
property which is the thing that is checked in the call toGetPropertiesFromState
. That method is here: http://sourcebrowser.io/Browse/aspnet/AspNetKatana/src/Microsoft.Owin.Security.OpenIdConnect/OpenidConnectAuthenticationHandler.cs#547... should give you a place to start looking.
As a side note, almost all of the ASP.NET Identity implementation and debugging I've done has been by reading through source code. This source code site is nice, but otherwise you can go directly to https://github.com/aspnet/AspNetKatana
Hi Ed,
Did you manage to resolve this issue? Im getting the same error...
Ive been battling various issues getting User authentication via AD on 7.11 for a few days.
I also had the same error in the logs and thanks to this post Ive now got it working.
I was using the default Configuration from UmbracoStandardOwinStartup + SetExternalSignInAutoLinkOptions (to attempt to get the auto linking).
I then tried adding the following, which was detailed in this post
and I managed to get to the point of it failing on obtaining the email addr. In another post somewhere on the web, I read that the email was in a prop called 'upn'
So i now have AD auth and auto linking, so thanks for the help - although this does not solve reason behind
you can add these rows and it will solve your problem:
another way:
Rivki Aizen
is working on a reply...