obtainAccessCredentialsViaCodeExchange function

Future<AccessCredentials> obtainAccessCredentialsViaCodeExchange(
  1. Client client,
  2. ClientId clientId,
  3. String code, {
  4. String redirectUrl = 'postmessage',
  5. String? codeVerifier,
  6. AuthEndpoints authEndpoints = const GoogleAuthEndpoints(),
})

Obtain oauth2 AccessCredentials by exchanging an authorization code.

Running a hybrid oauth2 flow as described in the googleapis_auth.auth_browser library results in a HybridFlowResult which contains short-lived AccessCredentials for the client and an authorization code. This authorization code needs to be transferred to the server, which can exchange it against long-lived AccessCredentials.

client will be used for making the HTTP requests needed to create the returned AccessCredentials.

The clientId that you obtain from the API Console Credentials page, as described in Obtain OAuth 2.0 credentials.

If the authorization code was obtained using the mentioned hybrid flow, the redirectUrl must be "postmessage" (default).

If you obtained the authorization code using a different mechanism, the redirectUrl must be the same that was used to obtain the code.

NOTE: Only the server application will know the client secret - which is necessary to exchange an authorization code against access tokens.

NOTE: It is important to transmit the authorization code in a secure manner to the server. You should use "anti-request forgery state tokens" to guard against "cross site request forgery" attacks.

Implementation

Future<AccessCredentials> obtainAccessCredentialsViaCodeExchange(
  http.Client client,
  ClientId clientId,
  String code, {
  String redirectUrl = 'postmessage',
  String? codeVerifier,
  AuthEndpoints authEndpoints = const GoogleAuthEndpoints(),
}) async {
  final jsonMap = await client.oauthTokenRequest(
    {
      'client_id': clientId.identifier,
      'client_secret': clientId.secret ?? '',
      'code': code,
      if (codeVerifier != null) 'code_verifier': codeVerifier,
      'grant_type': 'authorization_code',
      'redirect_uri': redirectUrl,
    },
    authEndpoints: authEndpoints,
  );
  final accessToken = parseAccessToken(jsonMap);

  final idToken = jsonMap['id_token'] as String?;
  final refreshToken = jsonMap['refresh_token'] as String?;

  final scope = jsonMap['scope'];
  if (scope is! String) {
    throw ServerRequestFailedException(
      'The response did not include a `scope` value of type `String`.',
      responseContent: json,
    );
  }
  final scopes = scope.split(' ').toList();

  return AccessCredentials(
    accessToken,
    refreshToken,
    scopes,
    idToken: idToken,
  );
}