Open Closed

Invalid username and password using IdentityModel.Client; #6452


User avatar
0
rogercprops created
  • ABP Framework version: v7.2.2 Commercial
  • UI Type: N/A
  • Database System: EF Core SQL Server
  • Tiered (for MVC) or Auth Server Separated (for Angular): yes
  • Exception message and full stack trace: We're using the microservice template and using the auth-server app for authentication. The auth-server application has been slightly modified for custom branding.

We have a .net API to get a token using the IdentityModel.Client.

When I call the API using Postman that's pointing to the auth-server running on localhost via Tye I'm able to successfully get a token. When I call the API pointing to the auth-server running in Azure Kubernetes I get an invalid username and password error.

The code is the exact same. The database is the same and the credentials are the exact same.

Here's the log from the localhost version: [auth-server_7b8d49a0-6]: [14:31:40 INF] Request starting HTTP/1.1 GET https://localhost:44322/.well-known/openid-configuration - - [auth-server_7b8d49a0-6]: [14:31:40 INF] Request finished HTTP/1.1 GET https://localhost:44322/.well-known/jwks - - - 200 1620 application/json;charset=UTF-8 14.9184ms [auth-server_7b8d49a0-6]: [14:31:40 INF] Request starting HTTP/1.1 POST https://localhost:44322/connect/token application/x-[www-form-urlencoded 357](http://www-form-urlencoded 357) [auth-server_7b8d49a0-6]: [14:31:40 INF] The request URI matched a server endpoint: Token. [auth-server_7b8d49a0-6]: [14:31:40 INF] The token request was successfully extracted: { [auth-server_7b8d49a0-6]: "grant_type": "password", [auth-server_7b8d49a0-6]: "username": "admin", [auth-server_7b8d49a0-6]: "password": "[redacted]", [auth-server_7b8d49a0-6]: "scope": "address email phone profile roles AccountService IdentityService AdministrationService SaasService ClientService ServicesService ClientServiceQueryService UserInfoQueryService DocumentService GuardianshipService NotesService ContactService EngagementLogService DocTemplateService FinancialsService", [auth-server_7b8d49a0-6]: "client_id": "PublicAPI", [auth-server_7b8d49a0-6]: "client_secret": "[redacted]" [auth-server_7b8d49a0-6]: }. [auth-server_7b8d49a0-6]: [14:31:41 INF] The token request was successfully validated. [auth-server_7b8d49a0-6]: [14:31:42 INF] The response was successfully returned as a JSON document: { [auth-server_7b8d49a0-6]: "access_token": "[redacted]", [auth-server_7b8d49a0-6]: "token_type": "Bearer", [auth-server_7b8d49a0-6]: "expires_in": 3600 [auth-server_7b8d49a0-6]: }. [auth-server_7b8d49a0-6]: [14:31:42 INF] Request finished HTTP/1.1 POST https://localhost:44322/connect/token application/x-[www-form-urlencoded 357](http://www-form-urlencoded 357) - 200 1946 application/json;charset=UTF-8 1888.1892ms

Here's the log from the AKS version: [20:18:22 INF] Request starting HTTP/1.1 GET http://authserver.cloverleafcms.dev/.well-known/openid-configuration - - [20:18:22 INF] Request finished HTTP/1.1 GET http://authserver.cloverleafcms.dev/.well-known/openid-configuration - - - 200 2461 application/json;charset=UTF-8 171.3345ms [20:18:22 INF] Request starting HTTP/1.1 GET http://authserver.cloverleafcms.dev/.well-known/jwks - - [20:18:22 INF] The token request was successfully extracted: { "grant_type": "password", "username": "admin", "password": "[redacted]", "scope": "address email phone profile roles AccountService IdentityService AdministrationService SaasService ClientService ServicesService ClientServiceQueryService UserInfoQueryService DocumentService GuardianshipService NotesService ContactService EngagementLogService DocTemplateService FinancialsService", "client_id": "PublicAPI", "client_secret": "[redacted]" }. [20:18:24 INF] The response was successfully returned as a JSON document: { "error": "invalid_grant", "error_description": "Invalid username or password!", "error_uri": "https://documentation.openiddict.com/errors/ID2024" }. [20:18:25 INF] Request finished HTTP/1.1 POST http://authserver.cloverleafcms.dev/connect/token application/x-[www-form-urlencoded 360](http://www-form-urlencoded 360) - 400 155 application/json;charset=UTF-8 3198.2666ms

  • Steps to reproduce the issue:
  1. Create a microservice solution using Abp Suite 7.2.2
  2. Run the solution locally using Tye
  3. Using Postman call the .net API that calls the get token endpoint from the auth-server microservice
  4. Generate a docker images for the auth server application and microservice services and the .net token api.
  5. Deploy the applications to Azure Kubernetes
  6. Change the url for the .net API in postman to the AKS ingress url for .net api

