From 4fe8af2e6681a7aa741e55beee71ae83f670428c Mon Sep 17 00:00:00 2001 From: Armand <4831c0@proton.me> Date: Mon, 15 Sep 2025 15:09:29 +0200 Subject: [PATCH] fix: use a 30 bit hash if the username is non-numeric --- firka/lib/helpers/db/models/token_model.dart | 23 ++++++++++++++++++-- firka/lib/helpers/extensions.dart | 7 ++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/firka/lib/helpers/db/models/token_model.dart b/firka/lib/helpers/db/models/token_model.dart index b53393f..9c32268 100644 --- a/firka/lib/helpers/db/models/token_model.dart +++ b/firka/lib/helpers/db/models/token_model.dart @@ -1,5 +1,9 @@ +import 'dart:convert'; + +import 'package:crypto/crypto.dart'; import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart'; import 'package:firka/helpers/api/resp/token_grant.dart'; +import 'package:firka/helpers/extensions.dart'; import 'package:isar/isar.dart'; import '../../debug_helper.dart'; @@ -37,8 +41,23 @@ class TokenModel { var m = TokenModel(); final jwt = JWT.decode(resp.idToken); - m.studentIdNorm = int.parse( - jwt.payload["kreta:user_name"].toString().replaceAll("G0", "")); + final username = jwt.payload["kreta:user_name"].toString(); + if (username.isNumeric() || + (username.contains("G0") && + username.substring(0, username.length - 3).isNumeric())) { + m.studentIdNorm = int.parse(username.toString().replaceAll("G0", "")); + } else { + // you would expect all usernames to be numeric + // and for them be the student's student id, but NO + final hash = sha256.convert(utf8.encode(username)); + final value = ((hash.bytes[0] << 24) | + (hash.bytes[1] << 16) | + (hash.bytes[2] << 8) | + (hash.bytes[3])) >>> + 0; + + m.studentIdNorm = value & 0x3FFFFFFF; + } m.studentId = jwt.payload["kreta:user_name"]; m.iss = jwt.payload["kreta:institute_code"]; m.idToken = resp.idToken; diff --git a/firka/lib/helpers/extensions.dart b/firka/lib/helpers/extensions.dart index 70f2fcb..96d52d2 100644 --- a/firka/lib/helpers/extensions.dart +++ b/firka/lib/helpers/extensions.dart @@ -263,3 +263,10 @@ extension LessonExtension on List { (lesson) => lesson.start.isAfter(now.add(Duration(milliseconds: 1)))); } } + +extension StringExtension on String { + bool isNumeric() { + final regex = RegExp(r'^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$'); + return regex.hasMatch(trim()); + } +}