authenticateWithMagicLink method

Future<CarpUser> authenticateWithMagicLink(
  1. String uri
)

Authenticate to this CARP service using an magic link URI generated by CAWS as part of an anonymous access flow.

The magic link can be found inside the .csv file downloaded from the portal.

Implementation

Future<CarpUser> authenticateWithMagicLink(String uri) async {
  assert(_manager != null, 'Manager not configured. Call configure() first.');
  if (!_manager!.didInit) await initManager();

  String? code;
  String? clientId = _authProperties?.clientId;
  String? redirectUri = _authProperties?.anonymousRedirectURI?.toString();
  uri = _constructAuthUri(uri);

  TokenResponse tokenResponse =
      await FlutterWebAuth2.authenticate(
        url: uri,
        callbackUrlScheme: redirectUri!.split(':/').first,
        options: FlutterWebAuth2Options(
          intentFlags: ephemeralIntentFlags,
          preferEphemeral: true,
        ),
      ).then((result) async {
        code = Uri.parse(result).queryParameters['code'];
        if ((_currentUser == null || _currentUser!.isAuthenticated) &&
            code != null) {
          return await FlutterAppAuth().token(
            TokenRequest(
              clientId!,
              redirectUri,
              authorizationCode: code,
              discoveryUrl: _authProperties?.discoveryURL
                  .replace(
                    pathSegments: [
                      ...?_authProperties?.discoveryURL.pathSegments,
                      '.well-known',
                      'openid-configuration',
                    ],
                  )
                  .toString(),
              grantType: 'authorization_code',
            ),
          );
        }
        return Future.error("No code in redirect URI");
      });

  _currentUser = getCurrentUserProfileFromTokenResponse(tokenResponse);

  final accessToken = tokenResponse.accessToken;
  final refreshToken = tokenResponse.refreshToken;
  final idToken = tokenResponse.idToken;
  final scopeString =
      tokenResponse.tokenAdditionalParameters?['scope'] ??
      tokenResponse.tokenType;
  final scope = (scopeString is String) ? scopeString.split(' ') : <String>[];
  final expiresAt =
      tokenResponse.accessTokenExpirationDateTime ??
      DateTime.now().add(const Duration(hours: 1));

  if (_currentUser != null) {
    _currentUser!.authenticated(
      OAuthToken(
        accessToken ?? '',
        refreshToken ?? '',
        idToken ?? '',
        expiresAt,
        scope,
        idToken ?? '',
      ),
    );
    _authEventController.add(AuthEvent.authenticated);
    return currentUser;
  }

  // All other cases are treated as a failed attempt
  _authEventController.add(AuthEvent.failed);
  throw CarpUnauthorizedException('Authentication failed.');
}