exchangeCodeForTokens function
Exchange authorization code for tokens.
Implementation
Future<OAuthTokenExchangeResponse> exchangeCodeForTokens({
required String authorizationCode,
required String state,
required String codeVerifier,
required int port,
bool useManualRedirect = false,
int? expiresIn,
HttpClient? httpClient,
}) async {
final config = getOauthConfig();
final body = <String, dynamic>{
'grant_type': 'authorization_code',
'code': authorizationCode,
'redirect_uri': useManualRedirect
? config.manualRedirectUrl
: 'http://localhost:$port/callback',
'client_id': config.clientId,
'code_verifier': codeVerifier,
'state': state,
};
if (expiresIn != null) body['expires_in'] = expiresIn;
final client = httpClient ?? HttpClient();
try {
final request = await client.postUrl(Uri.parse(config.tokenUrl));
request.headers.contentType = ContentType.json;
request.write(jsonEncode(body));
final response = await request.close().timeout(const Duration(seconds: 15));
final responseBody = await response.transform(utf8.decoder).join();
if (response.statusCode != 200) {
throw Exception(
response.statusCode == 401
? 'Authentication failed: Invalid authorization code'
: 'Token exchange failed (${response.statusCode}): $responseBody',
);
}
return OAuthTokenExchangeResponse.fromJson(
jsonDecode(responseBody) as Map<String, dynamic>,
);
} finally {
if (httpClient == null) client.close();
}
}