23 lines
824 B
Dart
23 lines
824 B
Dart
import 'dart:convert';
|
|
import 'dart:math';
|
|
|
|
import 'package:crypto/crypto.dart';
|
|
|
|
/// Binds a guardian login request to the device that started it (PKCE-style):
|
|
/// the request carries only [challengeFor] of a secret that never leaves the
|
|
/// device, verification sends the secret itself. A mail link opened on another
|
|
/// device therefore cannot complete the login.
|
|
abstract final class DeviceBinding {
|
|
static String generateSecret([Random? random]) {
|
|
final rng = random ?? Random.secure();
|
|
final bytes = List<int>.generate(32, (_) => rng.nextInt(256));
|
|
return _base64UrlNoPad(bytes);
|
|
}
|
|
|
|
static String challengeFor(String secret) =>
|
|
_base64UrlNoPad(sha256.convert(utf8.encode(secret)).bytes);
|
|
|
|
static String _base64UrlNoPad(List<int> bytes) =>
|
|
base64Url.encode(bytes).replaceAll('=', '');
|
|
}
|