Пример #1
0
def test_is_enabled():
    conf1 = {
        'user_authentication': {
            'oauth': {
                'enabled': False
            }
        },
        'keys': {
            'secret': None,
            'private_key_path': None,
            'public_key_path': None
        }
    }

    with pytest.raises(OauthNotConfiguredError):
        token_manager(conf1)

    conf1 = {
        'user_authentication': {
            'oauth': {
                'enabled': True,
                'default_token_expiration': 1000
            },
            'keys': {
                'secret': None,
                'private_key_path': None,
                'public_key_path': None
            }
        }
    }
    with pytest.raises(InvalidOauthConfigurationError):
        token_manager(conf1)

    conf1 = {
        'user_authentication': {
            'oauth': {
                'enabled': True,
                'default_token_expiration': 'blah'
            },
            'keys': {
                'secret': 'asecret',
                'private_key_path': None,
                'public_key_path': None
            }
        }
    }
    with pytest.raises(InvalidOauthConfigurationError):
        token_manager(conf1)

    conf1 = {
        'user_authentication': {
            'oauth': {
                'enabled': True,
                'default_token_expiration': 1000
            },
            'keys': {}
        }
    }
    with pytest.raises(InvalidOauthConfigurationError):
        token_manager(conf1)
Пример #2
0
def test_jwt_token():
    test_config = {'secret': '123abc456def'}
    global _token_manager
    _token_manager = None

    mgr = token_manager(test_config)
    t = mgr.generate_token('admin')
    logger.info('Using token: {}'.format(t))
    j = JwtToken(token=t)
    assert j.credentials == t
    assert j.identifier == 'admin'
Пример #3
0
def get_oauth_token(grant_type="password",
                    username=None,
                    password=None,
                    client_id="anonymous"):
    """
    POST /oauth/token

    Requires the resource-owners credentials in the Authorization Header.

    This is a bit of a mix of the ResourceOwnerPasswordGrant flow and the ImplicitGrant flow since
    this function will populate the necessary fields to perform a password grant if the Authorization
    header is set and no content body is provided

    Note: the parameters above are embedded within the connexion request object, but must be specified in the
    method signature in order for connexion to route the request to this method. So it may appear that they are unused,
    but have no fear, they are!

    :return:
    """

    # Short-circuit if no oauth/token configured
    try:
        tok_mgr = token_manager()
        authz = ApiRequestContextProxy.get_service()._oauth_app
    except Exception as e:
        raise AccessDeniedError("Oauth not enabled in configuration",
                                detail={})

    # Add some default properties if not set in the request
    try:
        if request.content_length == 0 or not request.form:
            logger.debug(
                "Handling converting empty body into form-based grant request")

            if not request.data and not request.form:
                setattr(
                    request,
                    "form",
                    ImmutableMultiDict([
                        ("username", request.authorization.username),
                        ("password", request.authorization.password),
                        ("grant_type", "password"),
                        ("client_id", "anonymous"),
                    ]),
                )

        resp = authz.create_token_response()
        logger.debug("Token resp: {}".format(resp))
        return resp
    except:
        logger.debug_exception("Error authenticating")
        raise
Пример #4
0
def test_jwt_verifier():
    global _token_manager
    _token_manager = None
    mgr = token_manager({'secret': 'abc123'})

    v = BearerTokenVerifier(settings={})
    info = {'jwt': {'credential': 'signature_valid', 'failed_attempts': []}}

    t = JwtToken.__factory__().generate_token('admin')
    logger.info('Using token: {}'.format(t))
    test_token = JwtToken(token=t)
    bad_token = JwtToken(
        token=
        b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjogImFkbWluIiwgImFjY291bnQiOiAiMTIzIn0.w6gV8ABimGTKth-xiwxtM6v------'
    )
    v.verify_credentials(authc_token=test_token, authc_info=info)

    with pytest.raises(Exception):
        v.verify_credentials(authc_token=bad_token, authc_info=info)
