getAuthorizationUrl method

  1. @override
Future<String> getAuthorizationUrl({
  1. required List<String> scopes,
  2. String? state,
  3. Map<String, String>? additionalParams,
})
override

Get authorization URL

Implementation

@override
Future<String> getAuthorizationUrl({
  required List<String> scopes,
  String? state,
  Map<String, String>? additionalParams,
}) async {
  final metadata = await _discoverMetadata();
  // PKCE support is read from the metadata; without it there is no flow.
  if (!(metadata.codeChallengeMethodsSupported ?? const []).contains('S256')) {
    throw OAuthError(
      error: 'pkce_unsupported',
      errorDescription: '${metadata.issuer} does not advertise PKCE with S256; refusing to proceed',
    );
  }
  final pkce = _generatePkce();

  // Store code verifier for later use
  _codeVerifier = pkce['code_verifier']!;
  _state = state ?? _generateState();

  final params = <String, String>{
    'response_type': 'code',
    'client_id': effectiveClientId,
    'code_challenge': pkce['code_challenge']!,
    'code_challenge_method': 'S256',
    if (config.redirectUri != null) 'redirect_uri': config.redirectUri!,
    if (scopes.isNotEmpty) 'scope': scopes.join(' '),
    'state': _state!,
    if (resource != null) 'resource': resource!,
    ...?additionalParams,
  };

  final uri = Uri.parse(
    metadata.authorizationEndpoint,
  ).replace(queryParameters: params);

  return uri.toString();
}