Example #1
0
    def _access_token_post_parse_request(self,
                                         request,
                                         client_id="",
                                         **kwargs):
        """
        This is where clients come to get their access tokens

        :param request: The request
        :param authn: Authentication info, comes from HTTP header
        :returns:
        """

        request = AccessTokenRequest(**request.to_dict())

        if "state" in request:
            try:
                sinfo = self.endpoint_context.sdb[request["code"]]
            except KeyError:
                logger.error("Code not present in SessionDB")
                return self.error_cls(error="unauthorized_client")
            else:
                state = sinfo["authn_req"]["state"]

            if state != request["state"]:
                logger.error("State value mismatch")
                return self.error_cls(error="unauthorized_client")

        if "client_id" not in request:  # Optional for access token request
            request["client_id"] = client_id

        logger.debug("%s: %s" %
                     (request.__class__.__name__, sanitize(request)))

        return request
Example #2
0
def service_endpoint(endpoint):
    logger.info('At the "{}" endpoint'.format(endpoint.endpoint_name))

    try:
        authn = request.headers['Authorization']
    except KeyError:
        pr_args = {}
    else:
        pr_args = {'auth': authn}

    if request.method == 'GET':
        req_args = endpoint.parse_request(request.args.to_dict(), **pr_args)
    else:
        if request.data:
            req_args = request.data
        else:
            req_args = dict([(k, v) for k, v in request.form.items()])
        req_args = endpoint.parse_request(req_args, **pr_args)

    logger.info('request: {}'.format(req_args))
    if isinstance(req_args, ResponseMessage) and 'error' in req_args:
        return make_response(req_args.to_json(), 400)

    try:
        if request.cookies:
            kwargs = {'cookie': request.cookies}
        else:
            kwargs = {}

        if isinstance(endpoint, AccessToken):
            args = endpoint.process_request(AccessTokenRequest(**req_args),
                                            **kwargs)
        else:
            args = endpoint.process_request(req_args, **kwargs)
    except Exception as err:
        message = traceback.format_exception(*sys.exc_info())
        # cherrypy.response.headers['Content-Type'] = 'text/html'
        return make_response(
            json.dumps({
                'error': 'server_error',
                'error_description': message
            },
                       sort_keys=True,
                       indent=4), 400)

    logger.info('Response args: {}'.format(args))

    if 'http_response' in args:
        return make_response(args['http_response'], 200)

    return do_response(endpoint, req_args, **args)
Example #3
0
    def test_construct_client_assertion(self):
        token_service = self.entity.client_get("service", 'accesstoken')
        request = AccessTokenRequest()
        pkj = PrivateKeyJWT()
        http_args = pkj.construct(request,
                                  service=token_service,
                                  authn_endpoint='token_endpoint')

        assert http_args == {}
        _jws = factory(request["client_assertion"])
        _payload = _jws.jwt.payload()
        assert "iss" in _payload
        assert _payload["iss"] == 'https://foodle.uninett.no'
        assert _payload["sub"] == 'https://foodle.uninett.no'
        assert request['client_assertion_type'] == JWT_BEARER
Example #4
0
def service_endpoint(request, endpoint):
    """
    TODO: documentation here
    """
    logger.info('Request at the "{}" endpoint'.format(endpoint.name))

    http_info = _get_http_info(request)
    data = _get_http_data(request, http_info)
    req_args = endpoint.parse_request(data, http_info=http_info)

    try:
        if isinstance(endpoint, Token):
            args = endpoint.process_request(AccessTokenRequest(**req_args),
                                            http_info=http_info)
        else:
            args = endpoint.process_request(req_args, http_info=http_info)
    except (InvalidClient, UnknownClient, UnAuthorizedClient) as err:
        logger.error(err)
        return JsonResponse(json.dumps({
            'error': 'unauthorized_client',
            'error_description': str(err)
        }),
                            safe=False,
                            status=400)
    except Exception as err:
        logger.error(err)
        return JsonResponse(json.dumps({
            'error': 'invalid_request',
            'error_description': str(err),
            'method': request.method
        }),
                            safe=False,
                            status=400)

    if isinstance(req_args, ResponseMessage) and 'error' in req_args:
        return JsonResponse(req_args.__dict__, status=400)
    elif 'redirect_location' in args:
        return HttpResponseRedirect(args['redirect_location'])
    elif 'http_response' in args:
        return HttpResponse(args['http_response'], status=200)

    return do_response(request, endpoint, req_args, **args)
