@@ -320,7 +320,7 @@ async def _perform_authorization_code_grant(self) -> tuple[str, str]:
320320 raise OAuthFlowError ("No callback handler provided for authorization code grant" ) # pragma: no cover
321321
322322 if self .context .oauth_metadata and self .context .oauth_metadata .authorization_endpoint :
323- auth_endpoint = str (self .context .oauth_metadata .authorization_endpoint ) # pragma: no cover
323+ auth_endpoint = str (self .context .oauth_metadata .authorization_endpoint )
324324 else :
325325 auth_base_url = self .context .get_authorization_base_url (self .context .server_url )
326326 auth_endpoint = urljoin (auth_base_url , "/authorize" )
@@ -343,11 +343,16 @@ async def _perform_authorization_code_grant(self) -> tuple[str, str]:
343343
344344 # Only include resource param if conditions are met
345345 if self .context .should_include_resource_param (self .context .protocol_version ):
346- auth_params ["resource" ] = self .context .get_resource_url () # RFC 8707 # pragma: no cover
346+ auth_params ["resource" ] = self .context .get_resource_url () # RFC 8707
347347
348348 if self .context .client_metadata .scope : # pragma: no branch
349349 auth_params ["scope" ] = self .context .client_metadata .scope
350350
351+ # OIDC requires prompt=consent when offline_access is requested
352+ # https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess
353+ if "offline_access" in self .context .client_metadata .scope .split ():
354+ auth_params ["prompt" ] = "consent"
355+
351356 authorization_url = f"{ auth_endpoint } ?{ urlencode (auth_params )} "
352357 await self .context .redirect_handler (authorization_url )
353358
@@ -576,6 +581,7 @@ async def async_auth_flow(self, request: httpx.Request) -> AsyncGenerator[httpx.
576581 extract_scope_from_www_auth (response ),
577582 self .context .protected_resource_metadata ,
578583 self .context .oauth_metadata ,
584+ self .context .client_metadata .grant_types ,
579585 )
580586
581587 # Step 4: Register client or use URL-based client ID (CIMD)
@@ -622,7 +628,10 @@ async def async_auth_flow(self, request: httpx.Request) -> AsyncGenerator[httpx.
622628 try :
623629 # Step 2a: Update the required scopes
624630 self .context .client_metadata .scope = get_client_metadata_scopes (
625- extract_scope_from_www_auth (response ), self .context .protected_resource_metadata
631+ extract_scope_from_www_auth (response ),
632+ self .context .protected_resource_metadata ,
633+ self .context .oauth_metadata ,
634+ self .context .client_metadata .grant_types ,
626635 )
627636
628637 # Step 2b: Perform (re-)authorization and token exchange
0 commit comments