I can give you read access to our GitHub repositories if necessary.

Thank you


8 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Please make sure there is a admin user exists on your k8s environment.

  • User Avatar
    0
    rogercprops created

    Hi,

    As I said, the databases are exactly the same. The database is SQL server running in a vm. localhost appsettings.json "ConnectionStrings": { "IdentityService": "Server=40.124.37.230;Database=CloverleafCMS_Identity;User Id=*;password=;MultipleActiveResultSets=true;TrustServerCertificate=True",

    auth-sever aks deployment manifest - name: "ConnectionStrings__IdentityService" value: "Server=40.124.37.230;Database=CloverleafCMS_Identity;User Id=;password=;TrustServerCertificate=True"

  • User Avatar
    0
    rogercprops created

    Here's the code for the .net API that uses the IdentityModel.Client;

    `using IdentityModel.Client; using OauthToken.Models;

    namespace OauthToken.Services { public class TokenService : ITokenService { private readonly IConfiguration _configuration;

        public TokenService(IConfiguration configuration)
        {
            _configuration = configuration;
        }
        public async Task<TokenRequestResponse?> GetAccessToken(string? Tenant, string ClientId, string ClientSecret, string UserName, string Password)
        {
            var apiEndpoint = _configuration.GetValue<string>("AuthServiceBaseUrl");
            var Scope = _configuration.GetValue<string>("Scope");
            var discoveryCache = new DiscoveryCache(apiEndpoint);
            var disco = await discoveryCache.GetAsync();
            var client = new HttpClient();
    
            var passwordTokenRequest = new PasswordTokenRequest
            {
                Address = disco.TokenEndpoint,
                ClientId = ClientId,
                ClientSecret = ClientSecret,
                UserName = UserName,
                Password = Password,
                Scope = Scope
            };
    
            if (Tenant != null) passwordTokenRequest.Headers.Add("__tenant", Tenant);
            var tokenResponse = await client.RequestPasswordTokenAsync(passwordTokenRequest);
            
            TokenRequestResponse tokenRequestResponse = new();
    
            if (tokenResponse.IsError)
            {
                tokenRequestResponse.ErrorCode = (int)tokenResponse.HttpResponse.StatusCode;
                tokenRequestResponse.Error = tokenResponse.ErrorDescription;
            }
            else
            {
                tokenRequestResponse.AccessToken = tokenResponse.AccessToken;
                tokenRequestResponse.RefreshToken = tokenResponse.RefreshToken;
                tokenRequestResponse.ExpiresIn = tokenResponse.ExpiresIn;
            }
    
            return tokenRequestResponse;
        }
    }
    

    }`

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Did you pass the string? Tenant? Are you using nginx?

    https://docs.abp.io/en/abp/latest/Multi-Tenancy#problems-with-the-nginx

    There is no problem with your code. We can make sure that it is related to the environment.

  • User Avatar
    0
    rogercprops created

    Hi,

    In the output I sent you, the Tenant was not passed because the admin userId is for the host (i.e. no tenant).

    I've given you read access to the GitHub repositories oauth-api (.net API) & auth-server (Abp auth-server app)

    I tried modifying the configmap for the nginx ingress controller and it still didn't work either with a tenant or without a tenant in the request.

    Here's the postman request passing a tenant in node.js format . `const axios = require('axios');

    let config = { method: 'post', maxBodyLength: Infinity, url: 'https://oauth.cloverleafcms.dev/Token?Tenant=TexasGuardians&ClientId=PublicAPI&ClientSecret=***&UserName=EddyFitz&Password=', headers: { } };

    axios.request(config) .then((response) => { console.log(JSON.stringify(response.data)); }) .catch((error) => { console.log(error); });`

    When I tried to get a token for a user in one of the SaaS tenants this is what's in the log for the AKS auth-server

    024-01-08T14:27:23.291440312Z [14:27:23 INF] Request finished HTTP/1.1 GET http://authserver.cloverleafcms.dev/.well-known/jwks - - - 200 1652 application/json;charset=UTF-8 10.7121ms 2024-01-08T14:27:23.340415663Z [14:27:23 INF] Request starting HTTP/1.1 POST http://authserver.cloverleafcms.dev/connect/token application/x-[www-form-urlencoded 361](http://www-form-urlencoded 361) 2024-01-08T14:27:23.341995658Z [14:27:23 INF] The request URI matched a server endpoint: Token. 2024-01-08T14:27:23.342031258Z [14:27:23 INF] The token request was successfully extracted: { 2024-01-08T14:27:23.342038958Z "grant_type": "password", 2024-01-08T14:27:23.342043558Z "username": "EddyFitz", 2024-01-08T14:27:23.342050958Z "password": "[redacted]", 2024-01-08T14:27:23.342816056Z "scope": "address email phone profile roles AccountService IdentityService AdministrationService SaasService ClientService ServicesService ClientServiceQueryService UserInfoQueryService DocumentService GuardianshipService NotesService ContactService EngagementLogService DocTemplateService FinancialsService", 2024-01-08T14:27:23.342856056Z "client_id": "PublicAPI", 2024-01-08T14:27:23.346486645Z "client_secret": "[redacted]" 2024-01-08T14:27:23.346807644Z }. 2024-01-08T14:27:24.199496948Z [14:27:24 INF] The token request was successfully validated. 2024-01-08T14:27:24.212204810Z [14:27:24 INF] Executing endpoint 'Volo.Abp.OpenIddict.Controllers.TokenController.HandleAsync (Volo.Abp.OpenIddict.AspNetCore)' 2024-01-08T14:27:24.213356906Z [14:27:24 INF] Route matched with {action = "Handle", controller = "Token", area = "", page = ""}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] HandleAsync() on controller Volo.Abp.OpenIddict.Controllers.TokenController (Volo.Abp.OpenIddict.AspNetCore). 2024-01-08T14:27:24.213624105Z [14:27:24 INF] Skipping the execution of current filter as its not the most effective filter implementing the policy Microsoft.AspNetCore.Mvc.ViewFeatures.IAntiforgeryPolicy 2024-01-08T14:27:24.228731859Z [14:27:24 INF] Try to use LDAP for external authentication 2024-01-08T14:27:24.255050379Z [14:27:24 WRN] Ldap login feature is not enabled! 2024-01-08T14:27:24.257459872Z [14:27:24 INF] Try to use OAUTH for external authentication 2024-01-08T14:27:24.261001161Z [14:27:24 WRN] OAuth login feature is not enabled! 2024-01-08T14:27:24.515941685Z [14:27:24 INF] No user found matching username: EddyFitz 2024-01-08T14:27:24.566320632Z [14:27:24 INF] Executing ForbidResult with authentication schemes (["OpenIddict.Server.AspNetCore"]). 2024-01-08T14:27:24.566390331Z [14:27:24 INF] The response was successfully returned as a JSON document: { 2024-01-08T14:27:24.566416131Z "error": "invalid_grant", 2024-01-08T14:27:24.566422131Z "error_description": "Invalid username or password!", 2024-01-08T14:27:24.566426931Z "error_uri": "https://documentation.openiddict.com/errors/ID2024" 2024-01-08T14:27:24.566431731Z }. 2024-01-08T14:27:24.566436331Z [14:27:24 INF] AuthenticationScheme: OpenIddict.Server.AspNetCore was forbidden. 2024-01-08T14:27:24.566442731Z [14:27:24 INF] Executed action Volo.Abp.OpenIddict.Controllers.TokenController.HandleAsync (Volo.Abp.OpenIddict.AspNetCore) in 348.651ms 2024-01-08T14:27:24.579174992Z [14:27:24 INF] Executed endpoint 'Volo.Abp.OpenIddict.Controllers.TokenController.HandleAsync (Volo.Abp.OpenIddict.AspNetCore)' 2024-01-08T14:27:24.661847341Z [14:27:24 INF] Request finished HTTP/1.1 POST http://authserver.cloverleafcms.dev/connect/token application/x-[www-form-urlencoded 361](http://www-form-urlencoded 361) - 400 155 application/json;charset=UTF-8 1321.5275ms 20

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you try to remove the HostTenantResolveContributer?

    You can override the HandlePasswordAsync method of TokenController. Output a log to show the current tenant.

    var tenant = await TenantConfigurationProvider.GetAsync(saveResolveResult: false);

    https://github.com/abpframework/abp/blob/dev/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs#L78

  • User Avatar
    0
    rogercprops created

    Hi,

    We're woking on this but we need the HostTenantResolveContributer since we're getting the tenant from the url for our front-end application. For example: auth.agency1.mydomain.com the tenant is agency1.

    We're also exposing some services via API and need to get a token. The request will have the tenant in the request header if it is not for the host. The tenant will be left off the request header if it is for the host.

    We'll try temporarily following your suggestion but we'll need to put the HostTenantResolveContributer back. So please don't close this ticket until we have everything working.

    Thank you,

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    ok.

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