Пример #5
0
def get_oauth_token():
    """
    POST /oauth/token

    Requires the resource-owners credentials in the Authorization Header.

    This is a bit of a mix of the ResourceOwnerPasswordGrant flow and the ImplicitGrant flow since
    this function will populate the necessary fields to perform a password grant if the Authorization
    header is set and no content body is provided

    :return:
    """

    # Short-circuit if no oauth/token configured
    try:
        tok_mgr = token_manager()
        authz = ApiRequestContextProxy.get_service()._oauth_app
    except Exception as e:
        raise AccessDeniedError('Oauth not enabled in configuration',
                                detail={})

    # Add some default properties if not set in the request
    try:
        if request.content_length == 0 or not request.form:
            logger.debug(
                'Handling converting empty body into form-based grant request')

            if not request.data and not request.form:
                setattr(
                    request, 'form',
                    ImmutableMultiDict([
                        ('username', request.authorization.username),
                        ('password', request.authorization.password),
                        ('grant_type', 'password'), ('client_id', 'anonymous')
                    ]))

        resp = authz.create_token_response()
        logger.debug('Token resp: {}'.format(resp))
        return resp
    except:
        logger.debug_exception('Error authenticating')
        raise
Пример #6
0
def test_is_enabled():
    conf1 = {
        "user_authentication": {"oauth": {"enabled": False}},
        "keys": {"secret": None, "private_key_path": None, "public_key_path": None},
    }

    with pytest.raises(OauthNotConfiguredError):
        token_manager(conf1)

    conf1 = {
        "user_authentication": {
            "oauth": {"enabled": True, "default_token_expiration": 1000},
            "keys": {"secret": None, "private_key_path": None, "public_key_path": None},
        }
    }
    with pytest.raises(InvalidOauthConfigurationError):
        token_manager(conf1)

    conf1 = {
        "user_authentication": {
            "oauth": {"enabled": True, "default_token_expiration": "blah"},
            "keys": {
                "secret": "asecret",
                "private_key_path": None,
                "public_key_path": None,
            },
        }
    }
    with pytest.raises(InvalidOauthConfigurationError):
        token_manager(conf1)

    conf1 = {
        "user_authentication": {
            "oauth": {"enabled": True, "default_token_expiration": 1000},
            "keys": {},
        }
    }
    with pytest.raises(InvalidOauthConfigurationError):
        token_manager(conf1)
Пример #7
0
def test_jwt_token():
    test_config = {
        'user_authentication': {
            'oauth': {
                'enabled': True,
                'default_token_expiration_seconds': 60
            }
        },
        'keys': {
            'secret': 'abc123'
        }
    }
    global _token_manager
    _token_manager = None

    mgr = token_manager(test_config)
    t = mgr.generate_token('admin')
    logger.info('Using token: {}'.format(t))
    j = JwtToken(token=t)
    assert j.credentials == t
    assert j.identifier == 'admin'
Пример #8
0
def test_jwt_token():
    test_config = {
        "user_authentication": {
            "oauth": {
                "enabled": True,
                "default_token_expiration_seconds": 60
            }
        },
        "keys": {
            "secret": "abc123"
        },
    }
    global _token_manager
    _token_manager = None

    mgr = token_manager(test_config)
    t = mgr.generate_token("admin")
    logger.info("Using token: {}".format(t))
    j = JwtToken(token=t)
    assert j.credentials == t
    assert j.identifier == "admin"
Пример #9
0
def test_jwt_verifier():
    global _token_manager
    _token_manager = None
    mgr = token_manager({
        'user_authentication': {
            'oauth': {
                'enabled': True,
                'default_token_expiration_seconds': 60
            }
        },
        'keys': {
            'secret': 'abc123'
        }
    })

    v = BearerTokenVerifier(settings={})

    # The lookup normally returns the uuid of the user
    info = {
        'authc_info': {
            'jwt': {
                'credential': 'abc123uuid',
                'failed_attempts': []
            }
        }
    }

    t, exp = JwtToken.__factory__().generate_token('abc123uuid',
                                                   return_expiration=True)
    logger.info('Using token: {}'.format(t))
    test_token = JwtToken(token=ensure_str(t))
    bad_token = JwtToken(
        token=
        'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjogImFkbWluIiwgImFjY291bnQiOiAiMTIzIn0.w6gV8ABimGTKth-xiwxtM6v------'
    )
    v.verify_credentials(authc_token=test_token, authc_info=info)

    with pytest.raises(Exception):
        v.verify_credentials(authc_token=bad_token, authc_info=info)
