Hi @kansoftware,
You can follow the steps used in Angular for updating the profile picture to implement the same functionality. However, for the mobile side, I recommend researching resources on MAUI file uploading for handling file uploads. If you’d like, I can create an issue for this feature in the next release.
Hi, Our mobile app is in ionic. We are using 13.0.0 version of dot net. Are you saying we need customize the code for mobile app? Or there is inbuilt functionality? Can you please provide me a documentation for that
Thanks
I can see that the functionality for updating the profile picture is built-in. To update the profile picture, the UpdateProfilePicture function is used, which is part of the Profile App Service. To fetch the profile picture, the GetProfilePicture function is used, which is part of the Profile Controller. This works on our web application.
How can we use the same functionality for our mobile application, and what changes do we need to make?
Can I call these function on login button in Account controller to set options at runtime? If yes then how
I have enabled okta using OIDC. In web application it worked fine. But I have a mobile application as well. I have create a SPA application on okta for mobile app. They will be sending me the access token retrieved from Okta. I need to get the user info from that token and then generate my application token and return them. Is there any built in function? Or how can i do that?
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;
}
I want to set OpenIdConnectOptions during runtime for tenant. Is it possible if yes then how?
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 theSignInManager
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()
);
}
}
}
Hi kansoftware
To enable both Okta and Auth0 for a single tenant in your multi-tenant application, you will need to customize the code, as the standard ASP.NET Zero implementation typically supports only one OpenID Connect provider per tenant.
Ok. For now I have enabled okta through oidc. I have added the default options in startup.cs. But also I have configured the openid for a tenant through tenant settings page. I want to know how and where does it replaces the client id and other details before redirecting to okta login page.
As for my custom code I want to set the credentials runtime because for each tenant it will be different. I hope I am making sense
I want to enable both okta and auth0 for a single tenant as some users may login through okta and some through auth0. I am having a multitenant application. Do I need to custom the code or there is a functionality in the base code. Could you please help me out how can I achieve that
Hi @kansoftware
Where are you using the
GetExternalAuthenticationProviders
method? When I call the defaultGetExternalAuthenticationProviders
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