204 lines
6.1 KiB
C#
204 lines
6.1 KiB
C#
using System.IdentityModel.Tokens.Jwt;
|
|
using System.Text;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
|
|
using ServerCore;
|
|
using ServerBase;
|
|
using ServerCommon;
|
|
using ServerCommon.BusinessLogDomain;
|
|
|
|
namespace BrokerApiCore;
|
|
public class UserAuthService
|
|
{
|
|
private readonly PlanetUserEntity m_planet_user_entity;
|
|
private readonly SsoAccountRepo m_sso_account_repo;
|
|
private readonly IServerLogic m_server_logic;
|
|
|
|
public string AccountId
|
|
=> m_planet_user_entity.getEntityAttributeNotNull<AccountAttribute>().AccountId;
|
|
|
|
// public string Email { get; set; } = string.Empty;
|
|
public string UserGuid
|
|
=> m_planet_user_entity.getEntityAttributeNotNull<AccountAttribute>().UserGuid;
|
|
|
|
public string Nickname
|
|
=> m_planet_user_entity.getEntityAttributeNotNull<NicknameAttribute>().Nickname;
|
|
|
|
public IServerLogic ServerLogic => m_server_logic;
|
|
|
|
public PlanetUserEntity PlanetUserEntity => m_planet_user_entity;
|
|
|
|
private ServerConfigMetaverseBroker? getServerConfig()
|
|
{
|
|
return m_server_logic.getServerConfig() as ServerConfigMetaverseBroker;
|
|
}
|
|
|
|
public UserAuthService(SsoAccountRepo ssoAccountRepo, IServerLogic serverLogic)
|
|
{
|
|
m_sso_account_repo = ssoAccountRepo;
|
|
m_server_logic = serverLogic;
|
|
m_planet_user_entity = new PlanetUserEntity(serverLogic);
|
|
m_planet_user_entity.onInit().Wait();
|
|
}
|
|
|
|
public async Task<Result> authByWebPortalToken(string webPortalToken, string? planetId = null)
|
|
{
|
|
if (planetId is not null)
|
|
{
|
|
m_planet_user_entity.setPlanetId(planetId);
|
|
}
|
|
|
|
var m_sso_jwt_secret_key = getServerConfig()?.SsoAccountAuthJwtSecretKey ?? string.Empty;
|
|
Guard.Against.isNullOrEmptyOrWhiteSpace(m_sso_jwt_secret_key, ServerErrorCode.InternalServerError,
|
|
()=>"SSO JWT secret key is required in server config");
|
|
|
|
var jwt_result = verifySsoAccountAuthJwt(webPortalToken,
|
|
m_sso_jwt_secret_key,
|
|
out var account_id, out var account_type, out var access_token);
|
|
if (jwt_result.isFail())
|
|
{
|
|
var error_msg = $"Broker Api Failed to Auth From Jwt !!! : {jwt_result.toBasicString()}, {webPortalToken}";
|
|
Log.getLogger().error(error_msg);
|
|
return jwt_result;
|
|
}
|
|
|
|
var result = await authByAccount(account_id);
|
|
if (result.isSuccess())
|
|
{
|
|
if (planetId is not null)
|
|
{
|
|
// BrokerBusinessLogger.collectLog(m_planet_user_entity, LogActionType.BrokerApiUserLogin, new UserAuthLogInfo
|
|
// {
|
|
// AccountId = account_id,
|
|
// UserGuid = UserGuid,
|
|
// Nickname = Nickname,
|
|
// });
|
|
|
|
BusinessLogger.collectLog(m_planet_user_entity,
|
|
new PlanetUserAuthBusinessLog(
|
|
new PlanetUserAuthLogData { AccountId = account_id, UserGuid = UserGuid, Nickname = Nickname, },
|
|
LogActionType.BrokerApiUserLogin));
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> authFromEmail(string email)
|
|
{
|
|
var (result, sso_account) = await m_sso_account_repo.findOneByEmail(email);
|
|
Guard.Against.resultFail(result);
|
|
Guard.Against.isNull(sso_account, ServerErrorCode.AccountNotFound, ()=>"sso account not found");
|
|
|
|
result = await authByAccount(sso_account.Id.ToString());
|
|
Guard.Against.resultFail(result);
|
|
Guard.Against.isNull(sso_account, ServerErrorCode.UserNotFound, ()=>"user not found");
|
|
return result;
|
|
}
|
|
|
|
// todo: JwtParser를 사용해서 수정할 것
|
|
private Result verifySsoAccountAuthJwt(string ssoJwt
|
|
, string ssoJwtSecret
|
|
, out string id, out AccountType accountType, out UInt64 accessToken)
|
|
{
|
|
id = string.Empty;
|
|
accountType = AccountType.None;
|
|
accessToken = 0;
|
|
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
try
|
|
{
|
|
var token_handler = new JwtSecurityTokenHandler();
|
|
var validation_parameters = getValidationUserTokenParameters(ssoJwtSecret);
|
|
|
|
var claim = token_handler.ValidateToken(ssoJwt, validation_parameters, out var validated_token);
|
|
// account id
|
|
id = claim.Claims.FirstOrDefault(x => x.Type == "id")?.Value ?? string.Empty;
|
|
// account type
|
|
accountType = claim.Claims.FirstOrDefault(x => x.Type == "accountType")?.Value
|
|
?.convertEnumTypeAndValueStringToEnum(AccountType.None) ?? AccountType.None;
|
|
// access token
|
|
var access_token_string = claim.Claims.FirstOrDefault(x => x.Type == "accessToken")?.Value;
|
|
accessToken = Convert.ToUInt64(access_token_string);
|
|
}
|
|
catch (SecurityTokenExpiredException e)
|
|
{
|
|
err_msg = $"Expired WebAuthJWT !!! : SecurityTokenExpiredException:{e}";
|
|
result.setFail(ServerErrorCode.ExpiredUserJwt, err_msg);
|
|
}
|
|
catch (SecurityTokenException e)
|
|
{
|
|
err_msg = $"Failed to verify WebAuthJWT !!! : SecurityTokenException:{e}";
|
|
result.setFail(ServerErrorCode.InvalidUserJwt, err_msg);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
err_msg = $"Exception !!!, WebAuthJWT !!! : Exception:{e}";
|
|
result.setFail(ServerErrorCode.InvalidUserJwt, err_msg);
|
|
}
|
|
|
|
if (result.isFail())
|
|
{
|
|
result = verifyForTestUserToken(ssoJwt, ssoJwtSecret, out id, out accountType, out accessToken);
|
|
}
|
|
|
|
Guard.Against.resultFail(result);
|
|
return result;
|
|
}
|
|
|
|
// 치트를 허용하도록 처리함
|
|
private Result verifyForTestUserToken(string ssoJwt
|
|
, string ssoJwtSecret
|
|
, out string id, out AccountType accountType, out UInt64 accessToken)
|
|
{
|
|
var splits = ssoJwt.Split('|');
|
|
if (splits.Length < 1 || splits[1] != ssoJwtSecret)
|
|
{
|
|
id = string.Empty;
|
|
accountType = AccountType.None;
|
|
accessToken = 0;
|
|
return new Result
|
|
{
|
|
ErrorCode = ServerErrorCode.InvalidUserJwt, ResultString = "Failed to verify WebAuthJWT"
|
|
};
|
|
}
|
|
|
|
id = splits[0];
|
|
accountType = AccountType.None;
|
|
try
|
|
{
|
|
accessToken = Convert.ToUInt64(id);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
accessToken = 0;
|
|
}
|
|
|
|
return new Result();
|
|
}
|
|
|
|
private static TokenValidationParameters getValidationUserTokenParameters(string sdsoAccountAuthJwtSecretKey)
|
|
{
|
|
return new TokenValidationParameters()
|
|
{
|
|
ValidateLifetime = true,
|
|
ValidateAudience = false,
|
|
ValidateIssuer = false,
|
|
ValidIssuer = "",
|
|
ValidAudience = "",
|
|
IssuerSigningKey =
|
|
new SymmetricSecurityKey(
|
|
Encoding.UTF8.GetBytes(
|
|
sdsoAccountAuthJwtSecretKey))
|
|
};
|
|
}
|
|
|
|
public async Task<Result> authByAccount(string accountId)
|
|
{
|
|
var action = m_planet_user_entity.getEntityActionNotNull<UserAuthAction>();
|
|
return await action.findAndSetAllAttributeByAccountId(accountId);
|
|
}
|
|
}
|