Пример #10
0
def test_jwt_verifier():
    global _token_manager
    _token_manager = None
    mgr = token_manager({
        "user_authentication": {
            "oauth": {
                "enabled": True,
                "default_token_expiration_seconds": 60
            }
        },
        "keys": {
            "secret": "abc123"
        },
    })

    v = BearerTokenVerifier(settings={})

    # The lookup normally returns the uuid of the user
    info = {
        "authc_info": {
            "jwt": {
                "credential": "abc123uuid",
                "failed_attempts": []
            }
        }
    }

    t, exp = JwtToken.__factory__().generate_token("abc123uuid",
                                                   return_expiration=True)
    logger.info("Using token: {}".format(t))
    test_token = JwtToken(token=ensure_str(t))
    bad_token = JwtToken(
        token=
        "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjogImFkbWluIiwgImFjY291bnQiOiAiMTIzIn0.w6gV8ABimGTKth-xiwxtM6v------"
    )
    v.verify_credentials(authc_token=test_token, authc_info=info)

    with pytest.raises(Exception):
        v.verify_credentials(authc_token=bad_token, authc_info=info)
Пример #11
0
def generate_token(client, grant_type, user, scope):
    tok_mgr = token_manager()
    logger.info('Generating token: {}, {}, {}, {}'.format(
        client, grant_type, user, scope))
    return str(tok_mgr.generate_token(user.username), 'utf-8')
Пример #12
0
def init_oauth(app):
    """
    Configure the oauth routes and handlers via authlib
    :return:
    """
    logger.debug('Initializing oauth routes')
    conf = localconfig.get_config()
    if not conf.get('oauth') or not conf.get('oauth', {}).get('enabled'):
        # Not enabled in configuration
        return None

    def query_client(client_id):
        logger.debug('Looking up client: {}'.format(client_id))

        # if client_id == 'anonymous':
        #    db = get_session()
        #    c = db.query(OAuth2Client).filter_by(client_id=client_id).first()
        #    logger.debug('Found client: {}'.format(c))
        # else:
        #    logger.debug('Using default user client')
        #

        # Return a default client to support implicit flows
        c = OAuth2Client()
        c.id = 0
        c.client_id = client_id
        c.user_id = client_id
        c.client_secret = ''
        c.issued_at = time.time() - 100
        c.expires_at = time.time() + 1000
        c.grant_type = 'password'
        c.token_endpoint_auth_method = 'none'
        c.client_name = 'default'
        return c

    def do_not_save_token(token, request):
        return None

    def save_token(token, request):
        logger.debug('Saving token: {}'.format(token))
        try:
            if request.user:
                user_id = request.user.username
            else:
                user_id = None

            client = request.client
            tok = OAuth2Token(client_id=client.client_id,
                              user_id=user_id,
                              **token)

            db = get_session()
            db.add(tok)
            db.commit()
            logger.info('Saved new token')
        except:
            logger.exception('Exception saving token')
            raise

    try:
        # Initialize an anonymous client record
        with session_scope() as db:
            f = db.query(OAuth2Client).filter_by(client_id='anonymous').first()
            if not f:
                c = OAuth2Client()
                c.client_id = 'anonymous'
                c.user_id = None
                c.client_secret = None
                c.issued_at = time.time() - 100
                c.expires_at = time.time() + 1000
                c.grant_type = 'password'
                c.token_endpoint_auth_method = 'none'
                c.client_name = 'anonymous'
                db.add(c)
    except Exception as e:
        logger.debug('Default client record init failed: {}'.format(e))

    app.config['OAUTH2_JWT_ENABLED'] = True
    app.config['OAUTH2_ACCESS_TOKEN_GENERATOR'] = generate_token
    app.config['OAUTH2_REFRESH_TOKEN_GENERATOR'] = True
    # app.config['OAUTH2_TOKEN_EXPIRES_IN'] = {
    #     'authorization_code': 864000,
    #     'implicit': 3600,
    #     'password': int(conf['user_authentication']['oauth'].get('default_token_expiration_seconds')),
    #     'client_credentials': 864000
    # }

    tok_mgr = token_manager()
    app.config['OAUTH2_JWT_KEY'] = tok_mgr.default_issuer().signing_key
    app.config['OAUTH2_JWT_ISS'] = tok_mgr.default_issuer().issuer
    app.config['OAUTH2_JWT_ALG'] = tok_mgr.default_issuer().signing_alg

    authz = AuthorizationServer(app,
                                query_client=query_client,
                                save_token=save_token)
    authz.register_grant(grants.RefreshTokenGrant)
    authz.register_grant(grants.ImplicitGrant)
    authz.register_grant(PasswordGrant)

    return authz
