getToken method
- [bool forceRefresh = false]
Retrieves the current App Trust token.
Implementation
Future<String?> getToken([bool forceRefresh = false]) async {
if (!kIsWeb) {
return null;
}
final configuredToken = app.options.appTrustToken;
if (!forceRefresh &&
configuredToken != null &&
configuredToken.isNotEmpty) {
return configuredToken;
}
final state = _state;
if (state == null) {
throw _appTrustError(
'not-activated',
'Call FusabaseAppTrust.instance.activate() before getToken().',
);
}
if (state.cachedToken == null) {
await _loadPersistedToken(state);
}
final now = DateTime.now().millisecondsSinceEpoch;
if (state.cachedToken != null &&
state.cachedToken!.expireTimeMillis <=
now + const Duration(seconds: 5).inMilliseconds) {
state.cachedToken = null;
app.setInternalAppTrustToken(null);
app.setInternalPersistedAppTrustToken(null);
}
if (!forceRefresh &&
state.cachedToken != null &&
state.cachedToken!.expireTimeMillis >
now + const Duration(seconds: 5).inMilliseconds) {
return state.cachedToken!.token;
}
if (!forceRefresh && state.inFlight != null) {
return (await state.inFlight!).token;
}
if (forceRefresh && state.inFlight != null) {
try {
await state.inFlight;
} catch (_) {
// Ignore the previous attempt and continue with a forced refresh.
}
}
final provider = state.webProvider;
if (provider == null) {
throw _appTrustError(
'missing-provider',
'A web App Trust provider is required for web token retrieval.',
);
}
state.inFlight =
(() async {
const action = 'attest';
final attestationToken = await provider.getAttestationToken(action);
final attestRequest = <String, dynamic>{
'provider': _providerKeyForWeb('web', app.options.appID),
'attestationToken': attestationToken,
'action': action,
'deviceInfo': {
'platform': app.options.appType.toLowerCase(),
'userAgent': attestation.getUserAgent(),
},
};
final siteKey = _siteKeyForAttestationRequest(provider);
if (siteKey != null && siteKey.isNotEmpty) {
attestRequest['siteKey'] = siteKey;
}
final client = createClient(app);
try {
final response = await client.post(
Uri.parse(_buildAttestUrl(app)),
headers: {'content-type': 'application/json'},
body: jsonEncode(attestRequest),
);
if (response.statusCode < 200 || response.statusCode > 299) {
throw _appTrustError(
'attestation-exchange-failed',
'Attestation exchange failed (${response.statusCode}).',
);
}
final json = jsonDecode(response.body);
final token = json['attestToken'];
if (token is! String || token.isEmpty) {
throw _appTrustError(
'invalid-attestation-response',
'Attestation response missing attestToken.',
);
}
final result = _AppTrustTokenResult(
token: token,
expireTimeMillis: _defaultExpiryMillis(),
);
state.cachedToken = result;
app.setInternalAppTrustToken(result.token);
app.setInternalPersistedAppTrustToken(result.token);
_tokenController.add(result.token);
await apptrustdb.setPersistedToken(_storageKey(app), {
'token': result.token,
'expireTimeMillis': result.expireTimeMillis,
'updatedAtMillis': DateTime.now().millisecondsSinceEpoch,
});
return result;
} finally {
client.close();
state.inFlight = null;
}
})();
return (await state.inFlight!).token;
}