Hi @albert @alper @gterdem
I've upgraded to 4.3.2 and verified the new code written by @gterdem is in place. Subsequent logins of the external user do not result in the exception screen and I am instead prompted to verify my email address instead. Great stuff!
Unfortunately the issue described in my comment (https://support.abp.io/QA/Questions/1363#answer-ff0a88a4-1407-43a8-93d3-39fcf144b248) is still happening. If I am signing in / signing up as a brand new external user I am not prompted to verify my email first - I am taken straight to the homepage and can use the application immediately. If I log out and try log in again with that user it will force me to verify for subsequent logins (as intended).
This exact issue was affecting users registering locally but it was fixed as part of https://support.abp.io/QA/Questions/1113/Self-Registering-User-Logged-In-Without-Confirming-Email-First
If a similar fix can be extended to include newly registered external users, that should solve this issue and I believe the ticket would be good to close off (atleast in my eyes). Have you been able to confirm the behaviour I have described on your end?
Thankyou
Hello
Just to provide a quick update. We've completed our demonstration with the customer and there were some conflicting view points on whether email confirmation should be enforced on SSO login or not. Ultimately the decision was made to enforce email verification (i.e not what I thought was necessary but not a big deal at the end of the day).
In my mind, that means when an admin switches the 'Force email verification option' on in the settings, it applies to external users as well. It also seemed like something that would be pretty straight forward to implement in the code as shown below.
I've put the following code block in when the external user is NotAllowed
to force them to confirm their email. Exactly how it's being done for a local user.
if (result.IsNotAllowed)
{
var user = await UserManager.FindByLoginAsync(loginInfo.LoginProvider, loginInfo.ProviderKey);
await StoreConfirmUser(user);
return RedirectToPage("./ConfirmUser", new
{
returnUrl = ReturnUrl,
returnUrlHash = ReturnUrlHash
});
}
<br> Unfortunately, I'm seeing a repeat of the same behaviour in https://support.abp.io/QA/Questions/1113/Self-Registering-User-Logged-In-Without-Confirming-Email-First where the very first time the user logs in, they are not prompted to verify their email and are dropped straight onto the home page logged in and can use the application. If you log out and log in again with the same external user, they are then prompted to verify.
If you were to extend whatever fix you have done in https://support.abp.io/QA/Questions/1113/Self-Registering-User-Logged-In-Without-Confirming-Email-First for external users as well, I think that would resolve this issue if you are also adding in the verification code block if a user is NotAllowed
.
Happy to provide any further material to assist with this issue, Just let me know.
Thanks
@alper @gterdem
Thankyou for responding to this one so promptly.
I've taken a look at the code sample you have provided and I have been able to successfully implement a workaround to satisfy my immediate use case (i.e Azure AD login without error and local user login requiring confirmed email addresses without error). If the user is coming in from an external provider, I don't need them to confirm their email address like I would a local user as they would already have done this on the external providers end. I progress the login workflow as normal for an external user only (local users still go through email confirmation process).
Will this workaround cause problems or break certain login workflows? If not, I am happy for this ticket to be closed.
Some additional thoughts
Would something like this be workable?
Anyway, just some personal thoughts on the matter.
Thankyou again
Hi @alper
I've created a new ticket here - https://support.abp.io/QA/Questions/1363/Azure-AD-'Username-Taken'-on-Subsequent-Logins
Thankyou
Hi @gterdem
I have been able to log in successfully with Azure AD on both the fresh copy of ABP and our existing solution using the new instructions you have provided. Thankyou!
There is one fly in the ointment though, unfortunately. If you require users to confirm their email on login (ABP setting), attempting to log in again with the same Azure AD user results in a 'username is already taken' error. If you switch the setting off and users don't need to confirm their emails, the issue doesn't occur.
Do you have any suggestions on how to resolve this one?
Thankyou again.
Hi @gterdem
Thankyou for looking into this one and confirming the reproducability. Do you have any additional updates on the status / progress of your investigation and a potential way forward (bug fix / workaround / configuration) for resolving this one in the short term?
We have a release planned in the next 1-2 weeks that was expected to include Azure AD integration for our clients. Depending on the complexity of the issue here and an ETA on a fix, my team may need the time period leading up to the release to figure something else out if Azure AD integration is not possible before the end of the month.
Thankyou again for your help.
Hi @maliming
I've upgraded our solution to 4.3 and this issue appears to be fixed now. Thankyou for resolving this.
Hi @maliming
I have created a brand new 4.3.0-rc.2 application but, unfortunately, the problem has not been resolved. I am still immediately logged in to the application upon registration without having to verify my email address first.
Have you been able to reproduce the issue on your end using the reproducability steps I have provided?
Many thanks
<br> <br>
Id,ClientId,ClientName,Description,ClientUri,LogoUri,Enabled,ProtocolType,RequireClientSecret,RequireConsent,AllowRememberConsent,AlwaysIncludeUserClaimsInIdToken,RequirePkce,AllowPlainTextPkce,RequireRequestObject,AllowAccessTokensViaBrowser,FrontChannelLogoutUri,FrontChannelLogoutSessionRequired,BackChannelLogoutUri,BackChannelLogoutSessionRequired,AllowOfflineAccess,IdentityTokenLifetime,AllowedIdentityTokenSigningAlgorithms,AccessTokenLifetime,AuthorizationCodeLifetime,ConsentLifetime,AbsoluteRefreshTokenLifetime,SlidingRefreshTokenLifetime,RefreshTokenUsage,UpdateAccessTokenClaimsOnRefresh,RefreshTokenExpiration,AccessTokenType,EnableLocalLogin,IncludeJwtId,AlwaysSendClientClaims,ClientClaimsPrefix,PairWiseSubjectSalt,UserSsoLifetime,UserCodeType,DeviceCodeLifetime,ExtraProperties,ConcurrencyStamp,CreationTime,CreatorId,LastModificationTime,LastModifierId,IsDeleted,DeleterId,DeletionTime
39fb0cd8-5ebd-d891-7227-41d8bdb599c4,Client_Swagger,Client_Swagger,Client_Swagger,,,t,oidc,f,f,t,t,f,f,f,f,,t,,t,t,300,,31536000,300,,31536000,1296000,1,f,1,0,t,f,f,client_,,,,300,{},d17f0620c203454b9a9aec1fffacd6e2,38:01.2,,38:01.2,,f,,
39fb0cd8-5e77-c65d-6d9b-b4a467324d69,Client_App,Client_App,Client_App,,,t,oidc,f,f,t,t,f,f,f,f,,t,,t,t,300,,400,300,,1800,900,1,f,1,0,t,f,f,client_,,,,300,{},2577c8202df3412db530849fa91dc765,38:01.1,,15:01.1,39fb0cd8-5993-8e42-b1a5-e791f73d1e9f,f,,
I've removed some of the repeating successful token refresh lines to fit within forum text limit
[23:27:53 INF] Request starting HTTP/2 OPTIONS [https://localhost:44362/connect/token](https://localhost:44362/connect/token) - -
[23:27:53 INF] CORS policy execution successful.
[23:27:53 INF] Request finished HTTP/2 OPTIONS [https://localhost:44362/connect/token](https://localhost:44362/connect/token) - - - 204 - - 0.2743ms
[23:27:53 INF] Request starting HTTP/2 POST [https://localhost:44362/connect/token](https://localhost:44362/connect/token) application/x-www-form-urlencoded 160
[23:27:53 INF] CORS policy execution successful.
[23:27:53 INF] Successfully validated the token.
[23:27:53 DBG] CORS request made for path: /connect/token from origin: [http://localhost:4200](http://localhost:4200)
[23:27:53 DBG] CorsPolicyService allowed origin: [http://localhost:4200](http://localhost:4200)
[23:27:53 INF] CORS policy execution successful.
[23:27:53 DBG] Request path /connect/token matched to endpoint type Token
[23:27:53 DBG] Endpoint enabled: Token, successfully created handler: IdentityServer4.Endpoints.TokenEndpoint
[23:27:53 INF] Invoking IdentityServer endpoint: IdentityServer4.Endpoints.TokenEndpoint for /connect/token
[23:27:53 DBG] Start token request.
[23:27:53 DBG] Start client validation
[23:27:53 DBG] Start parsing Basic Authentication secret
[23:27:53 DBG] Start parsing for secret in post body
[23:27:53 DBG] client id without secret found
[23:27:53 DBG] Parser found secret: PostBodySecretParser
[23:27:53 DBG] Secret id found: Client_App
[23:27:53 DBG] client configuration validation for client Client_App succeeded.
[23:27:53 DBG] Public Client - skipping secret validation success
[23:27:53 DBG] Client validation success
[23:27:53 INF] {"ClientId": "Client_App", "AuthenticationMethod": "NoSecret", "Category": "Authentication", "Name": "Client Authentication Success", "EventType": "Success", "Id": 1010, "Message": null, "ActivityId": "80000182-0003-f700-b63f-84710c7967bb", "TimeStamp": "2021-03-31T12:27:53.0000000Z", "ProcessId": 10416, "LocalIpAddress": "127.0.0.1:44362", "RemoteIpAddress": "127.0.0.1", "$type": "ClientAuthenticationSuccessEvent"}
[23:27:53 DBG] Start token request validation
[23:27:53 DBG] Start validation of refresh token request
[23:27:53 DBG] Validation of refresh token request success
[23:27:53 INF] Token request validation success, {"ClientId": "Client_App", "ClientName": "Client_App", "GrantType": "refresh_token", "Scopes": null, "AuthorizationCode": "********", "RefreshToken": "****ED42", "UserName": null, "AuthenticationContextReferenceClasses": null, "Tenant": null, "IdP": null, "Raw": {"grant_type": "refresh_token", "scope": "offline_access Client", "refresh_token": "***REDACTED***", "client_id": "Client_App"}, "$type": "TokenRequestValidationLog"}
[23:27:53 DBG] Updating refresh token
[23:27:53 DBG] Token usage is one-time only. Setting current handle as consumed, and generating new handle
[23:27:53 DBG] Created refresh token in store
[23:27:53 DBG] Getting claims for identity token for subject: 39fb0cd8-5993-8e42-b1a5-e791f73d1e9f and client: Client_App
[23:27:53 INF] {"ClientId": "Client_App", "ClientName": "Client_App", "RedirectUri": null, "Endpoint": "Token", "SubjectId": "39fb0cd8-5993-8e42-b1a5-e791f73d1e9f", "Scopes": "openid Client offline_access", "GrantType": "refresh_token", "Tokens": [{"TokenType": "id_token", "TokenValue": "****4Wmw", "$type": "Token"}, {"TokenType": "refresh_token", "TokenValue": "****62BC", "$type": "Token"}, {"TokenType": "access_token", "TokenValue": "****l3yQ", "$type": "Token"}], "Category": "Token", "Name": "Token Issued Success", "EventType": "Success", "Id": 2000, "Message": null, "ActivityId": "80000182-0003-f700-b63f-84710c7967bb", "TimeStamp": "2021-03-31T12:27:53.0000000Z", "ProcessId": 10416, "LocalIpAddress": "127.0.0.1:44362", "RemoteIpAddress": "127.0.0.1", "$type": "TokenIssuedSuccessEvent"}
[23:27:53 DBG] Token request success.
[23:27:53 INF] Request finished HTTP/2 POST [https://localhost:44362/connect/token](https://localhost:44362/connect/token) application/x-www-form-urlencoded 160 - 200 - application/json;+charset=UTF-8 123.8776ms
[REMOVED MULTIPLE REPEATING TOEKN REFRESH SUCCESS BLOCKS]
[23:53:08 INF] Request starting HTTP/2 OPTIONS [https://localhost:44362/connect/token](https://localhost:44362/connect/token) - -
[23:53:08 INF] CORS policy execution successful.
[23:53:08 INF] Request finished HTTP/2 OPTIONS [https://localhost:44362/connect/token](https://localhost:44362/connect/token) - - - 204 - - 0.3562ms
[23:53:08 INF] Request starting HTTP/2 POST [https://localhost:44362/connect/token](https://localhost:44362/connect/token) application/x-www-form-urlencoded 160
[23:53:08 INF] CORS policy execution successful.
[23:53:08 INF] Successfully validated the token.
[23:53:08 DBG] CORS request made for path: /connect/token from origin: [http://localhost:4200](http://localhost:4200)
[23:53:08 DBG] CorsPolicyService allowed origin: [http://localhost:4200](http://localhost:4200)
[23:53:08 INF] CORS policy execution successful.
[23:53:08 DBG] Request path /connect/token matched to endpoint type Token
[23:53:08 DBG] Endpoint enabled: Token, successfully created handler: IdentityServer4.Endpoints.TokenEndpoint
[23:53:08 INF] Invoking IdentityServer endpoint: IdentityServer4.Endpoints.TokenEndpoint for /connect/token
[23:53:08 DBG] Start token request.
[23:53:08 DBG] Start client validation
[23:53:08 DBG] Start parsing Basic Authentication secret
[23:53:08 DBG] Start parsing for secret in post body
[23:53:08 DBG] client id without secret found
[23:53:08 DBG] Parser found secret: PostBodySecretParser
[23:53:08 DBG] Secret id found: Client_App
[23:53:08 DBG] client configuration validation for client Client_App succeeded.
[23:53:08 DBG] Public Client - skipping secret validation success
[23:53:08 DBG] Client validation success
[23:53:08 INF] {"ClientId": "Client_App", "AuthenticationMethod": "NoSecret", "Category": "Authentication", "Name": "Client Authentication Success", "EventType": "Success", "Id": 1010, "Message": null, "ActivityId": "800001f6-0004-ea00-b63f-84710c7967bb", "TimeStamp": "2021-03-31T12:53:08.0000000Z", "ProcessId": 10416, "LocalIpAddress": "127.0.0.1:44362", "RemoteIpAddress": "127.0.0.1", "$type": "ClientAuthenticationSuccessEvent"}
[23:53:08 DBG] Start token request validation
[23:53:08 DBG] Start validation of refresh token request
[23:53:08 WRN] Refresh token has expired.
[23:53:08 WRN] Refresh token validation failed. aborting, {"ClientId": "Client_App", "ClientName": "Client_App", "GrantType": "refresh_token", "Scopes": null, "AuthorizationCode": "********", "RefreshToken": "********", "UserName": null, "AuthenticationContextReferenceClasses": null, "Tenant": null, "IdP": null, "Raw": {"grant_type": "refresh_token", "scope": "offline_access Client", "refresh_token": "***REDACTED***", "client_id": "Client_App"}, "$type": "TokenRequestValidationLog"}
[23:53:08 INF] {"ClientId": "Client_App", "ClientName": "Client_App", "RedirectUri": null, "Endpoint": "Token", "SubjectId": null, "Scopes": null, "GrantType": "refresh_token", "Error": "invalid_grant", "ErrorDescription": null, "Category": "Token", "Name": "Token Issued Failure", "EventType": "Failure", "Id": 2001, "Message": null, "ActivityId": "800001f6-0004-ea00-b63f-84710c7967bb", "TimeStamp": "2021-03-31T12:53:08.0000000Z", "ProcessId": 10416, "LocalIpAddress": "127.0.0.1:44362", "RemoteIpAddress": "127.0.0.1", "$type": "TokenIssuedFailureEvent"}
[23:53:08 INF] Request finished HTTP/2 POST [https://localhost:44362/connect/token](https://localhost:44362/connect/token) application/x-www-form-urlencoded 160 - 400 - application/json;+charset=UTF-8 41.7969ms
[23:56:04 INF] Request starting HTTP/2 OPTIONS [https://localhost:44362/.well-known/openid-configuration](https://localhost:44362/.well-known/openid-configuration) - -
[23:56:04 INF] CORS policy execution successful.
[23:56:04 INF] Request finished HTTP/2 OPTIONS [https://localhost:44362/.well-known/openid-configuration](https://localhost:44362/.well-known/openid-configuration) - - - 204 - - 0.9833ms
[23:56:04 INF] Request starting HTTP/2 GET [https://localhost:44362/.well-known/openid-configuration](https://localhost:44362/.well-known/openid-configuration) - -
[23:56:04 INF] CORS policy execution successful.
[23:56:04 INF] Successfully validated the token.
[23:56:04 DBG] CORS request made for path: /.well-known/openid-configuration from origin: [http://localhost:4200](http://localhost:4200)
[23:56:04 DBG] CorsPolicyService allowed origin: [http://localhost:4200](http://localhost:4200)
[23:56:04 INF] CORS policy execution successful.
[23:56:04 DBG] Request path /.well-known/openid-configuration matched to endpoint type Discovery
[23:56:04 DBG] Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryEndpoint
[23:56:04 INF] Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration
[23:56:04 DBG] Start discovery request
[23:56:04 INF] Request finished HTTP/2 GET [https://localhost:44362/.well-known/openid-configuration](https://localhost:44362/.well-known/openid-configuration) - - - 200 - application/json;+charset=UTF-8 29.5408ms
[23:56:04 INF] Request starting HTTP/2 OPTIONS [https://localhost:44362/.well-known/openid-configuration/jwks](https://localhost:44362/.well-known/openid-configuration/jwks) - -
[23:56:04 INF] CORS policy execution successful.
[23:56:04 INF] Request finished HTTP/2 OPTIONS [https://localhost:44362/.well-known/openid-configuration/jwks](https://localhost:44362/.well-known/openid-configuration/jwks) - - - 204 - - 0.2289ms
[23:56:04 INF] Request starting HTTP/2 GET [https://localhost:44362/.well-known/openid-configuration/jwks](https://localhost:44362/.well-known/openid-configuration/jwks) - -
[23:56:04 INF] CORS policy execution successful.
[23:56:04 INF] Successfully validated the token.
[23:56:04 DBG] CORS request made for path: /.well-known/openid-configuration/jwks from origin: [http://localhost:4200](http://localhost:4200)
[23:56:04 DBG] CorsPolicyService allowed origin: [http://localhost:4200](http://localhost:4200)
[23:56:04 INF] CORS policy execution successful.
[23:56:04 DBG] Request path /.well-known/openid-configuration/jwks matched to endpoint type Discovery
[23:56:04 DBG] Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryKeyEndpoint
[23:56:04 INF] Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryKeyEndpoint for /.well-known/openid-configuration/jwks
[23:56:04 DBG] Start key discovery request
[23:56:04 INF] Request finished HTTP/2 GET [https://localhost:44362/.well-known/openid-configuration/jwks](https://localhost:44362/.well-known/openid-configuration/jwks) - - - 200 - application/json;+charset=UTF-8 10.8135ms
[23:56:04 INF] Request starting HTTP/2 OPTIONS [https://localhost:44362/connect/token](https://localhost:44362/connect/token) - -
[23:56:04 INF] CORS policy execution successful.
[23:56:04 INF] Request finished HTTP/2 OPTIONS [https://localhost:44362/connect/token](https://localhost:44362/connect/token) - - - 204 - - 0.2310ms
[23:56:04 INF] Request starting HTTP/2 POST [https://localhost:44362/connect/token](https://localhost:44362/connect/token) application/x-www-form-urlencoded 160
[23:56:04 INF] CORS policy execution successful.
[23:56:04 INF] Successfully validated the token.
[23:56:04 DBG] CORS request made for path: /connect/token from origin: [http://localhost:4200](http://localhost:4200)
[23:56:04 DBG] CorsPolicyService allowed origin: [http://localhost:4200](http://localhost:4200)
[23:56:04 INF] CORS policy execution successful.
[23:56:04 DBG] Request path /connect/token matched to endpoint type Token
[23:56:04 DBG] Endpoint enabled: Token, successfully created handler: IdentityServer4.Endpoints.TokenEndpoint
[23:56:04 INF] Invoking IdentityServer endpoint: IdentityServer4.Endpoints.TokenEndpoint for /connect/token
[23:56:04 DBG] Start token request.
[23:56:04 DBG] Start client validation
[23:56:04 DBG] Start parsing Basic Authentication secret
[23:56:04 DBG] Start parsing for secret in post body
[23:56:04 DBG] client id without secret found
[23:56:04 DBG] Parser found secret: PostBodySecretParser
[23:56:04 DBG] Secret id found: Client_App
[23:56:04 DBG] client configuration validation for client Client_App succeeded.
[23:56:04 DBG] Public Client - skipping secret validation success
[23:56:04 DBG] Client validation success
[23:56:04 INF] {"ClientId": "Client_App", "AuthenticationMethod": "NoSecret", "Category": "Authentication", "Name": "Client Authentication Success", "EventType": "Success", "Id": 1010, "Message": null, "ActivityId": "8000053f-0005-e500-b63f-84710c7967bb", "TimeStamp": "2021-03-31T12:56:04.0000000Z", "ProcessId": 10416, "LocalIpAddress": "127.0.0.1:44362", "RemoteIpAddress": "127.0.0.1", "$type": "ClientAuthenticationSuccessEvent"}
[23:56:04 DBG] Start token request validation
[23:56:04 DBG] Start validation of refresh token request
[23:56:04 WRN] Refresh token has expired.
[23:56:04 WRN] Refresh token validation failed. aborting, {"ClientId": "Client_App", "ClientName": "Client_App", "GrantType": "refresh_token", "Scopes": null, "AuthorizationCode": "********", "RefreshToken": "********", "UserName": null, "AuthenticationContextReferenceClasses": null, "Tenant": null, "IdP": null, "Raw": {"grant_type": "refresh_token", "scope": "offline_access Client", "refresh_token": "***REDACTED***", "client_id": "Client_App"}, "$type": "TokenRequestValidationLog"}
[23:56:04 INF] {"ClientId": "Client_App", "ClientName": "Client_App", "RedirectUri": null, "Endpoint": "Token", "SubjectId": null, "Scopes": null, "GrantType": "refresh_token", "Error": "invalid_grant", "ErrorDescription": null, "Category": "Token", "Name": "Token Issued Failure", "EventType": "Failure", "Id": 2001, "Message": null, "ActivityId": "8000053f-0005-e500-b63f-84710c7967bb", "TimeStamp": "2021-03-31T12:56:04.0000000Z", "ProcessId": 10416, "LocalIpAddress": "127.0.0.1:44362", "RemoteIpAddress": "127.0.0.1", "$type": "TokenIssuedFailureEvent"}
[23:56:04 INF] Request finished HTTP/2 POST [https://localhost:44362/connect/token](https://localhost:44362/connect/token) application/x-www-form-urlencoded 160 - 400 - application/json;+charset=UTF-8 31.2436ms