1import logging 
    2 
    3log = logging.getLogger(__name__) 
    4 
    5 
    6class Dispatcher: 
    7    default_grant = None 
    8    oidc_grant = None 
    9 
    10 
    11class AuthorizationCodeGrantDispatcher(Dispatcher): 
    12    """ 
    13    This is an adapter class that will route simple Authorization Code 
    14    requests, those that have `response_type=code` and a scope including 
    15    `openid` to either the `default_grant` or the `oidc_grant` based on 
    16    the scopes requested. 
    17    """ 
    18    def __init__(self, default_grant=None, oidc_grant=None): 
    19        self.default_grant = default_grant 
    20        self.oidc_grant = oidc_grant 
    21 
    22    def _handler_for_request(self, request): 
    23        handler = self.default_grant 
    24 
    25        if request.scopes and "openid" in request.scopes: 
    26            handler = self.oidc_grant 
    27 
    28        log.debug('Selecting handler for request %r.', handler) 
    29        return handler 
    30 
    31    def create_authorization_response(self, request, token_handler): 
    32        """Read scope and route to the designated handler.""" 
    33        return self._handler_for_request(request).create_authorization_response(request, token_handler) 
    34 
    35    def validate_authorization_request(self, request): 
    36        """Read scope and route to the designated handler.""" 
    37        return self._handler_for_request(request).validate_authorization_request(request) 
    38 
    39 
    40class ImplicitTokenGrantDispatcher(Dispatcher): 
    41    """ 
    42    This is an adapter class that will route simple Authorization 
    43    requests, those that have `id_token` in `response_type` and a scope 
    44    including `openid` to either the `default_grant` or the `oidc_grant` 
    45    based on the scopes requested. 
    46    """ 
    47    def __init__(self, default_grant=None, oidc_grant=None): 
    48        self.default_grant = default_grant 
    49        self.oidc_grant = oidc_grant 
    50 
    51    def _handler_for_request(self, request): 
    52        handler = self.default_grant 
    53 
    54        if request.scopes and "openid" in request.scopes and 'id_token' in request.response_type: 
    55            handler = self.oidc_grant 
    56 
    57        log.debug('Selecting handler for request %r.', handler) 
    58        return handler 
    59 
    60    def create_authorization_response(self, request, token_handler): 
    61        """Read scope and route to the designated handler.""" 
    62        return self._handler_for_request(request).create_authorization_response(request, token_handler) 
    63 
    64    def validate_authorization_request(self, request): 
    65        """Read scope and route to the designated handler.""" 
    66        return self._handler_for_request(request).validate_authorization_request(request) 
    67 
    68 
    69class AuthorizationTokenGrantDispatcher(Dispatcher): 
    70    """ 
    71    This is an adapter class that will route simple Token requests, those that authorization_code have a scope 
    72    including 'openid' to either the default_grant or the oidc_grant based on the scopes requested. 
    73    """ 
    74    def __init__(self, request_validator, default_grant=None, oidc_grant=None): 
    75        self.default_grant = default_grant 
    76        self.oidc_grant = oidc_grant 
    77        self.request_validator = request_validator 
    78 
    79    def _handler_for_request(self, request): 
    80        handler = self.default_grant 
    81        scopes = () 
    82        parameters = dict(request.decoded_body) 
    83        client_id = parameters.get('client_id') 
    84        code = parameters.get('code') 
    85        redirect_uri = parameters.get('redirect_uri') 
    86 
    87        # If code is not present fallback to `default_grant` which will 
    88        # raise an error for the missing `code` in `create_token_response` step. 
    89        if code: 
    90            scopes = self.request_validator.get_authorization_code_scopes(client_id, code, redirect_uri, request) 
    91 
    92        if 'openid' in scopes: 
    93            handler = self.oidc_grant 
    94 
    95        log.debug('Selecting handler for request %r.', handler) 
    96        return handler 
    97 
    98    def create_token_response(self, request, token_handler): 
    99        """Read scope and route to the designated handler.""" 
    100        handler = self._handler_for_request(request) 
    101        return handler.create_token_response(request, token_handler)