Пример #13
0
def init_oauth(app, grant_types, expiration_config):
    """
    Configure the oauth routes and handlers via authlib
    :return:
    """
    logger.debug('Initializing oauth routes')
    conf = localconfig.get_config()
    if not conf.get('user_authentication', {}).get('oauth', {}).get('enabled'):
        # Not enabled in configuration
        return None

    def query_client(client_id):
        logger.debug('Looking up client: {}'.format(client_id))
        db = get_session()
        c = db.query(OAuth2Client).filter_by(client_id=client_id).first()
        logger.debug('Found client record for client_id: {}'.format(client_id))
        return c

    def do_not_save_token(token, request):
        return None

    # Don't use this (yet), due to token signing that allows system to verify without persistence
    def save_token(token, request):
        try:
            if request.user:
                user_id = request.user.username
            else:
                user_id = None

            client = request.client
            tok = OAuth2Token(client_id=client.client_id,
                              user_id=user_id,
                              **token)

            db = get_session()
            db.add(tok)
            db.commit()
            logger.info('Saved new token')
        except:
            logger.exception('Exception saving token')
            raise

    try:
        # Initialize an anonymous client record
        with session_scope() as db:
            f = db.query(OAuth2Client).filter_by(client_id='anonymous').first()
            if not f:
                c = OAuth2Client()
                c.client_id = 'anonymous'
                c.user_id = None
                c.client_secret = None
                c.issued_at = time.time() - 100
                c.expires_at = time.time() + 1000
                c.grant_type = 'password'
                c.token_endpoint_auth_method = 'none'
                c.client_name = 'anonymous'
                db.add(c)
    except Exception as e:
        logger.debug('Default client record init failed: {}'.format(e))

    app.config['OAUTH2_JWT_ENABLED'] = True
    app.config['OAUTH2_ACCESS_TOKEN_GENERATOR'] = generate_token
    app.config['OAUTH2_REFRESH_TOKEN_GENERATOR'] = False

    # Only the password grant type is used, others can stay defaults
    app.config['OAUTH2_TOKEN_EXPIRES_IN'] = expiration_config

    tok_mgr = token_manager()
    app.config['OAUTH2_JWT_KEY'] = tok_mgr.default_issuer().signing_key
    app.config['OAUTH2_JWT_ISS'] = tok_mgr.default_issuer().issuer
    app.config['OAUTH2_JWT_ALG'] = tok_mgr.default_issuer().signing_alg

    authz = AuthorizationServer(app,
                                query_client=query_client,
                                save_token=do_not_save_token)
    # Support only the password grant for now
    for grant in grant_types:
        logger.debug('Registering oauth grant handler: {}'.format(
            getattr(grant, 'GRANT_TYPE', 'unknown')))
        authz.register_grant(grant)

    logger.debug('Oauth init complete')

    return authz
Пример #14
0
def generate_token(client, grant_type, user, scope):
    tok_mgr = token_manager()
    return str(tok_mgr.generate_token(user.username), 'utf-8')
