✨ New authorized device
This commit is contained in:
@@ -75,6 +75,7 @@ public class DysonTokenAuthHandler(
|
||||
session = await database.AuthSessions
|
||||
.Where(e => e.Id == sessionId)
|
||||
.Include(e => e.Challenge)
|
||||
.ThenInclude(e => e.Client)
|
||||
.Include(e => e.Account)
|
||||
.ThenInclude(e => e.Profile)
|
||||
.FirstOrDefaultAsync();
|
||||
|
@@ -23,7 +23,7 @@ public class AuthController(
|
||||
|
||||
public class ChallengeRequest
|
||||
{
|
||||
[Required] public ChallengePlatform Platform { get; set; }
|
||||
[Required] public ClientPlatform Platform { get; set; }
|
||||
[Required] [MaxLength(256)] public string Account { get; set; } = null!;
|
||||
[Required] [MaxLength(512)] public string DeviceId { get; set; } = null!;
|
||||
public List<string> Audiences { get; set; } = new();
|
||||
@@ -57,12 +57,11 @@ public class AuthController(
|
||||
.FirstOrDefaultAsync();
|
||||
if (existingChallenge is not null) return existingChallenge;
|
||||
|
||||
var device = await auth.GetOrCreateDeviceAsync(account.Id, request.DeviceId);
|
||||
var device = await auth.GetOrCreateDeviceAsync(account.Id, request.DeviceId, request.Platform);
|
||||
var challenge = new AuthChallenge
|
||||
{
|
||||
ExpiredAt = Instant.FromDateTimeUtc(DateTime.UtcNow.AddHours(1)),
|
||||
StepTotal = await auth.DetectChallengeRisk(Request, account),
|
||||
Platform = request.Platform,
|
||||
Audiences = request.Audiences,
|
||||
Scopes = request.Scopes,
|
||||
IpAddress = ipAddress,
|
||||
|
@@ -73,7 +73,8 @@ public class AuthService(
|
||||
return totalRequiredSteps;
|
||||
}
|
||||
|
||||
public async Task<AuthSession> CreateSessionForOidcAsync(Account.Account account, Instant time, Guid? customAppId = null)
|
||||
public async Task<AuthSession> CreateSessionForOidcAsync(Account.Account account, Instant time,
|
||||
Guid? customAppId = null)
|
||||
{
|
||||
var challenge = new AuthChallenge
|
||||
{
|
||||
@@ -101,12 +102,17 @@ public class AuthService(
|
||||
return session;
|
||||
}
|
||||
|
||||
public async Task<AuthClient> GetOrCreateDeviceAsync(Guid accountId, string deviceId)
|
||||
public async Task<AuthClient> GetOrCreateDeviceAsync(
|
||||
Guid accountId,
|
||||
string deviceId,
|
||||
ClientPlatform platform = ClientPlatform.Unidentified
|
||||
)
|
||||
{
|
||||
var device = await db.AuthClients.FirstOrDefaultAsync(d => d.DeviceId == deviceId && d.AccountId == accountId);
|
||||
if (device is not null) return device;
|
||||
device = new AuthClient
|
||||
{
|
||||
Platform = platform,
|
||||
DeviceId = deviceId,
|
||||
AccountId = accountId
|
||||
};
|
||||
@@ -316,4 +322,4 @@ public class AuthService(
|
||||
|
||||
return Convert.FromBase64String(padded);
|
||||
}
|
||||
}
|
||||
}
|
@@ -30,6 +30,7 @@ public class AuthServiceGrpc(
|
||||
session = await db.AuthSessions
|
||||
.AsNoTracking()
|
||||
.Include(e => e.Challenge)
|
||||
.ThenInclude(e => e.Client)
|
||||
.Include(e => e.Account)
|
||||
.ThenInclude(e => e.Profile)
|
||||
.FirstOrDefaultAsync(s => s.Id == sessionId);
|
||||
|
@@ -43,7 +43,7 @@ public enum ChallengeType
|
||||
Oidc // Trying to connect other platforms
|
||||
}
|
||||
|
||||
public enum ChallengePlatform
|
||||
public enum ClientPlatform
|
||||
{
|
||||
Unidentified,
|
||||
Web,
|
||||
@@ -61,7 +61,6 @@ public class AuthChallenge : ModelBase
|
||||
public int StepRemain { get; set; }
|
||||
public int StepTotal { get; set; }
|
||||
public int FailedAttempts { get; set; }
|
||||
public ChallengePlatform Platform { get; set; } = ChallengePlatform.Unidentified;
|
||||
public ChallengeType Type { get; set; } = ChallengeType.Login;
|
||||
[Column(TypeName = "jsonb")] public List<Guid> BlacklistFactors { get; set; } = new();
|
||||
[Column(TypeName = "jsonb")] public List<string> Audiences { get; set; } = new();
|
||||
@@ -90,14 +89,13 @@ public class AuthChallenge : ModelBase
|
||||
StepRemain = StepRemain,
|
||||
StepTotal = StepTotal,
|
||||
FailedAttempts = FailedAttempts,
|
||||
Platform = (Shared.Proto.ChallengePlatform)Platform,
|
||||
Type = (Shared.Proto.ChallengeType)Type,
|
||||
BlacklistFactors = { BlacklistFactors.Select(x => x.ToString()) },
|
||||
Audiences = { Audiences },
|
||||
Scopes = { Scopes },
|
||||
IpAddress = IpAddress,
|
||||
UserAgent = UserAgent,
|
||||
DeviceId = Client.DeviceId.ToString(),
|
||||
DeviceId = Client!.DeviceId,
|
||||
Nonce = Nonce,
|
||||
AccountId = AccountId.ToString()
|
||||
};
|
||||
@@ -107,6 +105,7 @@ public class AuthChallenge : ModelBase
|
||||
public class AuthClient : ModelBase
|
||||
{
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
public ClientPlatform Platform { get; set; } = ClientPlatform.Unidentified;
|
||||
[MaxLength(1024)] public string DeviceName { get; set; } = string.Empty;
|
||||
[MaxLength(1024)] public string? DeviceLabel { get; set; }
|
||||
[MaxLength(1024)] public string DeviceId { get; set; } = string.Empty;
|
||||
@@ -114,3 +113,21 @@ public class AuthClient : ModelBase
|
||||
public Guid AccountId { get; set; }
|
||||
[JsonIgnore] public Account.Account Account { get; set; } = null!;
|
||||
}
|
||||
|
||||
public class AuthClientWithChallenge : AuthClient
|
||||
{
|
||||
public List<AuthChallenge> Challenges { get; set; } = [];
|
||||
|
||||
public static AuthClientWithChallenge FromClient(AuthClient client)
|
||||
{
|
||||
return new AuthClientWithChallenge
|
||||
{
|
||||
Id = client.Id,
|
||||
Platform = client.Platform,
|
||||
DeviceName = client.DeviceName,
|
||||
DeviceLabel = client.DeviceLabel,
|
||||
DeviceId = client.DeviceId,
|
||||
AccountId = client.AccountId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -223,7 +223,6 @@ public abstract class OidcService(
|
||||
ExpiredAt = now.Plus(Duration.FromHours(1)),
|
||||
StepTotal = await auth.DetectChallengeRisk(request.Request, account),
|
||||
Type = ChallengeType.Oidc,
|
||||
Platform = ChallengePlatform.Unidentified,
|
||||
Audiences = [ProviderName],
|
||||
Scopes = ["*"],
|
||||
AccountId = account.Id,
|
||||
|
Reference in New Issue
Block a user