Skip to content

Commit

Permalink
rollout push token fix
Browse files Browse the repository at this point in the history
  • Loading branch information
frankmer committed Sep 13, 2024
1 parent a4a36a4 commit 0f3770a
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 97 deletions.
71 changes: 40 additions & 31 deletions lib/api/token_container_api_endpoint.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,6 @@ class PrivacyideaContainerApi {
final PrivacyideaIOClient _ioClient;
const PrivacyideaContainerApi({required PrivacyideaIOClient ioClient}) : _ioClient = ioClient;

Future<ContainerChallenge?> _getChallenge(ContainerCredentialFinalized container) async {
final initResponse = await _ioClient.doGet(url: container.syncUrl, parameters: {CONTAINER_SERIAL: container.serial});
try {
Logger.debug('Received container sync challenge: ${initResponse.body}', name: 'TokenContainerApiEndpoint#sync');
final piResponse = PiServerResponse<ContainerChallenge>.fromResponse(initResponse);
if (piResponse.isError) {
Logger.error('Error while syncing container: ${piResponse.asError.resultError}', name: 'TokenContainerApiEndpoint#sync');
return null;
}
return piResponse.asSuccess.resultValue;
} catch (e, s) {
Logger.error('Error while syncing container: $e', name: 'TokenContainerApiEndpoint#sync', stackTrace: s);
return null;
}
}

// Returns a tuple of updated/new tokens and serials of deleted tokens
Future<(List<Token>, List<String>)?> sync(ContainerCredentialFinalized container, TokenState tokenState) async {
final containerTokenTemplates = tokenState.containerTokens(container.serial).toTemplates();
Expand All @@ -73,7 +57,7 @@ class PrivacyideaContainerApi {
container: container,
challenge: challenge,
otpAuthMaps: [
for (var template in [...containerTokenTemplates, ...maybePiTokensTemplates]) template.otpAuthMap
for (var template in [...containerTokenTemplates, ...maybePiTokensTemplates]) template.otpAuthMapSafeToSend
],
);
if (decryptedContainerDictJson == null) return null;
Expand Down Expand Up @@ -106,6 +90,7 @@ class PrivacyideaContainerApi {
(mergedTemplatesWithSerial, deleteSerials) = _handlePiTokens(
containerTokenTemplates: containerTokenTemplates,
serverTokensWithSerial: serverTokensWithSerial,
container: container,
);

final updatedTokens = <Token>[];
Expand Down Expand Up @@ -144,6 +129,22 @@ class PrivacyideaContainerApi {
////// PRIVATE FUNCTIONS //////
////////////////////////////// */

Future<ContainerChallenge?> _getChallenge(ContainerCredentialFinalized container) async {
final initResponse = await _ioClient.doGet(url: container.syncUrl, parameters: {CONTAINER_SERIAL: container.serial});
try {
Logger.debug('Received container sync challenge: ${initResponse.body}', name: 'TokenContainerApiEndpoint#sync');
final piResponse = PiServerResponse<ContainerChallenge>.fromResponse(initResponse);
if (piResponse.isError) {
Logger.error('Error while syncing container: ${piResponse.asError.resultError}', name: 'TokenContainerApiEndpoint#sync');
return null;
}
return piResponse.asSuccess.resultValue;
} catch (e, s) {
Logger.error('Error while syncing container: $e', name: 'TokenContainerApiEndpoint#sync', stackTrace: s);
return null;
}
}

Future<Map<String, dynamic>?> _getContainerDict({
required ContainerCredentialFinalized container,
required ContainerChallenge challenge,
Expand Down Expand Up @@ -204,6 +205,19 @@ class PrivacyideaContainerApi {
return jsonDecode(utf8.decode(decryptedContainerDict)) as Map<String, dynamic>;
}

Future<List<Token>> _parseNewTokens({required ContainerCredentialFinalized container, required List<Uri> otpAuthUris}) async {
final newTokens = <Token>[];
for (var otpAuthUri in otpAuthUris) {
Logger.debug('Processing token: $otpAuthUri');
var newToken = (await const OtpAuthProcessor().processUri(otpAuthUri)).firstOrNull?.asSuccess?.resultData;
if (newToken != null) {
newToken = container.addOriginToToken(token: newToken, tokenData: otpAuthUri.toString());
newTokens.add(newToken);
}
}
return newTokens;
}

List<TokenTemplate> _handleMaybePiTokens({
required List<TokenTemplate> maybePiTokensTemplates,
required List<Map<String, dynamic>> serverTokensWithOtps,
Expand All @@ -215,7 +229,13 @@ class PrivacyideaContainerApi {
var mergedTemplate = maybePiTokensTemplates.firstWhere(
(maybePiToken) => const IterableEquality().equals(otps, maybePiToken.otpValues),
orElse: () => TokenTemplate.withOtps(
otps: serverTokenWithOtp[OTP_AUTH_OTP_VALUES]!, otpAuthMap: serverTokenWithOtp, container: container, checkedContainers: [container.serial]),
otps: serverTokenWithOtp[OTP_AUTH_OTP_VALUES]!,
otpAuthMap: serverTokenWithOtp,
container: container,
additionalData: {
Token.CHECKED_CONTAINERS: [container.serial],
},
),
);
mergedTemplate = mergedTemplate.withOtpAuthData(serverTokenWithOtp);
mergedTemplate = mergedTemplate.copyWith(container: container);
Expand All @@ -224,22 +244,10 @@ class PrivacyideaContainerApi {
return merged;
}

Future<List<Token>> _parseNewTokens({required ContainerCredentialFinalized container, required List<Uri> otpAuthUris}) async {
final newTokens = <Token>[];
for (var otpAuthUri in otpAuthUris) {
Logger.debug('Processing token: $otpAuthUri');
var newToken = (await const OtpAuthProcessor().processUri(otpAuthUri)).firstOrNull?.asSuccess?.resultData;
if (newToken != null) {
newToken = container.addOriginToToken(token: newToken, tokenData: otpAuthUri.toString());
newTokens.add(newToken);
}
}
return newTokens;
}

(List<TokenTemplate>, List<String>) _handlePiTokens({
required List<TokenTemplate> containerTokenTemplates,
required List<Map<String, dynamic>> serverTokensWithSerial,
required ContainerCredentialFinalized container,
}) {
final deleteSerials = <String>[];
final mergedTemplatesWithSerial = <TokenTemplate>[];
Expand All @@ -250,6 +258,7 @@ class PrivacyideaContainerApi {
deleteSerials.add(containerToken.serial!);
} else {
var mergedTemplate = containerToken.withOtpAuthData(serverToken);
mergedTemplate = mergedTemplate.copyWith(container: container);
mergedTemplatesWithSerial.add(mergedTemplate);
}
}
Expand Down
6 changes: 4 additions & 2 deletions lib/model/token_template.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ class TokenTemplate with _$TokenTemplate {
ContainerCredential? container,
}) = _TokenTemplateWithSerial;

/// [ otpAuthMap ]: The map containing the OTP token data. May contain the secret.
factory TokenTemplate.withOtps({
required Map<String, dynamic> otpAuthMap,
required List<String> otps,
required List<String> checkedContainers,
@Default({}) Map<String, dynamic> additionalData,
ContainerCredential? container,
}) = _TokenTemplateWithOtps;
Expand Down Expand Up @@ -76,6 +76,8 @@ class TokenTemplate with _$TokenTemplate {
name: CONTAINER_SERIAL,
);

Map<String, dynamic> get otpAuthMapSafeToSend => Map<String, dynamic>.from(otpAuthMap)..remove(OTP_AUTH_SECRET_BASE32);

@override
operator ==(Object other) {
if (other is! TokenTemplate) return false;
Expand All @@ -98,7 +100,7 @@ class TokenTemplate with _$TokenTemplate {
if (additionalData[Token.ORIGIN] != null) {
additionalData[Token.ORIGIN] = container != null
? TokenOriginData(
appName: '${container!.serverName} ${container!.serial}',
appName: '${container!.serverName} (${container!.serial})',
data: otpAuthMap.toString(),
source: TokenOriginSourceType.container,
isPrivacyIdeaToken: true,
Expand Down
40 changes: 4 additions & 36 deletions lib/model/token_template.freezed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ mixin _$TokenTemplate {
required TResult Function(
Map<String, dynamic> otpAuthMap,
List<String> otps,
List<String> checkedContainers,
Map<String, dynamic> additionalData,
ContainerCredential? container)
withOtps,
Expand All @@ -57,7 +56,6 @@ mixin _$TokenTemplate {
TResult? Function(
Map<String, dynamic> otpAuthMap,
List<String> otps,
List<String> checkedContainers,
Map<String, dynamic> additionalData,
ContainerCredential? container)?
withOtps,
Expand All @@ -74,7 +72,6 @@ mixin _$TokenTemplate {
TResult Function(
Map<String, dynamic> otpAuthMap,
List<String> otps,
List<String> checkedContainers,
Map<String, dynamic> additionalData,
ContainerCredential? container)?
withOtps,
Expand Down Expand Up @@ -311,7 +308,6 @@ class _$TokenTemplateWithSerialImpl extends _TokenTemplateWithSerial
required TResult Function(
Map<String, dynamic> otpAuthMap,
List<String> otps,
List<String> checkedContainers,
Map<String, dynamic> additionalData,
ContainerCredential? container)
withOtps,
Expand All @@ -331,7 +327,6 @@ class _$TokenTemplateWithSerialImpl extends _TokenTemplateWithSerial
TResult? Function(
Map<String, dynamic> otpAuthMap,
List<String> otps,
List<String> checkedContainers,
Map<String, dynamic> additionalData,
ContainerCredential? container)?
withOtps,
Expand All @@ -351,7 +346,6 @@ class _$TokenTemplateWithSerialImpl extends _TokenTemplateWithSerial
TResult Function(
Map<String, dynamic> otpAuthMap,
List<String> otps,
List<String> checkedContainers,
Map<String, dynamic> additionalData,
ContainerCredential? container)?
withOtps,
Expand Down Expand Up @@ -441,7 +435,6 @@ abstract class _$$TokenTemplateWithOtpsImplCopyWith<$Res>
$Res call(
{Map<String, dynamic> otpAuthMap,
List<String> otps,
List<String> checkedContainers,
Map<String, dynamic> additionalData,
ContainerCredential? container});

Expand All @@ -464,7 +457,6 @@ class __$$TokenTemplateWithOtpsImplCopyWithImpl<$Res>
$Res call({
Object? otpAuthMap = null,
Object? otps = null,
Object? checkedContainers = null,
Object? additionalData = null,
Object? container = freezed,
}) {
Expand All @@ -477,10 +469,6 @@ class __$$TokenTemplateWithOtpsImplCopyWithImpl<$Res>
? _value._otps
: otps // ignore: cast_nullable_to_non_nullable
as List<String>,
checkedContainers: null == checkedContainers
? _value._checkedContainers
: checkedContainers // ignore: cast_nullable_to_non_nullable
as List<String>,
additionalData: null == additionalData
? _value._additionalData
: additionalData // ignore: cast_nullable_to_non_nullable
Expand All @@ -500,13 +488,11 @@ class _$TokenTemplateWithOtpsImpl extends _TokenTemplateWithOtps
_$TokenTemplateWithOtpsImpl(
{required final Map<String, dynamic> otpAuthMap,
required final List<String> otps,
required final List<String> checkedContainers,
final Map<String, dynamic> additionalData = const {},
this.container,
final String? $type})
: _otpAuthMap = otpAuthMap,
_otps = otps,
_checkedContainers = checkedContainers,
_additionalData = additionalData,
$type = $type ?? 'withOtps',
super._();
Expand All @@ -530,15 +516,6 @@ class _$TokenTemplateWithOtpsImpl extends _TokenTemplateWithOtps
return EqualUnmodifiableListView(_otps);
}

final List<String> _checkedContainers;
@override
List<String> get checkedContainers {
if (_checkedContainers is EqualUnmodifiableListView)
return _checkedContainers;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_checkedContainers);
}

final Map<String, dynamic> _additionalData;
@override
@JsonKey()
Expand All @@ -556,7 +533,7 @@ class _$TokenTemplateWithOtpsImpl extends _TokenTemplateWithOtps

@override
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
return 'TokenTemplate.withOtps(otpAuthMap: $otpAuthMap, otps: $otps, checkedContainers: $checkedContainers, additionalData: $additionalData, container: $container)';
return 'TokenTemplate.withOtps(otpAuthMap: $otpAuthMap, otps: $otps, additionalData: $additionalData, container: $container)';
}

@override
Expand All @@ -566,7 +543,6 @@ class _$TokenTemplateWithOtpsImpl extends _TokenTemplateWithOtps
..add(DiagnosticsProperty('type', 'TokenTemplate.withOtps'))
..add(DiagnosticsProperty('otpAuthMap', otpAuthMap))
..add(DiagnosticsProperty('otps', otps))
..add(DiagnosticsProperty('checkedContainers', checkedContainers))
..add(DiagnosticsProperty('additionalData', additionalData))
..add(DiagnosticsProperty('container', container));
}
Expand All @@ -589,13 +565,11 @@ class _$TokenTemplateWithOtpsImpl extends _TokenTemplateWithOtps
required TResult Function(
Map<String, dynamic> otpAuthMap,
List<String> otps,
List<String> checkedContainers,
Map<String, dynamic> additionalData,
ContainerCredential? container)
withOtps,
}) {
return withOtps(
otpAuthMap, otps, checkedContainers, additionalData, container);
return withOtps(otpAuthMap, otps, additionalData, container);
}

@override
Expand All @@ -610,13 +584,11 @@ class _$TokenTemplateWithOtpsImpl extends _TokenTemplateWithOtps
TResult? Function(
Map<String, dynamic> otpAuthMap,
List<String> otps,
List<String> checkedContainers,
Map<String, dynamic> additionalData,
ContainerCredential? container)?
withOtps,
}) {
return withOtps?.call(
otpAuthMap, otps, checkedContainers, additionalData, container);
return withOtps?.call(otpAuthMap, otps, additionalData, container);
}

@override
Expand All @@ -631,15 +603,13 @@ class _$TokenTemplateWithOtpsImpl extends _TokenTemplateWithOtps
TResult Function(
Map<String, dynamic> otpAuthMap,
List<String> otps,
List<String> checkedContainers,
Map<String, dynamic> additionalData,
ContainerCredential? container)?
withOtps,
required TResult orElse(),
}) {
if (withOtps != null) {
return withOtps(
otpAuthMap, otps, checkedContainers, additionalData, container);
return withOtps(otpAuthMap, otps, additionalData, container);
}
return orElse();
}
Expand Down Expand Up @@ -687,7 +657,6 @@ abstract class _TokenTemplateWithOtps extends TokenTemplate {
factory _TokenTemplateWithOtps(
{required final Map<String, dynamic> otpAuthMap,
required final List<String> otps,
required final List<String> checkedContainers,
final Map<String, dynamic> additionalData,
final ContainerCredential? container}) = _$TokenTemplateWithOtpsImpl;
_TokenTemplateWithOtps._() : super._();
Expand All @@ -698,7 +667,6 @@ abstract class _TokenTemplateWithOtps extends TokenTemplate {
@override
Map<String, dynamic> get otpAuthMap;
List<String> get otps;
List<String> get checkedContainers;
@override
Map<String, dynamic> get additionalData;
@override
Expand Down
4 changes: 0 additions & 4 deletions lib/model/token_template.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions lib/model/tokens/otp_token.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ abstract class OTPToken extends Token {

@override
bool isSameTokenAs(Token other) {
return super.isSameTokenAs(other) && other is OTPToken && other.algorithm == algorithm && other.digits == digits && other.secret == secret;
return super.isSameTokenAs(other) || (other is OTPToken && other.secret == secret);
}

@override
Expand Down Expand Up @@ -136,7 +136,6 @@ abstract class OTPToken extends Token {
otpAuthMap: toOtpAuthMap(),
otps: [otpValue, nextValue],
container: container,
checkedContainers: checkedContainers,
additionalData: additionalData,
);
}
9 changes: 1 addition & 8 deletions lib/model/tokens/push_token.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,7 @@ class PushToken extends Token {
}

@override
bool isSameTokenAs(Token other) {
return super.isSameTokenAs(other) &&
other is PushToken &&
other.serial == serial &&
other.privateTokenKey == privateTokenKey &&
other.publicTokenKey == publicTokenKey &&
other.publicServerKey == publicServerKey;
}
bool isSameTokenAs(Token other) => super.isSameTokenAs(other) || (other is PushToken && other.serial == serial);

@override
PushToken copyWith({
Expand Down
Loading

0 comments on commit 0f3770a

Please sign in to comment.