Пример #15
0
    def _get_system_user_credentials(self):
        """
        Returns an AccessCredential object representing the system user

        :return:
        """
        cred = None
        exp = None  # Credential expiration, if needed

        logger.debug('Loading system user creds')

        with IdentityManager._cache_lock:
            cached_cred = IdentityManager._credential_cache.lookup(
                localconfig.SYSTEM_USERNAME)

            if cached_cred is not None:
                if cached_cred.is_expired():
                    # Flush it
                    logger.debug(
                        'Cached system credential is expired, flushing')
                    IdentityManager._credential_cache.delete(
                        localconfig.SYSTEM_USERNAME)
                else:
                    logger.debug('Cached system credential still ok')
                    # Use it
                    cred = cached_cred

            if cred is None:
                logger.debug('Doing refresh/initial system cred load')

                try:
                    tok_mgr = token_manager()
                except OauthNotConfiguredError:
                    tok_mgr = None

                # Generate one
                if tok_mgr:
                    # Generate a token
                    usr = db_account_users.get(localconfig.SYSTEM_USERNAME,
                                               session=self.session)
                    system_user_uuid = usr['uuid']
                    tok, exp = tok_mgr.generate_token(system_user_uuid,
                                                      return_expiration=True)
                    logger.debug(
                        'Generated token with expiration {}'.format(exp))
                    cred = HttpBearerCredential(tok, exp)
                else:
                    rec = db_accounts.get(localconfig.SYSTEM_USERNAME,
                                          session=self.session)
                    usr = db_account_users.get(localconfig.SYSTEM_USERNAME,
                                               session=self.session)

                    if not rec or not usr:
                        logger.error(
                            'Could not find a system account or user. This is not an expected state'
                        )
                        raise Exception('No system account or user found')

                    # This will not work if the system admin has configured hashed passwords but not oauth. But, that should be caught at config validation.
                    cred = HttpBasicCredential(
                        usr['username'],
                        usr.get('credentials',
                                {}).get(UserAccessCredentialTypes.password,
                                        {}).get('value'))

                if cred is not None:
                    logger.debug('Caching system creds')
                    IdentityManager._credential_cache.cache_it(
                        localconfig.SYSTEM_USERNAME, cred)

        return cred
Пример #16
0
def init_oauth(app, grant_types, expiration_config):
    """
    Configure the oauth routes and handlers via authlib
    :return:
    """
    logger.debug("Initializing oauth routes")
    try:
        tok_mgr = token_manager()
        logger.info("Initialized the token manager")
    except OauthNotConfiguredError:
        logger.info("OAuth support not configured, cannot initialize it")
        return None
    except InvalidOauthConfigurationError:
        logger.error("OAuth has invalid configuration, cannot initialize it")
        raise

    def query_client(client_id):
        db = get_session()
        c = db.query(OAuth2Client).filter_by(client_id=client_id).first()
        return c

    def do_not_save_token(token, request):
        return None

    # Don't use this (yet), due to token signing that allows system to verify without persistence
    def save_token(token, request):
        try:
            if request.user:
                user_id = request.user.username
            else:
                user_id = None

            client = request.client
            tok = OAuth2Token(client_id=client.client_id,
                              user_id=user_id,
                              **token)

            db = get_session()
            db.add(tok)
            db.commit()
        except:
            logger.exception("Exception saving token")
            raise

    try:
        # Initialize an anonymous client record
        with session_scope() as db:
            f = db.query(OAuth2Client).filter_by(client_id="anonymous").first()
            if not f:
                c = OAuth2Client()
                c.client_id = "anonymous"
                c.user_id = None
                c.client_secret = None
                c.issued_at = time.time() - 100
                c.expires_at = time.time() + 1000
                c.grant_type = "password"
                c.token_endpoint_auth_method = "none"
                c.client_name = "anonymous"
                db.add(c)
    except Exception as e:
        logger.debug("Default client record init failed: {}".format(e))

    app.config["OAUTH2_JWT_ENABLED"] = True
    app.config["OAUTH2_ACCESS_TOKEN_GENERATOR"] = generate_token
    app.config["OAUTH2_REFRESH_TOKEN_GENERATOR"] = False

    # Only the password grant type is used, others can stay defaults
    app.config["OAUTH2_TOKEN_EXPIRES_IN"] = expiration_config

    app.config["OAUTH2_JWT_KEY"] = tok_mgr.default_issuer().signing_key
    app.config["OAUTH2_JWT_ISS"] = tok_mgr.default_issuer().issuer
    app.config["OAUTH2_JWT_ALG"] = tok_mgr.default_issuer().signing_alg

    authz = AuthorizationServer(app,
                                query_client=query_client,
                                save_token=do_not_save_token)
    # Support only the password grant for now
    for grant in grant_types:
        logger.debug("Registering oauth grant handler: {}".format(
            getattr(grant, "GRANT_TYPE", "unknown")))
        authz.register_grant(grant)

    logger.debug("Oauth init complete")
    return authz
