getAccessToken method

  1. @override
Future<AccessToken> getAccessToken({
  1. int tokenValidBuffer = 10,
})
override

Returns a valid AccessToken for the clientIdentity which is at least valid for the time specified in tokenValidBuffer.

The default value for tokenValidBuffer is 10 seconds.

Throws NetworkResponseException if the OAuthProxy returns a bad status code. Throws InvalidJsonSchemaException if the response from the OAuthProxy is invalid. Throws MaxRetryException if there is no token bundle at the OAuthProxy after maxRetryPickup exceeded. Could throw FormatException if the token could not be parsed correctly. If there is no internet connection a SocketException is thrown.

Implementation

@override
Future<AccessToken> getAccessToken({int tokenValidBuffer = 10}) async {
  if (_accessToken != null && _refreshToken != null) {
    //check if current _accessToken is valid
    if (_accessToken!.isNotExpired(timeBufferInSeconds: tokenValidBuffer)) {
      return _accessToken!;
    }
    //check if _refreshToken is valid and try to get a new access token
    if (_refreshToken!.isNotExpired(timeBufferInSeconds: tokenValidBuffer)) {
      final http.Response response =
          await http.post(refreshTokenEndpoint, headers: <String, String>{
        'content-type': 'application/x-www-form-urlencoded'
      }, body: <String, String>{
        KeycloakKeys.grantType: KeycloakKeys.refreshToken,
        KeycloakKeys.clientId: clientIdentity.id,
        KeycloakKeys.clientSecret: clientIdentity.secret,
        KeycloakKeys.refreshToken: _refreshToken!.originalToken
      });
      if (response.statusCode == 200) {
        try {
          _parseAndSetTokenResponse(response.body);
          //_accessToken and _refreshToken should be valid if this is reached
          return _accessToken!;
          // TODO(poq): test _accessToken.isNotExpired
        } catch (e) {
          //ignore errors in favor of full flow
        }
      }
      //something went wrong while refreshing token -> try full flow
    }
  }
  //full flow
  _invalidateLoginState();
  String authInit = '$authProxyBase${'/initialize/${clientIdentity.id}/'
      '${clientIdentity.secret}'}';
  if (scopes.isNotEmpty) authInit += '/${scopes.join(' ')}';
  //send start auth request to oAuthProxy
  http.Response response = await http.get(Uri.parse(authInit));
  if (response.statusCode != 200) throw NetworkResponseException(response);
  try {
    final Map<String, dynamic> initBody =
        jsonDecode(response.body) as Map<String, dynamic>;
    //check response
    if (initBody['redirect_url'] != null &&
        initBody['proxy_user_identifier'] != null &&
        initBody['proxy_secret'] != null) {
      //build url for interaction with the user and send it to the application
      final String authenticatorUrl =
          authProxyBase + initBody['redirect_url'].toString();
      await openUrlCallback(Uri.parse(authenticatorUrl));
      //start polling at pickup endpoint
      final String pollingUrl = "$authProxyBase${"/pickup/"
          "${initBody["proxy_user_identifier"].toString()}/"
          "${initBody["proxy_secret"].toString()}"}";
      final http.Client pickUpClient = http.Client();
      for (int i = 0; i < maxRetryPickup; i++) {
        response = await pickUpClient.get(Uri.parse(pollingUrl));
        await Future<dynamic>.delayed(
            Duration(milliseconds: retryWaitingTimeMilliSec));
        if (response.statusCode != 200)
          throw NetworkResponseException(response);
        try {
          _parseAndSetTokenResponse(response.body);
          //_accessToken and _refreshToken should be
          // valid if this code is reached
          if (onAuthSuccess != null) onAuthSuccess!();
          return _accessToken!;
          // TODO(poq): test _accessToken.isNotExpired
        } catch (e) {
          //answer doesn't includes the needed tokens
        }
      }
    } else {
      throw InvalidJsonSchemaException(
          'S3I-OAuthProxy returned invalid json', response.body);
    }
  } on TypeError catch (e) {
    throw InvalidJsonSchemaException(
        'S3I-OAuthProxy returned invalid json (${e.toString()})',
        response.body);
  } on FormatException catch (e) {
    throw InvalidJsonSchemaException(
        'S3I-OAuthProxy returned invalid json (${e.toString()})',
        response.body);
  }
  throw MaxRetryException('Can not receive token bundle from OAuthProxy');
}