♻️ Updated auth challenges and device API to fit new design
This commit is contained in:
@@ -560,7 +560,7 @@ public class AccountCurrentController(
|
|||||||
|
|
||||||
[HttpGet("devices")]
|
[HttpGet("devices")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public async Task<ActionResult<List<SnAuthClientWithChallenge>>> GetDevices()
|
public async Task<ActionResult<List<SnAuthClientWithSessions>>> GetDevices()
|
||||||
{
|
{
|
||||||
if (HttpContext.Items["CurrentUser"] is not SnAccount currentUser ||
|
if (HttpContext.Items["CurrentUser"] is not SnAccount currentUser ||
|
||||||
HttpContext.Items["CurrentSession"] is not SnAuthSession currentSession) return Unauthorized();
|
HttpContext.Items["CurrentSession"] is not SnAuthSession currentSession) return Unauthorized();
|
||||||
@@ -571,18 +571,41 @@ public class AccountCurrentController(
|
|||||||
.Where(device => device.AccountId == currentUser.Id)
|
.Where(device => device.AccountId == currentUser.Id)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var challengeDevices = devices.Select(SnAuthClientWithChallenge.FromClient).ToList();
|
var sessionDevices = devices.Select(SnAuthClientWithSessions.FromClient).ToList();
|
||||||
var deviceIds = challengeDevices.Select(x => x.DeviceId).ToList();
|
var clientIds = sessionDevices.Select(x => x.Id).ToList();
|
||||||
|
|
||||||
var authChallenges = await db.AuthChallenges
|
var authSessions = await db.AuthSessions
|
||||||
.Where(c => deviceIds.Contains(c.DeviceId))
|
.Where(c => clientIds.Contains(c.Id))
|
||||||
.GroupBy(c => c.DeviceId)
|
.GroupBy(c => c.Id)
|
||||||
.ToDictionaryAsync(c => c.Key, c => c.ToList());
|
.ToDictionaryAsync(c => c.Key, c => c.ToList());
|
||||||
foreach (var challengeDevice in challengeDevices)
|
foreach (var dev in sessionDevices)
|
||||||
if (authChallenges.TryGetValue(challengeDevice.DeviceId, out var challenge))
|
if (authSessions.TryGetValue(dev.Id, out var challenge))
|
||||||
challengeDevice.Challenges = challenge;
|
dev.Sessions = challenge;
|
||||||
|
|
||||||
return Ok(challengeDevices);
|
return Ok(sessionDevices);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("challenges")]
|
||||||
|
[Authorize]
|
||||||
|
public async Task<ActionResult<List<SnAuthChallenge>>> GetChallenges(
|
||||||
|
[FromQuery] int take = 20,
|
||||||
|
[FromQuery] int offset = 0
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (HttpContext.Items["CurrentUser"] is not SnAccount currentUser) return Unauthorized();
|
||||||
|
|
||||||
|
var query = db.AuthChallenges
|
||||||
|
.Where(challenge => challenge.AccountId == currentUser.Id)
|
||||||
|
.OrderByDescending(c => c.CreatedAt);
|
||||||
|
|
||||||
|
var total = await query.CountAsync();
|
||||||
|
Response.Headers.Append("X-Total", total.ToString());
|
||||||
|
|
||||||
|
var challenges = await query
|
||||||
|
.Skip(offset)
|
||||||
|
.Take(take)
|
||||||
|
.ToListAsync();
|
||||||
|
return Ok(challenges);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("sessions")]
|
[HttpGet("sessions")]
|
||||||
@@ -596,6 +619,7 @@ public class AccountCurrentController(
|
|||||||
HttpContext.Items["CurrentSession"] is not SnAuthSession currentSession) return Unauthorized();
|
HttpContext.Items["CurrentSession"] is not SnAuthSession currentSession) return Unauthorized();
|
||||||
|
|
||||||
var query = db.AuthSessions
|
var query = db.AuthSessions
|
||||||
|
.OrderByDescending(x => x.LastGrantedAt)
|
||||||
.Include(session => session.Account)
|
.Include(session => session.Account)
|
||||||
.Where(session => session.Account.Id == currentUser.Id);
|
.Where(session => session.Account.Id == currentUser.Id);
|
||||||
|
|
||||||
@@ -604,7 +628,6 @@ public class AccountCurrentController(
|
|||||||
Response.Headers.Append("X-Auth-Session", currentSession.Id.ToString());
|
Response.Headers.Append("X-Auth-Session", currentSession.Id.ToString());
|
||||||
|
|
||||||
var sessions = await query
|
var sessions = await query
|
||||||
.OrderByDescending(x => x.LastGrantedAt)
|
|
||||||
.Skip(offset)
|
.Skip(offset)
|
||||||
.Take(take)
|
.Take(take)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
@@ -933,4 +956,4 @@ public class AccountCurrentController(
|
|||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
return Ok(records);
|
return Ok(records);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,8 @@ public class AuthService(
|
|||||||
.Take(10)
|
.Take(10)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var recentChallengeIds = recentSessions.Where(s => s.ChallengeId != null).Select(s => s.ChallengeId.Value).ToList();
|
var recentChallengeIds =
|
||||||
|
recentSessions.Where(s => s.ChallengeId != null).Select(s => s.ChallengeId.Value).ToList();
|
||||||
var recentChallenges = await db.AuthChallenges.Where(c => recentChallengeIds.Contains(c.Id)).ToListAsync();
|
var recentChallenges = await db.AuthChallenges.Where(c => recentChallengeIds.Contains(c.Id)).ToListAsync();
|
||||||
|
|
||||||
var ipAddress = request.HttpContext.Connection.RemoteIpAddress?.ToString();
|
var ipAddress = request.HttpContext.Connection.RemoteIpAddress?.ToString();
|
||||||
@@ -192,7 +193,7 @@ public class AuthService(
|
|||||||
CreatedAt = time,
|
CreatedAt = time,
|
||||||
LastGrantedAt = time,
|
LastGrantedAt = time,
|
||||||
IpAddress = HttpContext.Connection.RemoteIpAddress?.ToString(),
|
IpAddress = HttpContext.Connection.RemoteIpAddress?.ToString(),
|
||||||
UserAgent = HttpContext.Request.Headers.UserAgent,
|
UserAgent = HttpContext.Request.Headers.UserAgent,
|
||||||
AppId = customAppId,
|
AppId = customAppId,
|
||||||
ParentSessionId = parentSession?.Id,
|
ParentSessionId = parentSession?.Id,
|
||||||
Type = customAppId is not null ? SessionType.OAuth : SessionType.Oidc,
|
Type = customAppId is not null ? SessionType.OAuth : SessionType.Oidc,
|
||||||
@@ -409,8 +410,12 @@ public class AuthService(
|
|||||||
if (challenge.StepRemain != 0)
|
if (challenge.StepRemain != 0)
|
||||||
throw new ArgumentException("Challenge not yet completed.");
|
throw new ArgumentException("Challenge not yet completed.");
|
||||||
|
|
||||||
var device = await GetOrCreateDeviceAsync(challenge.AccountId, challenge.DeviceId, challenge.DeviceName,
|
var device = await GetOrCreateDeviceAsync(
|
||||||
challenge.Platform);
|
challenge.AccountId,
|
||||||
|
challenge.DeviceId,
|
||||||
|
challenge.DeviceName,
|
||||||
|
challenge.Platform
|
||||||
|
);
|
||||||
|
|
||||||
var now = SystemClock.Instance.GetCurrentInstant();
|
var now = SystemClock.Instance.GetCurrentInstant();
|
||||||
var session = new SnAuthSession
|
var session = new SnAuthSession
|
||||||
@@ -421,7 +426,7 @@ public class AuthService(
|
|||||||
IpAddress = challenge.IpAddress,
|
IpAddress = challenge.IpAddress,
|
||||||
UserAgent = challenge.UserAgent,
|
UserAgent = challenge.UserAgent,
|
||||||
Scopes = challenge.Scopes,
|
Scopes = challenge.Scopes,
|
||||||
Audiences = challenge.Audiences,
|
Audiences = challenge.Audiences,
|
||||||
ChallengeId = challenge.Id,
|
ChallengeId = challenge.Id,
|
||||||
ClientId = device.Id,
|
ClientId = device.Id,
|
||||||
};
|
};
|
||||||
@@ -537,7 +542,8 @@ public class AuthService(
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<SnApiKey> CreateApiKey(Guid accountId, string label, Instant? expiredAt = null, SnAuthSession? parentSession = null)
|
public async Task<SnApiKey> CreateApiKey(Guid accountId, string label, Instant? expiredAt = null,
|
||||||
|
SnAuthSession? parentSession = null)
|
||||||
{
|
{
|
||||||
var key = new SnApiKey
|
var key = new SnApiKey
|
||||||
{
|
{
|
||||||
@@ -689,4 +695,4 @@ public class AuthService(
|
|||||||
|
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,13 +153,13 @@ public class SnAuthClient : ModelBase
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SnAuthClientWithChallenge : SnAuthClient
|
public class SnAuthClientWithSessions : SnAuthClient
|
||||||
{
|
{
|
||||||
public List<SnAuthChallenge> Challenges { get; set; } = [];
|
public List<SnAuthSession> Sessions { get; set; } = [];
|
||||||
|
|
||||||
public static SnAuthClientWithChallenge FromClient(SnAuthClient client)
|
public static SnAuthClientWithSessions FromClient(SnAuthClient client)
|
||||||
{
|
{
|
||||||
return new SnAuthClientWithChallenge
|
return new SnAuthClientWithSessions
|
||||||
{
|
{
|
||||||
Id = client.Id,
|
Id = client.Id,
|
||||||
Platform = client.Platform,
|
Platform = client.Platform,
|
||||||
|
|||||||
Reference in New Issue
Block a user