Example #5
0
    "request_uri_parameter_supported":
    True,
}

AUTH_REQ = AuthorizationRequest(
    client_id="client_1",
    redirect_uri="https://example.com/cb",
    scope=["openid"],
    state="STATE",
    response_type="code id_token",
)

TOKEN_REQ = AccessTokenRequest(
    client_id="client_1",
    redirect_uri="https://example.com/cb",
    state="STATE",
    grant_type="authorization_code",
    client_secret="hemligt",
)

TOKEN_REQ_DICT = TOKEN_REQ.to_dict()

BASEDIR = os.path.abspath(os.path.dirname(__file__))


def full_path(local_file):
    return os.path.join(BASEDIR, local_file)


class TestEndpoint(object):
    @pytest.fixture(autouse=True)
Example #6
0
    def test_code_flow(self):
        # code is a Token instance
        code = self.auth()

        # next step is access token request

        TOKEN_REQ = AccessTokenRequest(
            client_id="client_1",
            redirect_uri="https://example.com/cb",
            state="STATE",
            grant_type="authorization_code",
            client_secret="hemligt",
            code=code.value,
        )

        # parse the token
        session_id = self.session_manager.token_handler.sid(TOKEN_REQ["code"])
        user_id, client_id, grant_id = self.session_manager.decrypt_session_id(
            session_id)

        # Now given I have the client_id from the request and the user_id from the
        # token I can easily find the grant

        # client_info = self.session_manager.get([user_id, TOKEN_REQ['client_id']])
        tok = self.session_manager.find_token(session_id, TOKEN_REQ["code"])

        # Verify that it's of the correct type and can be used
        assert tok.token_class == "authorization_code"
        assert tok.is_active()

        # Mint an access token and a refresh token and mark the code as used

        assert tok.supports_minting("access_token")

        client_info = self.session_manager.get(
            [user_id, TOKEN_REQ["client_id"]])

        assert tok.supports_minting("access_token")

        grant = self.session_manager[session_id]

        grant.mint_token(
            session_id=session_id,
            endpoint_context=self.endpoint_context,
            token_class="access_token",
            token_handler=self.session_manager.token_handler["access_token"],
            expires_at=time_sans_frac() + 900,  # 15 minutes from now
            based_on=tok,  # Means the token (tok) was used to mint this token
        )

        # this test is include in the mint_token methods
        # assert tok.supports_minting("refresh_token")

        refresh_token = grant.mint_token(
            session_id=session_id,
            endpoint_context=self.endpoint_context,
            token_class="refresh_token",
            token_handler=self.session_manager.token_handler["refresh_token"],
            based_on=tok,
        )

        tok.register_usage()

        assert tok.max_usage_reached() is True

        # A bit later a refresh token is used to mint a new access token

        REFRESH_TOKEN_REQ = RefreshAccessTokenRequest(
            grant_type="refresh_token",
            client_id="client_1",
            client_secret="hemligt",
            refresh_token=refresh_token.value,
            scope=["openid", "mail", "offline_access"],
        )

        session_id = self.session_manager.encrypted_session_id(
            user_id, REFRESH_TOKEN_REQ["client_id"], grant_id)
        reftok = self.session_manager.find_token(
            session_id, REFRESH_TOKEN_REQ["refresh_token"])

        # Can I use this token to mint another token ?
        assert grant.is_active()

        user_claims = self.endpoint_context.userinfo(
            user_id,
            client_id=TOKEN_REQ["client_id"],
            user_info_claims=grant.claims)

        access_token_2 = grant.mint_token(
            session_id=session_id,
            endpoint_context=self.endpoint_context,
            token_class="access_token",
            token_handler=self.session_manager.token_handler["access_token"],
            expires_at=time_sans_frac() + 900,  # 15 minutes from now
            based_on=
            reftok,  # Means the refresh token (reftok) was used to mint this token
        )

        assert access_token_2.is_active()

        token_info = self.session_manager.token_handler.info(
            access_token_2.value)
        assert token_info
