Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions services/celest_cloud_auth/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.3.2

- fix: Properly set/check session duration

## 0.3.1

- fix: Allow dashes in routes
Expand Down

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions services/celest_cloud_auth/lib/celest_cloud_auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ final class CelestCloudAuth {
issuer: context.rootEntity,
routeMap: routeMap,
corks: corks,
cryptoKeys: cryptoKeys,
users: users,
db: db,
authorizer: authorizer,
);
Expand Down Expand Up @@ -162,6 +164,8 @@ final class CelestCloudAuth {
routeMap: routeMap,
authorizer: authorizer,
corks: corks,
cryptoKeys: cryptoKeys,
users: users,
db: db,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,13 @@ final class SessionStateSuccess extends SessionState {

factory SessionStateSuccess.fromProto(pb.AuthenticationSuccess success) {
return SessionStateSuccess(
cork: Cork.parse(success.identityToken),
cork: CedarCork.parse(success.identityToken),
user: success.user.toModel(),
isNewUser: success.isNewUser,
);
}

final Cork cork;
final CedarCork cork;
String get identityToken => cork.toString();

final User user;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:celest_ast/celest_ast.dart';
import 'package:celest_cloud/src/proto.dart' as pb;
import 'package:celest_cloud_auth/src/authorization/authorization_middleware.dart';
import 'package:celest_cloud_auth/src/authorization/authorizer.dart';
import 'package:celest_cloud_auth/src/authorization/celest_role.dart';
import 'package:celest_cloud_auth/src/authorization/corks_repository.dart';
import 'package:celest_cloud_auth/src/context.dart';
import 'package:celest_cloud_auth/src/crypto/crypto_key_repository.dart';
Expand All @@ -16,6 +17,7 @@ import 'package:celest_cloud_auth/src/sessions/sessions_repository.dart';
import 'package:celest_cloud_auth/src/users/users_repository.dart';
import 'package:celest_cloud_auth/src/util/typeid.dart';
import 'package:celest_core/celest_core.dart';
import 'package:clock/clock.dart';
import 'package:corks_cedar/corks_cedar.dart';
import 'package:meta/meta.dart';
import 'package:shelf/shelf.dart';
Expand Down Expand Up @@ -137,6 +139,8 @@ extension type AuthenticationService._(_Deps _deps) implements Object {
final requestAuthorizer = AuthorizationMiddleware(
routeMap: _deps.routeMap,
corks: _deps.corks,
cryptoKeys: _deps.cryptoKeys,
users: _deps.users,
db: _deps.db,
authorizer: _deps.authorizer,
issuer: _deps.issuer,
Expand Down Expand Up @@ -275,19 +279,19 @@ extension type AuthenticationService._(_Deps _deps) implements Object {
throw InternalServerError('Unknown user: ${session.userId}');
}

final isNewUser = user.roles.contains(
const EntityUid.of('Celest::Role', 'anonymous'),
);
final isNewUser = user.roles.contains(CelestRole.anonymous);
if (isNewUser) {
user = await _users.updateUser(
userId: session.userId,
factor: factor,
roles: const [EntityUid.of('Celest::Role', 'authenticated')],
roles: const [CelestRole.authenticated],
);
}
final cork = await _corks.createCork(
session: session.copyWith(
expireTime: clock.now().add(SessionsRepository.postAuthSessionDuration),
),
user: user,
session: session,
);
return SessionStateSuccess(
cork: cork,
Expand Down Expand Up @@ -317,7 +321,7 @@ extension type AuthenticationService._(_Deps _deps) implements Object {
'Failed to send OTP. Please restart the authentication flow.',
);
}
final resendIn = nextResend.difference(DateTime.timestamp());
final resendIn = nextResend.difference(clock.now());
throw ResourceExhaustedException(
'Failed to send OTP. Try again in ${resendIn.inSeconds} seconds',
);
Expand All @@ -334,7 +338,7 @@ extension type AuthenticationService._(_Deps _deps) implements Object {
// 'Failed to send OTP. Please restart the authentication flow.',
// );
// }
// final resendIn = nextResend.difference(DateTime.timestamp());
// final resendIn = nextResend.difference(clock.now());
// throw ResourceExhaustedException(
// 'Failed to send OTP. Try again in ${resendIn.inSeconds} seconds',
// );
Expand All @@ -358,7 +362,7 @@ extension type AuthenticationService._(_Deps _deps) implements Object {
SessionStatePendingConfirmation? confirmation,
AuthenticationFactor? resend,
}) async {
var session = await _db.cloudAuthCoreDrift
final session = await _db.cloudAuthCoreDrift
.getSession(sessionId: sessionId.encoded)
.getSingleOrNull();
if (session == null) {
Expand Down Expand Up @@ -386,11 +390,14 @@ extension type AuthenticationService._(_Deps _deps) implements Object {
null => throw StateError('Unexpected state'),
};

session = await _sessions.updateSession(
return _sessions.updateSession(
session: session,
state: updatedState,
sessionDuration: switch (updatedState) {
SessionStateSuccess() => SessionsRepository.postAuthSessionDuration,
_ => SessionsRepository.preAuthSessionDuration,
},
);
return session.copyWith(sessionToken: sessionToken);
}

Future<Response> handleContinueSession(Request request) async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ import 'package:celest/http.dart';
import 'package:celest_cloud_auth/src/authorization/authorizer.dart';
import 'package:celest_cloud_auth/src/authorization/corks_repository.dart';
import 'package:celest_cloud_auth/src/context.dart';
import 'package:celest_cloud_auth/src/crypto/crypto_key_repository.dart';
import 'package:celest_cloud_auth/src/database/auth_database_accessors.dart';
import 'package:celest_cloud_auth/src/http/http_helpers.dart';
import 'package:celest_cloud_auth/src/model/interop.dart';
import 'package:celest_cloud_auth/src/model/route_map.dart';
import 'package:celest_cloud_auth/src/sessions/sessions_repository.dart';
import 'package:celest_cloud_auth/src/users/users_repository.dart';
import 'package:celest_cloud_auth/src/util/typeid.dart';
import 'package:celest_core/celest_core.dart' as core;
import 'package:celest_core/celest_core.dart';
import 'package:collection/collection.dart';
Expand All @@ -17,6 +21,8 @@ import 'package:shelf/shelf.dart' show Handler, Request;
typedef _Deps = ({
RouteMap routeMap,
CorksRepository corks,
CryptoKeyRepository cryptoKeys,
UsersRepository users,
CloudAuthDatabaseMixin db,
Authorizer authorizer,
EntityUid issuer,
Expand All @@ -30,13 +36,17 @@ extension type AuthorizationMiddleware._(_Deps _deps) implements Object {
AuthorizationMiddleware({
required RouteMap routeMap,
required CorksRepository corks,
required CryptoKeyRepository cryptoKeys,
required UsersRepository users,
required CloudAuthDatabaseMixin db,
required Authorizer authorizer,
required EntityUid issuer,
}) : this._(
(
routeMap: routeMap,
corks: corks,
cryptoKeys: cryptoKeys,
users: users,
db: db,
authorizer: authorizer,
issuer: issuer,
Expand All @@ -47,6 +57,12 @@ extension type AuthorizationMiddleware._(_Deps _deps) implements Object {
CorksRepository get _corks => _deps.corks;
CloudAuthDatabaseAccessors get _db => _deps.db.cloudAuth;
Authorizer get _authorizer => _deps.authorizer;
SessionsRepository get _sessions => SessionsRepository(
corks: _corks,
db: _deps.db,
cryptoKeys: _deps.cryptoKeys,
users: _deps.users,
);

Handler call(Handler inner) {
return (request) async {
Expand Down Expand Up @@ -129,13 +145,20 @@ extension type AuthorizationMiddleware._(_Deps _deps) implements Object {
context.put(contextKeyCork, cork);
switch (cork.bearer) {
case EntityUid(type: 'Celest::Session', id: final sessionId):
final session = await _db.getSession(sessionId: sessionId);
final sessionTid = TypeId.tryDecode<Session>(sessionId);
if (sessionTid == null) {
context.logger.severe('Invalid session ID: $sessionId');
throw const UnauthorizedException('Invalid session ID');
}
final session = await _sessions.getSession(
sessionId: sessionTid,
);
if (session == null) {
throw const UnauthorizedException('Invalid session');
throw UnauthorizedException('Invalid session: $sessionId');
}
final user = await _db.getUser(userId: session.userId);
if (user == null) {
throw const UnauthorizedException('Invalid user');
throw UnauthorizedException('Invalid user: ${session.userId}');
}
context.logger.finest('Found user for cork: $user');
return (user, user.toEntity());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:celest_cloud_auth/src/database/schema/cloud_auth_core.drift.dart
as drift;
import 'package:celest_cloud_auth/src/model/interop.dart';
import 'package:celest_core/celest_core.dart';
import 'package:clock/clock.dart';
import 'package:corks_cedar/corks_cedar.dart';
import 'package:drift/drift.dart' as drift;

Expand Down Expand Up @@ -41,7 +42,7 @@ extension type CorksRepository._(_Dependencies _deps) implements Object {
}

/// Creates a new cork for the given [user].
Future<Cork> createCork({
Future<CedarCork> createCork({
required Session session,
required User user,
EntityUid? audience,
Expand Down Expand Up @@ -88,7 +89,7 @@ extension type CorksRepository._(_Dependencies _deps) implements Object {
expireTime: expireTime,
);
});
return cork;
return CedarCork(cork);
}

/// Verifies the given [cork].
Expand All @@ -115,7 +116,7 @@ extension type CorksRepository._(_Dependencies _deps) implements Object {
..where((tbl) => tbl.corkId.equals(cork.id));
await query.write(
drift.CloudAuthCorksCompanion(
lastUseTime: drift.Value(DateTime.timestamp()),
lastUseTime: drift.Value(clock.now()),
),
);
} on Object catch (e, st) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class CloudAuthDatabase extends $CloudAuthDatabase with CloudAuthDatabaseMixin {
final ResolvedProject? _project;

@override
int get schemaVersion => 4;
int get schemaVersion => 5;

@override
MigrationStrategy get migration {
Expand Down
Loading