Пример #17
0
def generate_refresh_token(client, user, scope):
    tok_mgr = token_manager()
    logger.info('Generating refresh token: {}, {}, {}, {}'.format(
        client, 'refresh', user, scope))
    return str(tok_mgr.generate_token(user.username), 'utf-8')
Пример #18
0
def init_oauth(app, grant_types, expiration_config):
    """
    Configure the oauth routes and handlers via authlib

    :param app:
    :param grant_types:
    :param expiration_config:
    :return:
    """
    logger.debug("Initializing oauth routes")
    try:
        tok_mgr = token_manager()
        logger.info("Initialized the token manager")
    except OauthNotConfiguredError:
        logger.info("OAuth support not configured, cannot initialize it")
        return None
    except InvalidOauthConfigurationError:
        logger.error("OAuth has invalid configuration, cannot initialize it")
        raise

    def query_client(client_id):
        db = get_session()
        c = db.query(OAuth2Client).filter_by(client_id=client_id).first()
        return c

    def do_not_save_token(token, request):
        return None

    # Don't use this (yet), due to token signing that allows system to verify without persistence
    def save_token(token, request):
        try:
            if request.user:
                user_id = request.user.username
            else:
                user_id = None

            client = request.client
            tok = OAuth2Token(client_id=client.client_id,
                              user_id=user_id,
                              **token)

            db = get_session()
            db.add(tok)
            db.commit()
        except:
            logger.exception("Exception saving token")
            raise

    try:
        expected_metadata = {
            "token_endpoint_auth_method":
            "none",  # This should be a function of the grant type input but all of our types are this currently
            "client_name": "anonymous",
            "grant_types": [grant.GRANT_TYPE for grant in grant_types],
        }

        # Initialize an anonymous client record
        with session_scope() as db:
            found = (db.query(OAuth2Client).filter_by(
                client_id=ANONYMOUS_CLIENT_ID).one_or_none())

            logger.info("Creating new oauth client record for %s",
                        ANONYMOUS_CLIENT_ID)
            to_merge = OAuth2Client()
            to_merge.client_id = ANONYMOUS_CLIENT_ID
            to_merge.user_id = None
            to_merge.client_secret = None
            # These are no-ops effectively since the client isn't authenticated itself
            to_merge.client_id_issued_at = time.time() - 100
            to_merge.client_secret_expires_at = time.time() + 1000
            to_merge.set_client_metadata({
                "token_endpoint_auth_method":
                "none",  # This should be a function of the grant type input but all of our types are this currently
                "client_name":
                ANONYMOUS_CLIENT_ID,
                "grant_types": [grant.GRANT_TYPE for grant in grant_types],
            })

            merged = setup_oauth_client(found, to_merge)
            merged = db.merge(merged)
            logger.info(
                "Initializing db record for oauth client %s with grants %s",
                merged.client_id,
                merged.client_metadata.get("grant_types"),
            )
    except Exception as e:
        logger.debug("Default client record init failed: {}".format(e))

    app.config["OAUTH2_JWT_ENABLED"] = True
    app.config["OAUTH2_ACCESS_TOKEN_GENERATOR"] = generate_token
    app.config["OAUTH2_REFRESH_TOKEN_GENERATOR"] = False

    # Only the password grant type is used, others can stay defaults
    app.config["OAUTH2_TOKEN_EXPIRES_IN"] = expiration_config

    app.config["OAUTH2_JWT_KEY"] = tok_mgr.default_issuer().signing_key
    app.config["OAUTH2_JWT_ISS"] = tok_mgr.default_issuer().issuer
    app.config["OAUTH2_JWT_ALG"] = tok_mgr.default_issuer().signing_alg

    authz = AuthorizationServer(app,
                                query_client=query_client,
                                save_token=do_not_save_token)
    # Support only the password grant for now
    for grant in grant_types:
        logger.debug("Registering oauth grant handler: {}".format(
            getattr(grant, "GRANT_TYPE", "unknown")))
        authz.register_grant(grant)

    logger.debug("Oauth init complete")
    return authz