Base solution for your next web application
Open Closed

Internal methods used in GetExternalAuthenticationProviders API of TokenAuthcontroller not working #12199


User avatar
0
kansoftware created

I have enabled the AllowSocialLoginSettingsPerTenant and OpenId in appsettings.json. Also I have a configured OpenId for a tenant. Now when I am calling the below function for that tenant, the allproviders return null.

[HttpGet] public List<ExternalLoginProviderInfoModel> GetExternalAuthenticationProviders() {
var allProviders = _externalAuthConfiguration.ExternalLoginInfoProviders .Select(infoProvider => infoProvider.GetExternalLoginInfo()) .Where(IsSchemeEnabledOnTenant) .ToList(); return ObjectMapper.Map<List<ExternalLoginProviderInfoModel>>(allProviders); }

Basically I am getting null from GetExternalLoginInfo.

Could you please let me know how to resolve this, as I am stuck in this completely.


8 Answer(s)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @kansoftware

    Where are you using the GetExternalAuthenticationProviders method? When I call the default GetExternalAuthenticationProviders method in the TokenAuthController under *Web.Core, data is returned as shown in the screenshot below. You may want to check the OpenId settings in appsettings.json again. Could you provide more details so I can reproduce this issue?

  • User Avatar
    0
    kansoftware created

    Hi @kansoftware

    Where are you using the GetExternalAuthenticationProviders method? When I call the default GetExternalAuthenticationProviders method in the TokenAuthController under *Web.Core, data is returned as shown in the screenshot below. You may want to check the OpenId settings in appsettings.json again. Could you provide more details so I can reproduce this issue?

    Right now I am calling through postman. Below is the curl curl --location 'https://localhost:44302/api/TokenAuth/GetExternalAuthenticationProviders'
    --header 'abp.tenantid: 2'

    Below is my appsettings for authentication block "Authentication": { "AllowSocialLoginSettingsPerTenant": true, "Facebook": { "IsEnabled": "false", "AppId": "", "AppSecret": "" }, "Google": { "IsEnabled": "false", "ClientId": "", "ClientSecret": "", "UserInfoEndpoint": "https://www.googleapis.com/oauth2/v2/userinfo" }, "Twitter": { "IsEnabled": "false", "ConsumerKey": "", "ConsumerSecret": "" }, "Microsoft": { "IsEnabled": "false", "ConsumerKey": "", "ConsumerSecret": "" }, "WsFederation": { "IsEnabled": "false", "MetaDataAddress": "", "Wtrealm": "" }, "JwtBearer": { "IsEnabled": "true", "SecurityKey": "", "Issuer": "CDP", "Audience": "CDP" }, "OpenId": { "IsEnabled": "true", "Authority": "https://fynauth0.uk.auth0.com", "ClientId": "", "ClientSecret": "***", "ValidateIssuer": "false", "ResponseType": "code", "ClaimsMapping": [ { "claim": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "key": "http://schemas.microsoft.com/identity/claims/objectidentifier" } ] } }

    Also I have set openid for tenant id 2 from it's settings page as I have multi tenant application. Could you please let me know if I have missed out something. Also what changes you have made to enable openid

  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi kansoftware

    ExternalAuthenticationProvider structure in MVC is different from Angular. The GetExternalAuthenticationProvidersmethod in TokenAuthController is used in Angular. In MVC, ExternalAuthConfiguration *WebMvcModule.cs must also be configured. Configuration example: You can configure it according to your scenario by using the ConfigureExternalAuthProviders method in the *WebHostModule.cs class in the *.Host project. Or if you want to use it as Scheme, you can use the GetExternalAuthenticationSchemesAsync method in the SignInManager class in the *.Core project.

  • User Avatar
    0
    kansoftware created

    Hi kansoftware

    ExternalAuthenticationProvider structure in MVC is different from Angular. The GetExternalAuthenticationProvidersmethod in TokenAuthController is used in Angular. In MVC, ExternalAuthConfiguration *WebMvcModule.cs must also be configured. Configuration example: You can configure it according to your scenario by using the ConfigureExternalAuthProviders method in the *WebHostModule.cs class in the *.Host project. Or if you want to use it as Scheme, you can use the GetExternalAuthenticationSchemesAsync method in the SignInManager class in the *.Core project.

    Hi I am reframing my question, I want to give the below API to my mobile app team to pass the okta provider code and get the access token of my application. So I found one function is already built in in token auth controller i.e. ExternalAuthenticate. I have configured okta for a tenant using openid from its settings page. Now when I am calling this API it gives me Unknown external auth provider error.

    public async Task<ExternalAuthenticateResultModel> ExternalAuthenticate( [FromBody] ExternalAuthenticateModel model) {
    var externalUser = await GetExternalUserInfo(model);

    var loginResult = await _logInManager.LoginAsync(
        new UserLoginInfo(model.AuthProvider, externalUser.ProviderKey, model.AuthProvider),
        GetTenancyNameOrNull()
    );
    
    switch (loginResult.Result)
    {
        case AbpLoginResultType.Success:
        {
            // One Concurrent Login 
            if (AllowOneConcurrentLoginPerUser())
            {
                await ResetSecurityStampForLoginResult(loginResult);
            }
    
            var refreshToken = CreateRefreshToken(
                await CreateJwtClaims(
                    loginResult.Identity,
                    loginResult.User,
                    tokenType: TokenType.RefreshToken
                )
            );
    
            var accessToken = CreateAccessToken(
                await CreateJwtClaims(
                    loginResult.Identity,
                    loginResult.User,
                    refreshTokenKey: refreshToken.key
                )
            );
    
            var returnUrl = model.ReturnUrl;
    
            if (model.SingleSignIn.HasValue && model.SingleSignIn.Value &&
                loginResult.Result == AbpLoginResultType.Success)
            {
                loginResult.User.SetSignInToken();
                returnUrl = AddSingleSignInParametersToReturnUrl(
                    model.ReturnUrl,
                    loginResult.User.SignInToken,
                    loginResult.User.Id,
                    loginResult.User.TenantId
                );
            }
    
            return new ExternalAuthenticateResultModel
            {
                AccessToken = accessToken,
                EncryptedAccessToken = GetEncryptedAccessToken(accessToken),
                ExpireInSeconds = (int) _configuration.AccessTokenExpiration.TotalSeconds,
                ReturnUrl = returnUrl,
                RefreshToken = refreshToken.token,
                RefreshTokenExpireInSeconds = (int) _configuration.RefreshTokenExpiration.TotalSeconds
            };
        }
        case AbpLoginResultType.UnknownExternalLogin:
        {
            var newUser = await RegisterExternalUserAsync(externalUser);
            if (!newUser.IsActive)
            {
                return new ExternalAuthenticateResultModel
                {
                    WaitingForActivation = true
                };
            }
    
            //Try to login again with newly registered user!
            loginResult = await _logInManager.LoginAsync(
                new UserLoginInfo(model.AuthProvider, model.ProviderKey, model.AuthProvider),
                GetTenancyNameOrNull()
            );
    
            if (loginResult.Result != AbpLoginResultType.Success)
            {
                throw _abpLoginResultTypeHelper.CreateExceptionForFailedLoginAttempt(
                    loginResult.Result,
                    externalUser.EmailAddress,
                    GetTenancyNameOrNull()
                );
            }
    
            var refreshToken = CreateRefreshToken(await CreateJwtClaims(loginResult.Identity,
                loginResult.User, tokenType: TokenType.RefreshToken)
            );
    
            var accessToken = CreateAccessToken(await CreateJwtClaims(loginResult.Identity,
                loginResult.User, refreshTokenKey: refreshToken.key));
    
            return new ExternalAuthenticateResultModel
            {
                AccessToken = accessToken,
                EncryptedAccessToken = GetEncryptedAccessToken(accessToken),
                ExpireInSeconds = (int) _configuration.AccessTokenExpiration.TotalSeconds,
                RefreshToken = refreshToken.token,
                RefreshTokenExpireInSeconds = (int) _configuration.RefreshTokenExpiration.TotalSeconds
            };
        }
        default:
        {
            throw _abpLoginResultTypeHelper.CreateExceptionForFailedLoginAttempt(
                loginResult.Result,
                externalUser.EmailAddress,
                GetTenancyNameOrNull()
            );
        }
    }
    

    }

  • User Avatar
    0
    maliming created
    Support Team

    hi

    I have configured okta for a tenant using openid from its settings page. Now when I am calling this API it gives me Unknown external auth provider error.

    Does UserLoginInfo(model.AuthProvider, externalUser.ProviderKey, model.AuthProvider) exist on your database?

    it generally coming from externalLoginInfo = await _signInManager.GetExternalLoginInfoAsync();

  • User Avatar
    0
    maliming created
    Support Team

    If UserLoginInfo exists under a tenant, you must switch to this tenant.

  • User Avatar
    0
    kansoftware created

    UserLoginInfo

    Sorry, I didn't understand. What do you mean can you please describe. I am getting the error from var externalUser = await GetExternalUserInfo(model); And after going to internal function the actual error comes from the below method

    public IDisposableDependencyObjectWrapper<IExternalAuthProviderApi> CreateProviderApi(string provider)
    {
        ExternalLoginProviderInfo externalLoginProviderInfo = ((!_externalAuthConfiguration.ExternalLoginInfoProviders.Any((IExternalLoginInfoProvider infoProvider) => infoProvider.Name == provider)) ? _externalAuthConfiguration.Providers.FirstOrDefault((ExternalLoginProviderInfo p) => p.Name == provider) : _externalAuthConfiguration.ExternalLoginInfoProviders.Single((IExternalLoginInfoProvider infoProvider) => infoProvider.Name == provider).GetExternalLoginInfo());
        if (externalLoginProviderInfo == null)
        {
            throw new Exception("Unknown external auth provider: " + provider);
        }
    
        IDisposableDependencyObjectWrapper<IExternalAuthProviderApi> disposableDependencyObjectWrapper = _iocResolver.ResolveAsDisposable<IExternalAuthProviderApi>(externalLoginProviderInfo.ProviderApiType);
        disposableDependencyObjectWrapper.Object.Initialize(externalLoginProviderInfo);
        return disposableDependencyObjectWrapper;
    }
    
  • User Avatar
    0
    maliming created
    Support Team

    Hi kan software

    Can you share a project to reproduce?

    In this way, we can quickly troubleshoot and solve the problem.

    [email protected]