Skip to content

Commit 45499ff

Browse files
committed
Merge remote-tracking branch 'oauth2cli_github/dev' into auth-code-receiver
2 parents fcf34a2 + 68ef992 commit 45499ff

File tree

1 file changed

+55
-37
lines changed

1 file changed

+55
-37
lines changed

msal/oauth2cli/oauth2.py

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33

44
import json
55
try:
6-
from urllib.parse import urlencode, parse_qs, quote_plus, urlparse
6+
from urllib.parse import urlencode, parse_qs, quote_plus, urlparse, urlunparse
77
except ImportError:
8-
from urlparse import parse_qs, urlparse
8+
from urlparse import parse_qs, urlparse, urlunparse
99
from urllib import urlencode, quote_plus
1010
import logging
1111
import warnings
@@ -573,16 +573,8 @@ def authorize(): # A controller in a web app
573573
def obtain_token_by_browser(
574574
# Name influenced by RFC 8252: "native apps should (use) ... user's browser"
575575
self,
576-
scope=None,
577-
extra_scope_to_consent=None,
578576
redirect_uri=None,
579-
timeout=None,
580-
welcome_template=None,
581-
success_template=None,
582-
error_template=None,
583-
auth_params=None,
584-
auth_uri_callback=None,
585-
browser_name=None,
577+
auth_code_receiver=None,
586578
**kwargs):
587579
"""A native app can use this method to obtain token via a local browser.
588580
@@ -625,38 +617,64 @@ def obtain_token_by_browser(
625617
626618
:return: Same as :func:`~obtain_token_by_auth_code_flow()`
627619
"""
620+
if auth_code_receiver: # Then caller already knows the listen port
621+
return self._obtain_token_by_browser( # Use all input param as-is
622+
auth_code_receiver, redirect_uri=redirect_uri, **kwargs)
623+
# Otherwise we will listen on _redirect_uri.port
628624
_redirect_uri = urlparse(redirect_uri or "http://127.0.0.1:0")
629625
if not _redirect_uri.hostname:
630626
raise ValueError("redirect_uri should contain hostname")
631-
if _redirect_uri.scheme == "https":
632-
raise ValueError("Our local loopback server will not use https")
633-
listen_port = _redirect_uri.port if _redirect_uri.port is not None else 80
634-
# This implementation allows port-less redirect_uri to mean port 80
627+
listen_port = ( # Conventionally, port-less uri would mean port 80
628+
80 if _redirect_uri.port is None else _redirect_uri.port)
635629
try:
636630
with _AuthCodeReceiver(port=listen_port) as receiver:
637-
flow = self.initiate_auth_code_flow(
638-
redirect_uri="http://{host}:{port}".format(
639-
host=_redirect_uri.hostname, port=receiver.get_port(),
640-
) if _redirect_uri.port is not None else "http://{host}".format(
641-
host=_redirect_uri.hostname
642-
), # This implementation uses port-less redirect_uri as-is
643-
scope=_scope_set(scope) | _scope_set(extra_scope_to_consent),
644-
**(auth_params or {}))
645-
auth_response = receiver.get_auth_response(
646-
auth_uri=flow["auth_uri"],
647-
state=flow["state"], # Optional but we choose to do it upfront
648-
timeout=timeout,
649-
welcome_template=welcome_template,
650-
success_template=success_template,
651-
error_template=error_template,
652-
auth_uri_callback=auth_uri_callback,
653-
browser_name=browser_name,
654-
)
631+
uri = redirect_uri if _redirect_uri.port != 0 else urlunparse((
632+
_redirect_uri.scheme,
633+
"{}:{}".format(_redirect_uri.hostname, receiver.get_port()),
634+
_redirect_uri.path,
635+
_redirect_uri.params,
636+
_redirect_uri.query,
637+
_redirect_uri.fragment,
638+
)) # It could be slightly different than raw redirect_uri
639+
self.logger.debug("Using {} as redirect_uri".format(uri))
640+
return self._obtain_token_by_browser(
641+
receiver, redirect_uri=uri, **kwargs)
655642
except PermissionError:
656-
if 0 < listen_port < 1024:
657-
self.logger.error(
658-
"Can't listen on port %s. You may try port 0." % listen_port)
659-
raise
643+
raise ValueError(
644+
"Can't listen on port %s. You may try port 0." % listen_port)
645+
646+
def _obtain_token_by_browser(
647+
self,
648+
auth_code_receiver,
649+
scope=None,
650+
extra_scope_to_consent=None,
651+
redirect_uri=None,
652+
timeout=None,
653+
welcome_template=None,
654+
success_template=None,
655+
error_template=None,
656+
auth_params=None,
657+
auth_uri_callback=None,
658+
browser_name=None,
659+
**kwargs):
660+
# Internally, it calls self.initiate_auth_code_flow() and
661+
# self.obtain_token_by_auth_code_flow().
662+
#
663+
# Parameters are documented in public method obtain_token_by_browser().
664+
flow = self.initiate_auth_code_flow(
665+
redirect_uri=redirect_uri,
666+
scope=_scope_set(scope) | _scope_set(extra_scope_to_consent),
667+
**(auth_params or {}))
668+
auth_response = auth_code_receiver.get_auth_response(
669+
auth_uri=flow["auth_uri"],
670+
state=flow["state"], # Optional but we choose to do it upfront
671+
timeout=timeout,
672+
welcome_template=welcome_template,
673+
success_template=success_template,
674+
error_template=error_template,
675+
auth_uri_callback=auth_uri_callback,
676+
browser_name=browser_name,
677+
)
660678
return self.obtain_token_by_auth_code_flow(
661679
flow, auth_response, scope=scope, **kwargs)
662680

0 commit comments

Comments
 (0)