complete method
The second half: judge the redirect the authorization server sent
back and redeem its code. The issuer is checked first, then state;
an error is reported only once both hold.
Implementation
Future<OAuthGrant> complete(PendingAuthorization pending, Uri redirect) async {
final params = redirect.queryParameters;
checkAuthorizationResponseIssuer(
recordedIssuer: pending.issuer,
issParameterSupported: pending.issParameterSupported,
iss: params['iss'],
);
if (params['state'] != pending.state) {
throw const OAuthError(
error: 'invalid_state', errorDescription: 'The answer is not for the request this client made');
}
final error = params['error'];
if (error != null) {
throw OAuthError(error: error, errorDescription: params['error_description'], errorUri: params['error_uri']);
}
final code = params['code'];
if (code == null) {
throw const OAuthError(error: 'invalid_request', errorDescription: 'The answer carries no code');
}
final registration = await _knownRegistration(pending.issuer, pending.clientId);
final token = await _tokenRequest(pending.tokenEndpoint, registration, {
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': pending.redirectUri,
'code_verifier': pending.codeVerifier,
'resource': pending.resource,
});
final grant = OAuthGrant(
issuer: pending.issuer,
resource: pending.resource,
tokenEndpoint: pending.tokenEndpoint,
clientId: pending.clientId,
token: token,
scopes: token.scopes ?? pending.scopes,
);
await options.store.saveGrant(grant);
return grant;
}