{"id":21887181,"url":"https://github.com/profcomff/auth-api","last_synced_at":"2025-04-15T09:50:40.805Z","repository":{"id":61195284,"uuid":"537918143","full_name":"profcomff/auth-api","owner":"profcomff","description":"API сервиса аутентификации и авторизации в приложение Твой ФФ!","archived":false,"fork":false,"pushed_at":"2025-04-06T22:58:06.000Z","size":836,"stargazers_count":16,"open_issues_count":10,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-06T23:25:28.983Z","etag":null,"topics":["auth-service"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/profcomff.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-17T20:04:20.000Z","updated_at":"2025-03-13T19:07:42.000Z","dependencies_parsed_at":"2023-02-01T16:16:48.767Z","dependency_job_id":"bef7647c-09e0-41a7-8b7b-1f1a9bb1a06c","html_url":"https://github.com/profcomff/auth-api","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/profcomff%2Fauth-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/profcomff%2Fauth-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/profcomff%2Fauth-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/profcomff%2Fauth-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/profcomff","download_url":"https://codeload.github.com/profcomff/auth-api/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249048713,"owners_count":21204305,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auth-service"],"created_at":"2024-11-28T11:08:40.439Z","updated_at":"2025-04-15T09:50:40.776Z","avatar_url":"https://github.com/profcomff.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# auth-api\n API сервиса аутентификации и авторизации в приложение Твой ФФ!\n\n[\u003cimg src=\"https://cdn.profcomff.com/easycode/easycode.svg\" width=\"200\"\u003e\u003c/img\u003e](https://easycode.profcomff.com/templates/docker-fastapi/workspace?mode=manual\u0026param.Repository+URL=https://github.com/profcomff/auth-api.git\u0026param.Working+directory=auth-api)\n\n## Схема работы Auth APUI\n\n![Auth Schema](https://github.com/profcomff/auth-api/assets/5656720/ab2730be-054a-454c-ab76-5475e615bb64)\n\n## Функционал \n1) Аутентификация и авторизация пользователей\n2) Управление доступами к ресурсам Твой ФФ\n3) Отправка пользовательских данных в Userdata API\n\n\n## Запуск\n\n1) Перейдите в папку проекта\n\n2) Создайте виртуальное окружение командой и активируйте его:\n```console\nfoo@bar:~$ python3 -m venv venv\nfoo@bar:~$ source ./venv/bin/activate  # На MacOS и Linux\nfoo@bar:~$ venv\\Scripts\\activate  # На Windows\n```\n\n3) Установите библиотеки\n```console\nfoo@bar:~$ pip install -r requirements.txt\n```\n   - Бэкенд может запуститься без кластера Kafka. Просто не указывайте ``KAFKA_DSN`` в ``.env``. Если вам нужна его логика, то \nтут находится инструкция по поднятию: ``https://github.com/profcomff/db-kafka``\n\n4) Запускайте приложение!\n```console\nfoo@bar:~$ python -m auth_backend start\n```\n\n---\n\n## ENV-file description\n\n- `DB_DSN` – Адрес базы данных в фаормате `postgresql://admin:admin@localhost:5432/dev`\n- `EMAIL` – Адрес электронной почты (логин для входа) для отправки уведомлений по Email\n- `EMAIL_PASS` – Пароль от электронной почты\n- `HOST` – Хост для использования в шаблонах сообщений электронной почты\n- `KAFKA_DSN` - Адрес Kafka Cluster\n- `KAFKA_USER_LOGIN_TOPIC_NAME` - имя топика, куда Auth API пишет пользовательские данные при успешной авторизации\n- `KAFKA_TIMEOUT` - время, в течение которого kafka worker ждет пока новое сообщение отправится(не используется)\n- `KAFKA_LOGIN` - Логин в брокер сообщений Kafka\n- `KAFKA_PASSWORD` - Пароль в брокер сообщений Kafka\n- `ENABLED_AUTH_METHODS` - включенные методы авторизации\n- `TOKEN_LENGTH` - длина отдаваемого токена при авторизации\n- `SESSION_TIME_IN_DAYS` - время, через которое протухнет токен\n- `MAX_RETRIES` - максимальное кол-во ретраев при отправке письма\n- `STOP_MAX_DELAY` - максимальная задержка между попытками отправить письмо\n- `WAIT_MIN`, `WAIT_MAX` -  минимальное и максимальное время ожидания успешной отправки письма\n- `EMAIL_DELAY_TIME_IN_MINUTES` - окно учёта писем\n- `EMAIL_DELAY_COUNT` - сколько писем можно отправить максимум в промежутке времени `EMAIL_DELAY_TIME_IN_MINUTES`\n\nОстальные параметры указаны [тут](https://github.com/profcomff/.github/wiki/%255Bbackend%255D-%25D0%259D%25D0%25B0%25D1%2581%25D1%2582%25D1%2580%25D0%25BE%25D0%25B9%25D0%25BA%25D0%25B8-%25D0%25BF%25D1%2580%25D0%25B8%25D0%25BB%25D0%25BE%25D0%25B6%25D0%25B5%25D0%25BD%25D0%25B8%25D1%258F)\n\n### Google\n- `GOOGLE_REDIRECT_URL: str` – URL адрес страницы для получения данных авторизации на нашем фронтэнде\n- `GOOGLE_SCOPES: list[str]` – Запрашиваемые у гугла права на управление аккаунтом, по умолчанию запрашивает данные пользователя\n- `GOOGLE_CREDENTIALS: Json` – Данные приложения Google, получить можно в Google Cloud Console\n\n### Physics\n- `PHYSICS_REDIRECT_URL: str` – см. секцию *Google*\n- `PHYSICS_SCOPES: list[str]` – см. секцию *Google*\n- `PHYSICS_CREDENTIALS: Json` – см. секцию *Google*\n\n### LK MSU\n- `LKMSU_REDIRECT_URL` – URL адрес страницы для получения данных авторизации на нашем фронтэнде\n\n### Yandex \n- `YANDEX_REDIRECT_URL` – URL адрес страницы для получения данных авторизации на нашем фронтэнде\n- `YANDEX_CLIENT_ID` - ID приложения, созданного в Яндексе\n- `YANDEX_CLIENT_SECRET` - Ключ для получения токена пользователя в Яндексе\n\n### MYMSU\n- `MYMSU_REDIRECT_URL` – см. секцию *Yandex*\n- `MYMSU_CLIENT_ID` - см. секцию *Yandex*\n- `MYMSU_CLIENT_SECRET` - см. секцию *Yandex*\n\n### Telegram \n- `TELEGRAM_REDIRECT_URL` – URL адрес страницы для получения данных авторизации на нашем фронтэнде\n- `TELEGRAM_BOT_TOKEN` - Токен бота приложения\n---\n\n### Основные абстракции\n1) Пользователь - запись в таблице user, может иметь много методов входа, например, VK, email, LKMSU\n2) Скоуп - право на определенное действие над определенным ресурсом. Например `timetable.event.update` - право на изменение расписания в Timetable API \n3) Группа - запись в таблице Group. Может иметь родителя, в итоге группы образуют дерево(деревья). Группа имеет свои скоупы. Группы также косвенно имеет все скоупы своего родителя, которая в свою очередь имеет скоупы своего родителя и т.д.\n4) Сессия - сущность опредляющая доступ к аккаунту. Имеет токен, свои скоупы. Пользователь авторизуется и тем самым создает сессию. В нее можно поместить те права, которые есть у пользователя. Сессия заканчивается через какое то время и доступ становится невозможен, надо создать новую сессию.\n\n## Сценарий использования\n### Email: регистрация нового аккаунта\n1. Дернуть ручку `POST /email/registrate` . Вы передаете\n```json\n{\n \"email\": \"string\", // Почта\n \"password\": \"string\" // Пароль\n}\n```\n3. На почту приходит письмо с линком на `GET /email/approve?token='...'`, если по ней перейти то почта будет подтверждена и регистрацию можно считать завершенной.\n\n### Email: вход в аккаунт\n1. Дернуть ручку `POST /email/login`. там всего один вариант логина, никуда не денетесь\n2. В теле запроса есть scopes, это обязательный параметр. scopes - это лист айдишников, существующих в группах в которых вы состоите прямо или в группах, которые являются родителями ваших групп. Он может быть равен [], если вам не нужны права для этого токена.\n3. Вам придет токен, сохраняйте его куда нибудь, срок действия ограничен.\n\n### Email: Восстановление забытого пароля\n1. Дернуть ручку `POST /email/reset/password/restore`. Вы передаете\n```json\n{\"email\": \"string\" // Почта}\n```\n3. Вам придет письмо, где будет ссылка НА ФРОНТ(надо сделать это), в ссылке будет reset_token\n4. Токен надо передать в ручку `POST /email/reset/password` в заголовках, вместе с\n```json\n{\"new_password\": \"\"}\n```\nи пароль будет изменен\n\n### Email: Изменение пароля\n1. Если пароль не забыт, а просто надо его поменять. Тогда в `POST /email/reset/password/request` передается токен авторизации, в теле вы передаете\n```json\n{\n\"password\": \"string\", // старый пароль\n\"new_password\": \"string\" // новый пароль\n}\n```\n3. Отправляете запрос и всё, пароль изменен, вам придет письмо с уведомлением о смене пароляю\n\n### Email: Изменение адреса электронной почты\n1. Дернуть ручку `POST /email/reset/email/request`. Всего один вариант, передаете новое мыло в теле\n```json\n{\"email\": \"string\" //Почта}\n```\nи токен атворизации в заголовках\n2. На почту придет письмо с подтверждением почты, там будет токен подтверждения в query параметрах. Ссылка ведет на ручку GET пока что, но надо переделать, чтобы тоже вела на фронт.\n\n\n### Google/Physics: вход пользователя с аккаунтом Google\n*Все примеры написаны для Google аккаунта, для аккаунта physics.msu.ru средует делать запросы к `/physics-msu` вместо `/google`*\n\n1. Получаем адрес для запроса на сервер Google: `GET /google/auth_url`\n2. Редиректим пользователя на этот url, пользователь входит в аккаунт и возвращается на страницу, которую можно узнать запросом `GET /google/redirect_url`\n3. Если Google не передал в ответе GET параметр `error`, передаем GET параметры страницы на сервер авториации в теле POST запроса в формате JSON: `POST /google/login`. Иначе возвращаем ошибку авторизации\n4. При успешном входе получаем `token` сессии. В теле запроса есть scopes, это обязательный параметр. scopes - это лист айдишников, существующих в группах в которых вы состоите прямо или в группах, которые являются родителями ваших групп. Он может быть равен [], если вам не нужны права для этого токена. Если сервер авторизации ответил ошибкой 401:\n   1. запоминаем значение id_token из ответа.\n   2. Предлагаем пользователю завести новый аккаунт нашего приложения, связанный с гуглом\n5. Если пользователь соглашается, делаем запрос с `{\"id_token\": \"\u003cid-token\u003e\"}` в теле на адрес `POST /google/register`. При успешном входе получаем `token` сессии, иначе показываем экран ошибки авторизации. В теле запроса есть scopes, это обязательный параметр. scopes - это лист айдишников, существующих в группах в которых вы состоите прямо или в группах, которые являются родителями ваших групп. Он может быть равен [], если вам не нужны права для этого токена.\n\n### Google/Physics: добавление аккаунта Google как второго метода входа\n*Все примеры написаны для Google аккаунта, для аккаунта physics.msu.ru средует делать запросы к `/physics-msu` вместо `/google`*\n\n1. Получаем адрес для запроса на сервер Google: `GET /google/auth_url`\n2. Редиректим пользователя на этот url, пользователь входит в аккаунт и возвращается на страницу, которую можно узнать запросом `GET /google/redirect_url`\n3. Если Google не передал в ответе GET параметр `error`, передаем данные на сервер авториации: `POST /google/register`, указываем заголовок `Authorization: \u003cauth-token\u003e`. Иначе возвращаем ошибку авторизации\n4. При успешном входе получаем `token` сессии, иначе показываем экран ошибки авторизации\n\n### Telegram: добавление аккаунта Telegram как второго метода входа\n\n1. Получаем адрес обычным способом, перенаправляем туда пользователя\n2. После выдачи доступа пользователь попадает на redirect url с параметром **#tgAuthResult=...**\n   1. На этой странице должен быть встроен виджет авторизации телеграмма, который преобразует **#tgAuthResult=...** в **?first_name=...\u0026user_name=...**\n3. Отослать данные из GET параметров в виде словаря на ручку `GET /telegram/login`\n4. При успешном входе получаем `token` сессии, иначе показываем экран ошибки авторизации\n\n### Созданиие группы \n1. Дернуть ручку `POST /group`, передать\n```json\n{\n\"name\": \"string\", // имя группы\n\"parent_id\": \"string\", // айди предка группы(из него подтянутся скоупы)\n\"scopes\": \"string\" // скуопы группы\n}\n```\nИтоговые права участников группы будут равны сумме прав участников рожительской группы и прав текущей группы\n\n### Создание скоупсов \n0. У вас должен быть аккаунт с правом на создание скоупсов :)\n1. Получаете токен со скоупом auth.scope.create \n2. Идете с токеном на ручку ` POST /scope`, отправляете его туда в заголовке и в теле отправляете\n```json\n{\n\"name\": \"string\", // имя скоупа(там должно быть две точки и три слова без пробелов)\n\"comment\": \"string\" // комментарий\n}\n```\n4. Профит\n\n### Добавление скоупсов в группу\n1. Дернуть `PATCH /group/{id}`, передать\n```json\n{\"scopes\": [\"\u003cscopes\u003e\"] // список, содержащий старые скоупы + новые. Ручка полностью заменит скоупы на переданные}\n```\n\n### Узнать информацию о себе\n1. Дернуть ручку `GET /me`, передать в заголовках токен авторизации\nОтвет содержит поля\n- `auth_methods` - список доступных методов авторизации пользователя\n- `session_scopes` - скоупы текущей сессии\n- `user_scopes` - список доступных пользователю скоупов\n- `indirect_groups` - список групп в которых пользователь состоит косвенно(то есть родители групп, в которых он состоит непосредственно)\n- `groups` - список групп в которых пользователь состоит непосредственно\n- `email` - электронная почта пользователя\n- `id` - айди в Auth API\n\n---\n\n## Добавление метода аутентификации\n1. Продумайте, какой путь должен совершить пользователь, чтобы войти в сервис с использованием вашего метода аутентификации\n    - Все методы должны поддерживать минимум 2 варианта взаимодействия: регистрация нового пользователя (она же, добавление метода аутентификации существующему пользователю) и повторный вход.\n    - Большинство внешних приложений (Google/Yandex/Telegram и др.) уже придумали все за вас и используют стандарт OAuth2 для авторизации внешних приложений, поэтому они очень похожи друг на друга и можно посомтреть примеры. Google авторизация уже реализована и можно почитать пути пользователя выше.\n\n2. Определитесь, какие методы нужны для работы с вашим методом авторизации.\n    - По умолчанию есть 2 API ручки: `/login` – вход (повторный), и `/register` – первичная регистрация/добавление нового метода авторизации\n    - Для OAuth2 авторизации и аутентификации также обязательно определены ручки `/auth_url` и `/redirect_url` – возвращают URL, куда пользователя должен перенаправить наш фронтенд для ввода логина и пароля на внешнем ресурсе, и URL, куда внешнее приложение перенаправит результат входа, соответственно\n    - Вы можете определить и свои методы, но помните, что их нужно также поддержать и на фронтенде приложения. Обязательно опишите пошагово (а лучше нарисуйте схему в Miro или draw.io), как будут рабоать ваши методы со стороны пользователя/фронтенда\n\n3. Создайте новый файл в папке `auth_backend/auth_plugins`, создайте класс и отнаследуйте его \n    - для legacy аутентификации от https://github.com/profcomff/auth-api/blob/1ce51bd532bd6f57c0abe922c7dd1a809d030723/auth_backend/auth_plugins/auth_method.py#L37\n    - для OAuth аутентификации от https://github.com/profcomff/auth-api/blob/1ce51bd532bd6f57c0abe922c7dd1a809d030723/auth_backend/auth_plugins/auth_method.py#L112\n\n4. Задайте классу описание, `prefix` и `tags` https://github.com/profcomff/auth-api/blob/1ce51bd532bd6f57c0abe922c7dd1a809d030723/auth_backend/auth_plugins/google.py#L31-L34\n    - `prefix` используется как отправная точка для ваших методов. Ручка логина для метода авторизации с премиксом `/myauth` будет `/myauth/login`\n    - Описание и теги используются для документирования кода. Зачастую без них непонятно, что вообще происходит. Не пропускайте их.\n\n5. Создайте основные методы\n    - Помните, что все методы являются `@staticmethod` или `@classmethod`. То есть не принимают аргумент `self` (текущий объект), а принимают ничего или `cls` (текущий класс) соответственно\n    - Ручки `/login` и `/register` имеют сигнатуры `async def _login(...)` и `async def _register(...)` соответственно\n    - Ручка `/login` обязательно возвращает объект https://github.com/profcomff/auth-api/blob/1ce51bd532bd6f57c0abe922c7dd1a809d030723/auth_backend/models/db.py#L117\n    - Ручки `/auth_url` и `/redirect_url` методов OAuth2 обязательно возвращают оъект https://github.com/profcomff/auth-api/blob/1ce51bd532bd6f57c0abe922c7dd1a809d030723/auth_backend/auth_plugins/auth_method.py#L115-L116\n  \n## Contributing\n\n- Основная [информация](https://github.com/profcomff/.github/wiki/%255Bdev%255D-Backend-%25D1%2580%25D0%25B0%25D0%25B7%25D1%2580%25D0%25B0%25D0%25B1%25D0%25BE%25D1%2582%25D0%25BA%25D0%25B0) по разработке наших приложений\n\n- Основная информация по разработке Auth API [тут](https://github.com/profcomff/auth-api/blob/main/CONTRIBUTING.md) и [тут](https://github.com/profcomff/.github/wiki/Сервис-авторизации)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprofcomff%2Fauth-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprofcomff%2Fauth-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprofcomff%2Fauth-api/lists"}