Single Sign-On. Технология единого входа

Есть сайт где нужно авторизоваться, и система авторизации (SSO). Схема работает следующим образом:

  1. Посылается аякс запрос в систему авторизации с проверкой авторизации.
    URL: https://bus-sso-gateway/api/org.sso/User/core.auth/check
  2. Возвращается ответ. ERROR_OK пользователь авторизован. ERROR_AUTH - пользователь не авторизован.
  3. Если пользователь авторизован, то в браузере создается уникальный временный токен для авторизации. Он отправляется заппрос на сайт во внешнюю шину. 
    URL: https://bus-site-gateway/api/org.sso/User/core.auth/signAuthTmpToken. Сайт подписывает временный токен своим приватным ключом. Токен создается на определенное время.
  4. Сайт отвечает браузеру подписанным временным токеном.
  5. Посылается аякс запрос во внешнюю шину системы авторизации. 
    SSO проверяет токен публичным ключом сайта. Это токен устанавливает временный токен для сессии для конкретного сайта.
    URL: https://bus-sso-gateway/api/org.sso/User/core.auth/setAuthTmpToken.
  6. Браузер посылает запрос сайту для авторизации через токен.
    URL: https://bus-site-gateway/api/org.sso/User/core.auth/authFromTmpToken.
  7. Сайт посылает системный запрос в SSO. Система SSO, проверяет временный токен и создает JWT токен. и возвращает его.
    URL: https://bus-sso-gateway/bus/org.sso/User/core.auth/createJWTFromTmpToken.
  8. Сайт устанавливает JWT куки и возвращает их браузеру.

Формат JWT токенов

{
	"c": "", /* created jwt unix time */
	"e": "", /* expire jwt unix time */
	"u": "", /* user login */
	"i": "", /* user_id > 0 */
	"s": "", /* session_id */
},

Описание API

Вход в систему

POST: https://sso.example/api/sso/login/

{
  "method": "login",
  "login": "",
  "password": "",
}

Ответ:

{
  "result": {
    "jwt_data": [
      "user_id": "",
      "session_id": "",
      "login": "",
    ],
    "jwt_string": "",
  },
  "error": {
    "code": 1,
    "message": "",
    "name": ""
  }
}

Ответом на этот запрос будет установлена в куках jwt.

Выход из системы

POST: https://sso.example/api/sso/logout/

В запросе в куки нужно передать jwt токен

Ответ:

{
  "error": {
    "code": 1,
    "message": "",
    "name": ""
  }
}

Происходит удаление сессии из базы данных.

Проверка авторизации

URL: https://sso.example/api/sso/check_auth/

Ответ если пользователь авторизован:

{
  "result": {
    "login_hash": "",
  },
  "error": {
    "code": 1,
    "message": "",
    "name": ""
  }
}

Пользователь неавторизован:

{
  "result": {
    "login_hash": "",
  },
  "error": {
    "code": -1,
    "message": "User not auth",
    "name": "Core.Exceptions.NotAuthException"
  }
}

Подпись временного токена авторизации

Фронтенд отправляет на бэкенд запрос с временным токеном.

POST: https://app.example/api/sso/sign_tmp_token/

{
  "tmp_token": "",
}

Ответ:

Возвращает id проекта, токен и подпись этого токена.

{
  "result": {
    "project_id": "",
    "tmp_token": "",
    "sign": <base64 of sign>,
  },
  "error": {
    "code": 1,
    "message": "",
    "name": ""
  }
}

Установка временного токена авторизации в sso

Фронтенд отправляет в sso подписанный бэкендом временный токен. JWT передается на sso в куках запроса. Это запрос выполняется, если пользователь авторизован на SSO.

Проект SSO проверяет текущую куку jwt, узнает user_id и в базе для этого пользователя для конретного проекта записывает этот временный токен.

POST: https://sso.example/api/sso/set_tmp_token/

{
  "project_id": "",
  "tmp_token": <string of token>,
  "sign": <base64 of sign>,
}

Ответ:

{
  "result": {
    "project_id": "",
    "tmp_token": "",
    "sign": <base64 of sign>,
    "expire": DateTime,
  },
  "error": {
    "code": 1,
    "message": "",
    "name": ""
  }
}

Создание JWT токена через временный tmp токен

Фронтенд отправляет запрос на бэкенд. POST: https://app.example/api/sso/auth_tmp_token/

Бэкенд отправляет запрос на sso. POST: https://sso.example/api/sso/auth_tmp_token/

sso читает временный токен, проверяет его подпись, находит временный токен в базе, узнает ID пользователя и создает JWT токен и возвращает его бэкенду, а тот передает его на фронтенд.

{
  "project_id": "",
  "tmp_token": "",
  "sign": <base64 of sign>,
}

Ответ:

{
  "result": {
    "jwt_data": [
      "user_id": "",
      "session_id": "",
      "login": "",
    ],
    "jwt_string": "",
  },
  "error": {
    "code": 1,
    "message": "",
    "name": ""
  }
}

Обновление JWT токена

Фронтенд отправляет запрос на бэкенд. В куках запроса передается jwt токен. POST: https://app.example/api/sso/update_jwt_token/

Бэкенд проверяет цифровую подпись токена, и если она корректна, то отправляет запрос на sso. POST: https://sso.example/api/sso/update_jwt_token/

SSO обновляет дату окончания действия токена и пересоздает его. Ответом на этот запрос будет установлена в куках новая jwt.

Ответ:

{
  "result": {
    "jwt_data": [
      "user_id": "",
      "session_id": "",
      "login": "",
    ],
    "jwt_string": "",
  },
  "error": {
    "code": 1,
    "message": "",
    "name": ""
  }
}

Запрос на получения списка полномочий

Запрос может быть послан либо в бэкенд, либо в sso

URL: https://sso.example/api/sso/get_permissions/

URL: https://app.example/api/sso/get_permissions/

JWT передается в куках запроса.

Ответ:

{
  "result": {
    "user_id": "",
    "session_id": "",
    "login": "",
	"permissions":
	[
	  {
	    "project_id": "project_name",
		"permissions":
		[
		  "permission1",
		  "permission2",
		  "permission3",
		  "permission4",
		  "permission5",
		],
		"layers":
		{
		  [
		    "layer_id": "номер слоя",
			"permissions":
			[
			  "permission1",
			  "permission2",
			  "permission3",
			  "permission4",
			]
		  ]
		},
	  }
	]
  },
  "error": {
    "code": 1,
    "message": "",
    "name": ""
  }
}