Example #7
0
    True,
    "request_parameter_supported":
    True,
    "request_uri_parameter_supported":
    True,
}

AUTH_REQ = AuthorizationRequest(client_id='client_1',
                                redirect_uri='https://example.com/cb',
                                scope=['openid'],
                                state='STATE',
                                response_type='code')

TOKEN_REQ = AccessTokenRequest(client_id='client_1',
                               redirect_uri='https://example.com/cb',
                               state='STATE',
                               grant_type='authorization_code',
                               client_secret='hemligt')

TOKEN_REQ_DICT = TOKEN_REQ.to_dict()

BASEDIR = os.path.abspath(os.path.dirname(__file__))


def full_path(local_file):
    return os.path.join(BASEDIR, local_file)


USERINFO = UserInfo(json.loads(open(full_path('users.json')).read()))

Example #8
0
def service_endpoint(endpoint):
    _log = current_app.srv_config.logger
    _log.info('At the "{}" endpoint'.format(endpoint.endpoint_name))

    try:
        authn = request.headers['Authorization']
    except KeyError:
        pr_args = {}
    else:
        pr_args = {'auth': authn}

    if request.method == 'GET':
        try:
            req_args = endpoint.parse_request(request.args.to_dict(), **pr_args)
        except Exception as err:
            _log.error(err)
            return make_response(json.dumps({
                'error': 'invalid_request',
                'error_description': str(err)
                }), 400)
    else:
        if request.data:
            req_args = request.data
        else:
            req_args = dict([(k, v) for k, v in request.form.items()])
        try:
            req_args = endpoint.parse_request(req_args, **pr_args)
        except Exception as err:
            _log.error(err)
            return make_response(json.dumps({
                'error': 'invalid_request',
                'error_description': str(err)
                }), 400)

    _log.info('request: {}'.format(req_args))
    if isinstance(req_args, ResponseMessage) and 'error' in req_args:
        return make_response(req_args.to_json(), 400)

    try:
        if request.cookies:
            _log.debug(request.cookies)
            kwargs = {'cookie': request.cookies}
        else:
            kwargs = {}

        if isinstance(endpoint, AccessToken):
            args = endpoint.process_request(AccessTokenRequest(**req_args),
                                            **kwargs)
        else:
            args = endpoint.process_request(req_args, **kwargs)
    except Exception as err:
        message = traceback.format_exception(*sys.exc_info())
        _log.error(message)
        return make_response(json.dumps({
            'error': 'invalid_request',
            'error_description': str(err)
            }), 400)

    _log.info('Response args: {}'.format(args))

    if 'redirect_location' in args:
        return redirect(args['redirect_location'])
    if 'http_response' in args:
        return make_response(args['http_response'], 200)

    return do_response(endpoint, req_args, **args)
