Ищете совет по защите частного REST API, написанного в python-колбе

В настоящее время я пишу API для отдыха в python с микрофлокой Flask. Это частный API, и он имеет дело с пользовательскими данными. Я планирую использовать этот API для создания веб-приложения и приложения для Android.

В настоящее время я использую digest auth для защиты частных пользовательских данных. Например, если вы хотите публиковать данные на моем сервисе с помощью пользователя bob, вы делаете запрос на почту в myapi/story/create и предоставляете учетные данные bob с помощью шаблона дайджеста.

Я знаю, что это нехорошее решение, потому что:
-Digest auth не безопасно
-Клиент не аутентифицирован (как защитить запросы, не связанные с текущим пользователем, например, создать нового пользователя?)

Я прочитал много статей о oAuth, но трехсторонняя аутентификация кажется излишней, потому что я не планирую открывать свой API для третьей стороны.
2-legged oAuth не подходит, поскольку он обеспечивает аутентификацию только для клиентов, а не для пользователей.
Другая проблема с oAuth заключается в том, что я не нашел исчерпывающего руководства по ее реализации в Python. Я нашел библиотеку python-oauth2, но я не понимаю пример сервера, и я не могу найти дополнительную документацию. Плюс, похоже, что многие аспекты oAuth не рассматриваются в этом примере.

Итак, мои вопросы:

  • Существует ли альтернативная схема (а не oAuth) для аутентификации как клиента, так и пользователя с разумным уровнем безопасности?
  • Если oAuth - лучшее решение:
    • Как пропустить процесс авторизации (поскольку пользователям не нужно разрешать сторонние клиенты)?
    • Есть ли подробная документация для python-oauth2 или для любой другой библиотеки Python?

Любая помощь или совет будут оценены.

Ответы

Ответ 1

Простой ответ заключается в том, чтобы разоблачить ваш API только через HTTPS, а затем использовать HTTP Basic authentication. Я не думаю, что есть какая-то причина беспокоиться о Дайджесте. Обычная проверка подлинности небезопасна, но отправляется с каждым запросом, поэтому вам не нужно беспокоиться о том, что ваша аутентификация устарела или что-то еще. Путем туннелирования через HTTPS у вас есть безопасное соединение.

Если вы хотите аутентифицировать клиента, вы можете использовать сертификаты клиента SSL. Тем не менее, в целом довольно сложно блокировать клиента от вредоносных пользователей, поэтому я хотел бы рассмотреть возможность открытого доступа к функциям регистрации и защитить себя от DOS и т.д. Посредством проверки внеполосной учетной записи.

Ответ 2

Вы уже считали, что используете базовую аутентификацию?

Я еще не использовал фреймворк, который вы упомянули, но я использовал базовый auth для защиты некоторых URL-адресов в приложении на основе web.py и работал нормально.

В принципе, вы можете использовать токен в base64, который на самом деле является стандартным http-хейдером.

Возможно, этот пример может помочь вам:

class Login:

    def GET(self):
        auth = web.ctx.env.get('HTTP_AUTHORIZATION')
        authreq = False
        if auth is None:
            authreq = True
        else:
            auth = re.sub('^Basic ','',auth)
            username,password = base64.decodestring(auth).split(':')
            if (username,password) in settings.allowed:
                raise web.seeother('/eai')
            else:
                authreq = True
        if authreq:
            web.header('WWW-Authenticate','Basic realm="Auth example"')
            web.ctx.status = '401 Unauthorized'
            return

Ответ 3

Если вы заинтересованы в базовой аутентификации, вот быстрый атрибут, который вы можете использовать для украшения ваших обработчиков http://www.varunpant.com/posts/basic-authentication-in-web-py-via-attribute. Этот пример написан в основном в контексте web.py, но я думаю, его можно легко настроить.

def check_auth(username, password): 
    return username == 'username' and password == 'password'


def requires_auth(f):
    @wraps(f)     
    def decorated(*args, **kwargs):        
        auth = web.ctx.env['HTTP_AUTHORIZATION'] if 'HTTP_AUTHORIZATION' in  web.ctx.env else None
        if auth:
            auth = re.sub('^Basic ', '', auth)
            username, password = base64.decodestring(auth).split(':')
        if not auth or not check_auth(username, password):
            web.header('WWW-Authenticate', 'Basic realm="admin"')
            web.ctx.status = '401 Unauthorized'
            return 

        return f(*args, **kwargs)

    return decorated