authenticate method
Implementation
Future<ConnectanumHttpAuthGrant> authenticate({
required String realm,
required String authId,
required AbstractAuthentication authentication,
String? authMethod,
Map<String, Object?> authextra = const <String, Object?>{},
Map<String, String> headers = const <String, String>{},
}) {
return _runTrackedOperation((openRequest) async {
try {
final requestRealm = _nonEmptyArgument(realm, 'realm');
final requestAuthId = _nonEmptyArgument(authId, 'authId');
final method = _httpAuthMethodName(
authMethod ?? authentication.getName(),
);
final details = Details.forHello()
..authid = requestAuthId
..authmethods = <String>[method];
if (authextra.isNotEmpty) {
details.authextra = Map<String, dynamic>.from(authextra);
}
await authentication.hello(requestRealm, details);
final normalizedAuthId = details.authid ?? requestAuthId;
final startBody = <String, Object?>{
'realm': requestRealm,
'authmethod': method,
'authid': normalizedAuthId,
if (details.authextra != null && details.authextra!.isNotEmpty)
'authextra': Map<String, Object?>.from(details.authextra!),
};
final challenge = await _postJsonObject(
startBody,
expectedStatus: HttpStatus.unauthorized,
label: 'HTTP auth challenge',
extraHeaders: headers,
openRequest: openRequest,
);
_validateAuthResponseIdentity(
challenge,
label: 'HTTP auth challenge',
realm: requestRealm,
authMethod: method,
);
final state = _nonEmptyString(challenge['state'], 'state');
final authenticate = await authentication.challenge(
_challengeExtraFrom(challenge['challenge']),
);
final grant = await _postJsonObject(
<String, Object?>{
'state': state,
if (authenticate.signature != null)
'signature': authenticate.signature,
if (authenticate.extra != null)
'extra': Map<String, Object?>.from(authenticate.extra!),
},
expectedStatus: HttpStatus.ok,
label: 'HTTP auth token request',
extraHeaders: headers,
openRequest: openRequest,
);
final parsedGrant = ConnectanumHttpAuthGrant.fromJson(
grant,
authEndpoint: endpoint,
);
_validateAuthResponseIdentity(
grant,
label: 'HTTP auth grant',
realm: requestRealm,
authMethod: method,
authId: normalizedAuthId,
);
final finalAuthExtra = parsedGrant.details['authextra'];
Map<String, Object?>? verifierFields;
if (finalAuthExtra is Map) {
verifierFields = <String, Object?>{
for (final entry in finalAuthExtra.entries)
if (entry.key is String) entry.key as String: entry.value,
};
}
await authentication.verifyFinal(
authId: parsedGrant.authId,
authMethod: authentication.getName(),
authExtra: verifierFields,
);
return parsedGrant;
} on Object {
await authentication.cancelPendingChallenge();
rethrow;
}
});
}