Open Closed

Login from AspNetZero using IdentityServer #2775


User avatar
0
andmattia created

Hi

I try to use Identity Server to authenticate my user from ANZ.

On ANZ site I add openId configuration

    "OpenId": {
      "IsEnabled": "true",
      "ClientId": "anz-client",
      "Authority": "https://localhost:44308",
      "LoginUrl": "https://localhost:44308/Account/Login",
      "ValidateIssuer": "false",
      "ClaimsMapping": [
        {
          "claim": "unique_name",
          "key": "preferred_username"
        }
      ]
    },

Now after choose tenant on ANZ I see the OpenId Connection button. If I click it app redirect my to IS but not with tenant (first issue) after login process IS no redirect back to ANZ site.

My goal is:

  • copy user and tenant on ABP.IO
  • Enable IS on ABP.IO and use it to auth user from ANZ

21 Answer(s)
  • User Avatar
    0
    andmattia created

    Hi all

    I spent my last 3 days to try to identify why this not work.

    I start from scracth again with 2 clean solution ANZ 7.1 and ABP.IO 5.1.4 and I'm able to send my login to ABP.IO page but the flow not works. This is the configuration In ANZ we put this configuration

        "OpenId": {
          "IsEnabled": "true",
          "ClientId": "anz_client",
          "Authority": "https://localhost:44379/",
          "LoginUrl": "https://localhost:44379/Account/Login",
          "ValidateIssuer": "false",
          "ClaimsMapping": [
            {
              "claim": "unique_name",
              "key": "preferred_username"
            }
          ]
        },
    

    Go to login for default tenant we are redirect to https://localhost:44379/Account/Login?response_type=id_token&client_id=anz_client&state=dhMpK2WQPQWaY2fovyS9jhWyk3DXQceDYJ7Ff1WB%3BopenIdConnect%3D1&redirect_uri=http%3A%2F%2Flocalhost%3A4300%2Faccount%2Flogin&scope=openid%20profile&nonce=dhMpK2WQPQWaY2fovyS9jhWyk3DXQceDYJ7Ff1WB And no return happen

    I check the link generate from ABP.IO angular https://localhost:44379/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fresponse_type%3Dcode%26client_id%3DTest_App%26state%3DUHFYMlJ2TEx2ckt-V3BfdFN0LUNWVHRpZ2tmWVZiTTdvVnFVNEp6LkE4NXln%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A4200%26scope%3Dopenid%2520offline_access%2520Test%26code_challenge%3DaXtCQgVDgqr52DYoXZgL2-cktwkxIrmcCLTHf2Dtin0%26code_challenge_method%3DS256%26nonce%3DUHFYMlJ2TEx2ckt-V3BfdFN0LUNWVHRpZ2tmWVZiTTdvVnFVNEp6LkE4NXln%26culture%3Den%26ui-culture%3Den

    I see some differnce

    • ReturnUrl is missed on ANZ
    • response_type code vs id_token

    I hope is enough to investigate why doesn't work

  • User Avatar
    0
    andmattia created

    Any update?

  • User Avatar
    0
    andmattia created

    Hi

    could you please give us support on this issue?

  • User Avatar
    0
    alper created
    Support Team Director

    you might be getting HTTPS problems. because you use HTTP Also, this is related to a 3rd party component and we don't provide direct support for 3rd parties. You can ask it on the Identity Server repository. On the other hand, this is a consultancy topic, you can get consultancy services from our experienced architectures. send an email to info@abp.io

  • User Avatar
    0
    andmattia created

    Hi @albert

    I tried with Https but situation still the same.

    So I'm not agree with your answer "is related to a 3rd party component".

    My question is releted how ANZ and ABP.IO can comunicate. I think is a big point to allow project migration from ANZ to ABP for many customer and is not cover in any guide or document at the moment.

    I sended a full empty solution based on ANZ and ABP (without our customization) at @info to give you all information and data to try this issue.

    Any way I write to info to get a quotation for this issue

  • User Avatar
    1
    alper created
    Support Team Director

    thank you @andmattia I understand your situation and we'll definitely try to help you to solve your issue.

  • User Avatar
    0
    alper created
    Support Team Director

    @gterdem can you check the issue pls?

  • User Avatar
    0
    andmattia created

    Hi @gterdem

    to reproduce this issue I write the steps:

    • create an empty solution on ANZ (.NetCore + Angular Vs 7.1.0)
    • create an empty solution on ABP pro (v 5.1.4) + UI Angular
    • enable OpenId on ANZ (in prev post you can see our configuration)
    • enable option on IS in ABP.IO solution
    • start Angualr+API (ANZ)+IS(ABP.IO)
    • Try to login from Angular (ANZ)

    Our situation is this:

    • Login redirect to IS
    • Do login process correctly
    • No rederiction on ANZ site

    Let me know if you need more information

  • User Avatar
    0
    alper created
    Support Team Director

    Check that you are redirecting to a HTTPS address (this is important)

    also, enable Identity Server detailed logging then send us the logs.

    public override void ConfigureServices(ServiceConfigurationContext context)
    {
            Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
    }
    
  • User Avatar
    0
    andmattia created

    Hi I start apps in this configuration:

    For this configuration the endpoint on Angular via IS is https://localhost:44379/Account/login?response_type=id_token&client_id=anz_client&state=xxiEPGcW8Mx44MxvbDIz3orNCrTnFibn9ai7og7W%3BopenIdConnect%3D1&redirect_uri=https%3A%2F%2Flocalhost%3A4301%2Faccount%2Flogin&scope=openid%20profile&nonce=xxiEPGcW8Mx44MxvbDIz3orNCrTnFibn9ai7og7W

    About HTTPS I don't think is the problem. ABP.IO angular app start on http://localhost:4200/ and works fine...

    Below i copy&paste the log trace (is not the full stack because is too long to copy)

    2022-04-04 08:34:39.193 +02:00 [INF] Request starting HTTP/2 GET https://localhost:44379/Account/login?response_type=id_token&client_id=anz_client&state=LhrF5VqDmgShGSgOzV6LYPlPve1I2z3E9qraHfLm%3BopenIdConnect%3D1&redirect_uri=https%3A%2F%2Flocalhost%3A4301%2Faccount%2Flogin&scope=openid%20profile&nonce=LhrF5VqDmgShGSgOzV6LYPlPve1I2z3E9qraHfLm - -
    2022-04-04 08:34:39.627 +02:00 [DBG] Login Url: /Account/Login
    2022-04-04 08:34:39.627 +02:00 [DBG] Login Return Url Parameter: ReturnUrl
    2022-04-04 08:34:39.627 +02:00 [DBG] Logout Url: /Account/Logout
    2022-04-04 08:34:39.627 +02:00 [DBG] ConsentUrl Url: /Consent
    2022-04-04 08:34:39.627 +02:00 [DBG] Consent Return Url Parameter: returnUrl
    2022-04-04 08:34:39.627 +02:00 [DBG] Error Url: /Account/Error
    2022-04-04 08:34:39.627 +02:00 [DBG] Error Id Parameter: errorId
    2022-04-04 08:34:39.841 +02:00 [INF] Executing endpoint '/Account/Login'
    2022-04-04 08:34:39.885 +02:00 [INF] Route matched with {page = "/Account/Login", area = "", action = "", controller = ""}. Executing page /Account/Login
    2022-04-04 08:34:39.887 +02:00 [INF] Skipping the execution of current filter as its not the most effective filter implementing the policy Microsoft.AspNetCore.Mvc.ViewFeatures.IAntiforgeryPolicy
    2022-04-04 08:34:40.104 +02:00 [INF] Executing handler method Volo.Abp.Account.Public.Web.Pages.Account.LoginModel.OnGetAsync - ModelState is "Valid"
    2022-04-04 08:34:40.201 +02:00 [INF] Executed handler method OnGetAsync, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
    2022-04-04 08:34:41.270 +02:00 [DBG] Added bundle 'Lepton.Global' to the page in 36.26 ms.
    2022-04-04 08:34:41.327 +02:00 [DBG] Added bundle 'Lepton.Global' to the page in 8.41 ms.
    2022-04-04 08:34:41.345 +02:00 [INF] Executed page /Account/Login in 1455.6307ms
    2022-04-04 08:34:41.346 +02:00 [INF] Executed endpoint '/Account/Login'
    2022-04-04 08:34:41.360 +02:00 [INF] Request finished HTTP/2 GET https://localhost:44379/Account/login?response_type=id_token&client_id=anz_client&state=LhrF5VqDmgShGSgOzV6LYPlPve1I2z3E9qraHfLm%3BopenIdConnect%3D1&redirect_uri=https%3A%2F%2Flocalhost%3A4301%2Faccount%2Flogin&scope=openid%20profile&nonce=LhrF5VqDmgShGSgOzV6LYPlPve1I2z3E9qraHfLm - - - 200 - text/html;+charset=utf-8 2166.2434ms
    ...
    
    2022-04-04 08:35:04.268 +02:00 [INF] Request starting HTTP/2 POST https://localhost:44379/Account/login?response_type=id_token&client_id=anz_client&state=LhrF5VqDmgShGSgOzV6LYPlPve1I2z3E9qraHfLm%3BopenIdConnect%3D1&redirect_uri=https%3A%2F%2Flocalhost%3A4301%2Faccount%2Flogin&scope=openid%20profile&nonce=LhrF5VqDmgShGSgOzV6LYPlPve1I2z3E9qraHfLm application/x-www-form-urlencoded 334
    2022-04-04 08:35:04.276 +02:00 [INF] CORS policy execution failed.
    2022-04-04 08:35:04.276 +02:00 [INF] Request origin https://localhost:44379 does not have permission to access the resource.
    2022-04-04 08:35:04.283 +02:00 [INF] No CORS policy found for the specified request.
    2022-04-04 08:35:04.284 +02:00 [INF] Executing endpoint '/Account/Login'
    2022-04-04 08:35:04.284 +02:00 [INF] Route matched with {page = "/Account/Login", area = "", action = "", controller = ""}. Executing page /Account/Login
    2022-04-04 08:35:04.284 +02:00 [INF] Skipping the execution of current filter as its not the most effective filter implementing the policy Microsoft.AspNetCore.Mvc.ViewFeatures.IAntiforgeryPolicy
    2022-04-04 08:35:04.490 +02:00 [INF] Executing handler method Volo.Abp.Account.Public.Web.Pages.Account.LoginModel.OnPostAsync - ModelState is "Valid"
    2022-04-04 08:35:04.613 +02:00 [INF] Try to use LDAP for external authentication
    2022-04-04 08:35:04.618 +02:00 [WRN] Ldap login feature is not enabled!
    2022-04-04 08:35:07.022 +02:00 [DBG] Augmenting SignInContext
    2022-04-04 08:35:07.023 +02:00 [DBG] Adding idp claim with value: local
    2022-04-04 08:35:07.023 +02:00 [DBG] Adding auth_time claim with value: 1649054107
    2022-04-04 08:35:07.031 +02:00 [INF] AuthenticationScheme: Identity.Application signed in.
    2022-04-04 08:35:07.259 +02:00 [DBG] Added 0 entity changes to the current audit log
    2022-04-04 08:35:07.275 +02:00 [DBG] Added 0 entity changes to the current audit log
    2022-04-04 08:35:07.294 +02:00 [INF] {"Username":"admin","Provider":null,"ProviderUserId":null,"SubjectId":"8f9cbffc-a286-ffd5-3954-3a02d3218485","DisplayName":"admin","Endpoint":"UI","ClientId":null,"Category":"Authentication","Name":"User Login Success","EventType":"Success","Id":1000,"Message":null,"ActivityId":"0HMGM0KORJFEB:00000013","TimeStamp":"2022-04-04T06:35:07.0000000Z","ProcessId":36356,"LocalIpAddress":"::1:44379","RemoteIpAddress":"::1","$type":"UserLoginSuccessEvent"}
    2022-04-04 08:35:07.294 +02:00 [INF] Executed handler method OnPostAsync, returned result Microsoft.AspNetCore.Mvc.RedirectResult.
    2022-04-04 08:35:07.295 +02:00 [DBG] Added 0 entity changes to the current audit log
    2022-04-04 08:35:07.296 +02:00 [INF] Executing RedirectResult, redirecting to /.
    2022-04-04 08:35:07.296 +02:00 [INF] Executed page /Account/Login in 3011.8957ms
    2022-04-04 08:35:07.296 +02:00 [INF] Executed endpoint '/Account/Login'
    2022-04-04 08:35:07.297 +02:00 [DBG] Added 0 entity changes to the current audit log
    2022-04-04 08:35:07.503 +02:00 [DBG] Added 0 entity changes to the current audit log
    2022-04-04 08:35:07.503 +02:00 [DBG] Added 0 entity changes to the current audit log
    2022-04-04 08:35:07.511 +02:00 [INF] Request finished HTTP/2 POST https://localhost:44379/Account/login?response_type=id_token&client_id=anz_client&state=LhrF5VqDmgShGSgOzV6LYPlPve1I2z3E9qraHfLm%3BopenIdConnect%3D1&redirect_uri=https%3A%2F%2Flocalhost%3A4301%2Faccount%2Flogin&scope=openid%20profile&nonce=LhrF5VqDmgShGSgOzV6LYPlPve1I2z3E9qraHfLm application/x-www-form-urlencoded 334 - 302 0 - 3242.9496ms
    
    

    If you look into the log the redirect say

    [08:40:29 INF] Executing RedirectResult, redirecting to /.
    

    And not URL indecated on redirect_uri

  • User Avatar
    0
    gterdem created
    Support Team Senior .NET Developer

    Hi @andmattia,

    I'll try to reproduce this case and let you know. Can you verify that your ANZ version is 7.1.0 .Net Core 2.2?

  • User Avatar
    0
    andmattia created

    Hi

    Yes. ANZ 7.1.0 (NetCore 2.2).

    I do the same test with lastes ANZ but I'm still focus on 7.1.0 version

  • User Avatar
    1
    alper created
    Support Team Director

    ok thank you for the info.

  • User Avatar
    0
    gterdem created
    Support Team Senior .NET Developer

    You have an ANZ-Angular application which has its own token generation and validation within. You want to enable external login for ANZ-Angular application and use an ABP application identity server (tiered or non-tiered) as an openid provider.

    The distributed system you are trying to achieve somewhat looks like below:

    In this scenario, you are using ABP IdentityServer to externally login with ANZ-Angular application. You are not authorizing the ANZ-Web.Host, your access token is granted and validated only by ANZ-Web.Host not IdentityServer. To explain it shortly: you can not call ANZ-Web.Host from any extarnal application (ABP or not) because the SecureTokenServer is ANZ-Web.Host itself. Configuring IdentityServer for external login doesn't mean your STS is IdentityServer and will be validated by it. Anyways, that's a whole different consultancy on distributed systems story.

    There are some steps to activate external login using OpenId between ABP and ANZ-Angular:

    1. Register ANZ-Angular application to IdentityServer:

    You can either use the ABP IdentityServer Management UI as you mentioned above or update the CreateClientsAsync method of the IdentityServerDataSeedContributor under DbMigrator project :

    //Console Test / Angular Client
    ...
    
    //Anz Angular Client - Add this client
    var angular2 = configurationSection["AnzApp_App:ClientId"];
    if (!angular2.IsNullOrWhiteSpace())
    {
        var webClientRootUrl = configurationSection["AnzApp_App:RootUrl"]?.TrimEnd('/');
    
        await CreateClientAsync(
            name: angular2,
            scopes: commonScopes,
            grantTypes: new[] { "password", "implicit"  },
            secret: (configurationSection["AnzApp_App:ClientSecret"] ?? "1q2w3e*").Sha256(),
            requireClientSecret: false,
            redirectUri: webClientRootUrl,
            postLogoutRedirectUri: webClientRootUrl,
            corsOrigins: new[] { webClientRootUrl.RemovePostFix("/") }
        );
    }
    
    // Swagger Client
    ...
    

    Note: Don't forget to add implicit grant type.

    Update DbMigrator appsettings.json to add new configuration for this client:

    "IdentityServer": {
        "Clients": {
         ...
          "AnzApp_App": {
            "ClientId": "anz_client",
            "RootUrl": "http://localhost:4201"
          },
          ...
        }
      }
    

    Note: I used port 4201 for ANZ-Angular application, enter whichever port you are using.

    2. Update ANZ-Web.Host application:

    Navigate to WebHostModule.cs file under Startup folder and update the ConfigureExternalAuthProviders() method as below:

    private void ConfigureExternalAuthProviders()
    {
        var externalAuthConfiguration = IocManager.Resolve<ExternalAuthConfiguration>();
    
        if (bool.Parse(_appConfiguration["Authentication:OpenId:IsEnabled"]))
        {
            // Add this line to clear default ClaimsIdentity mapping
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
            if (bool.Parse(_appConfiguration["Authentication:AllowSocialLoginSettingsPerTenant"]))
            {
            ...
    

    You can check JwtSecurityTokenHandler for detailed information about default claim mapping.

    Navigate to appsettings.json and enable OpenId configuration:

    "OpenId": {
          "IsEnabled": "true",
          "ClientId": "anz_client",    // The client you have created in ABP IdentityServerDataSeedContributor
          "Authority": "https://localhost:44312", // ABP IdentityServer url
          "LoginUrl": "https://localhost:44312",  // ABP IdentityServer url
          "ValidateIssuer": "false",
          "ClaimsMapping": [            
          ]
        },
    
    3. Update ANZ-Angular application:

    Navigate to login.service.ts file under src/account/login folder. Find the getOpenIdConnectConfig(loginProvider: ExternalLoginProvider) method and update as below:

    private getOpenIdConnectConfig(loginProvider: ExternalLoginProvider): AuthConfig {
        let authConfig = new AuthConfig();
        // Update login url
        authConfig.loginUrl = loginProvider.additionalParams['LoginUrl'] +"/connect/authorize";
        authConfig.issuer = loginProvider.additionalParams['Authority'];
        authConfig.skipIssuerCheck = loginProvider.additionalParams['ValidateIssuer'] === 'false';
        authConfig.clientId = loginProvider.clientId;
        authConfig.responseType = 'id_token';
        authConfig.redirectUri = window.location.origin + '/account/login';
        // Add email scope
        authConfig.scope = 'openid profile email';
        authConfig.requestAccessToken = false;
        return authConfig;
    }
    
    Result:

    Known Issue: There is a claim mapping issue on ANZ side with mapping username and email, resulting with creating a user with wrong username and email:

    We'll fix it in next version of ANZ. For now, admin can update user information before activating the user.

  • User Avatar
    0
    alper created
    Support Team Director

    thanks @gterdem @andmattia check if it works for you. if there's no problem we can make this answer as a community article

  • User Avatar
    0
    andmattia created

    Hi @gterdem

    I've try and I confirm that work on ANZ lastest and on our target version 7.1.0.

    I found some little improve on flow (es port, url) but I think it's a very great artile to allow customers move forward from ANZ to ABP.IO.

    So I test we my team and we found 2 open pont:

    • User callback from ABP.IO Identity will be identify with GUID and not with orginal user (ex email, user) so we need to duplicate user on ANZ db. Is it possibile to merge or reconcile it with existing user?
    • On ANZ login user must do a click on OpenId but the best option could be direct redirection to ABP.IO Identity. Is it possibile?

    About community article if you want I/we can help you to wrinting it.

  • User Avatar
    0
    gterdem created
    Support Team Senior .NET Developer

    User callback from ABP.IO Identity will be identify with GUID and not with orginal user (ex email, user) so we need to duplicate user on ANZ db. Is it possibile to merge or reconcile it with existing user?

    Sorry, I don't follow. ABP application (IdentityServer) is an OpenId Provider, which contains the User Store that you authenticate your ANZ application users against. To explain it better; put Google (or Microsoft/Facebook/Twitter etc) instead of ABP application. You only use google login for your ANZ users. If the user is signing in the first time and doesn't exist in your ANZ application, the user is created in your ANZ application with Login provider, without any password. That's why it is an external login. You (ANZ application) don't have user's google (ABP application in your case) password. You only care if the user is authenticated against the external provider.

    On ANZ login user must do a click on OpenId but the best option could be direct redirection to ABP.IO Identity. Is it possibile?

    The easiest way is to customize the login page and instantly trigger OpenId provider click. For more info, you can check this article.

  • User Avatar
    0
    andmattia created

    Hi @gterdem

    this schema works on multitenant side?

    My team try to use it in SAAS app but they are not able to pagging tenant to Identity? we need to use special config to passing tenant on login process?

  • User Avatar
    0
    gterdem created
    Support Team Senior .NET Developer

    I think the subtle way to handle multi-tenancy on external openId provider is, adding tenant-id claim after login (adding to token) and using this claim in ANZ application.

  • User Avatar
    0
    andmattia created

    Ok but this il the flow from ABP.IO to ANZ but user start process from ANZ page in SAAS enviroment and need to be redirect to a auth server. The target auth server is in multi tenant enviroment. The correct flow I think is the first on the picture below but at the moment is not possibile. A mitigation of this could be setting tenant automaticly (es using {TENANCY_NAME} on config)

  • User Avatar
    0
    gterdem created
    Support Team Senior .NET Developer

    Well, it is about external login flow. There is nothing on identityserver about how to redirect back to whichever client is signed in.

    I think this should be handled in ANZ project. When redirected back; resolve tenant based on the tenant-id claim you have added and redirect to tenant domain.

Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11