Example #9
0
def service_endpoint(endpoint):
    _log = current_app.logger
    _log.info('At the "{}" endpoint'.format(endpoint.name))

    http_info = {
        "headers": {
            k: v
            for k, v in request.headers.items(lower=True) if k not in IGNORE
        },
        "method": request.method,
        "url": request.url,
        # name is not unique
        "cookie": [{
            "name": k,
            "value": v
        } for k, v in request.cookies.items()]
    }

    if request.method == 'GET':
        try:
            req_args = endpoint.parse_request(request.args.to_dict(),
                                              http_info=http_info)
        except (InvalidClient, UnknownClient) as err:
            _log.error(err)
            return make_response(
                json.dumps({
                    'error': 'unauthorized_client',
                    'error_description': str(err)
                }), 400)
        except Exception as err:
            _log.error(err)
            return make_response(
                json.dumps({
                    'error': 'invalid_request',
                    'error_description': str(err)
                }), 400)
    else:
        if request.data:
            if isinstance(request.data, str):
                req_args = request.data
            else:
                req_args = request.data.decode()
        else:
            req_args = dict([(k, v) for k, v in request.form.items()])
        try:
            req_args = endpoint.parse_request(req_args, http_info=http_info)
        except Exception as err:
            _log.error(err)
            err_msg = ResponseMessage(error='invalid_request',
                                      error_description=str(err))
            return make_response(err_msg.to_json(), 400)

    _log.info('request: {}'.format(req_args))
    if isinstance(req_args, ResponseMessage) and 'error' in req_args:
        return make_response(req_args.to_json(), 400)

    try:
        if isinstance(endpoint, Token):
            args = endpoint.process_request(AccessTokenRequest(**req_args),
                                            http_info=http_info)
        else:
            args = endpoint.process_request(req_args, http_info=http_info)
    except Exception as err:
        message = traceback.format_exception(*sys.exc_info())
        _log.error(message)
        err_msg = ResponseMessage(error='invalid_request',
                                  error_description=str(err))
        return make_response(err_msg.to_json(), 400)

    _log.info('Response args: {}'.format(args))

    if 'redirect_location' in args:
        return redirect(args['redirect_location'])
    if 'http_response' in args:
        return make_response(args['http_response'], 200)

    response = do_response(endpoint, req_args, **args)
    return response
Example #10
0
def service_endpoint(request, endpoint):
    """
    TODO: documentation here
    """
    logger = oidcendpoint_app.srv_config.logger
    logger.info('At the "{}" endpoint'.format(endpoint.endpoint_name))

    # if hasattr(request, 'debug') and request.debug:
        # import pdb; pdb.set_trace()

    authn = request.headers.get('Authorization', {})
    pr_args = {'auth': authn}
    if authn:
        logger.debug('request.headers["Authorization"] => {}'.format(pr_args))

    if request.method == 'GET':
        data = {k:v for k,v in request.GET.items()}
    elif request.body:
        data = request.body \
               if isinstance(request.body, str) else \
               request.body.decode()
        #<oidcendpoint.oidc.token.AccessToken object at 0x7fd626329d68>
        if authn:
            data = {k:v[0] for k,v in urlib_parse.parse_qs(data).items()}
    else:
        data = {k:v for k,v in request.POST.items()}

    # for .well-known resources like provider-config no data are submitted
    # if not data:
    #   ... not possible in this implementation

    logger.debug('Request arguments [{}]: {}'.format(request.method, data))
    try:
        req_args = endpoint.parse_request(data, **pr_args)
    except Exception as err:
        logger.error(err)
        return JsonResponse(json.dumps({
            'error': 'invalid_request',
            'error_description': str(err),
            'method': request.method
            }), status=400)

    logger.info('request: {}'.format(req_args))
    if isinstance(req_args, ResponseMessage) and 'error' in req_args:
        return JsonResponse(req_args.__dict__, status=400)

    if request.COOKIES:
        logger.debug(request.COOKIES)
        # TODO: cookie
        kwargs = {'cookie': request.COOKIES}
    else:
        kwargs = {}

    try:
        if isinstance(endpoint, AccessToken):
            args = endpoint.process_request(AccessTokenRequest(**req_args),
                                            **kwargs)
        else:
            args = endpoint.process_request(req_args, **kwargs)
    except Exception as err:
        message = '{}'.format(err)
        logger.error(message)
        return JsonResponse(json.dumps({
            'error': 'invalid_request',
            'error_description': str(err)
            }), status=400)

    logger.info('Response args: {}'.format(args))
    if 'redirect_location' in args:
        return HttpResponseRedirect(args['redirect_location'])
    if 'http_response' in args:
        return HttpResponse(args['http_response'], status=200)

    return do_response(endpoint, req_args, **args)