A corporation manager and dashboard for EVE Online
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 

111 lignes
3.8 KiB

  1. # -*- coding: utf-8 -*-
  2. from urllib.parse import urlencode
  3. import requests
  4. from ..exceptions import EVEAPIError
  5. __all__ = ["SSOManager"]
  6. class SSOManager:
  7. """EVE API module for Single Sign-On (SSO)."""
  8. def __init__(self, session, logger):
  9. self._session = session
  10. self._logger = logger
  11. self._debug = logger.debug
  12. def get_authorize_url(self, client_id, redirect_uri, scopes=None,
  13. state=None):
  14. """Return a URL that the end user can use to start a login."""
  15. baseurl = "https://login.eveonline.com/oauth/authorize?"
  16. params = {
  17. "response_type": "code",
  18. "redirect_uri": redirect_uri,
  19. "client_id": client_id
  20. }
  21. if scopes:
  22. params["scope"] = " ".join(scopes)
  23. if state is not None:
  24. params["state"] = state
  25. return baseurl + urlencode(params)
  26. def get_access_token(self, client_id, client_secret, code, refresh=False):
  27. """Given an auth code or refresh token, return an access token.
  28. If refresh is True, code should be a refresh token. Otherwise, it
  29. should be an authorization code.
  30. Does a step of OAuth2 and returns a 3-tuple of (access_token,
  31. token_expiry, refresh_token) if successful. Returns None if one of the
  32. arguments is not valid. Raises EVEAPIError if the API did not respond
  33. in a sensible way or looks to be down.
  34. """
  35. url = "https://login.eveonline.com/oauth/token"
  36. params = {"code": code}
  37. if refresh:
  38. params["grant_type"] = "refresh_token"
  39. else:
  40. params["grant_type"] = "authorization_code"
  41. self._debug("[POST] /oauth/token")
  42. try:
  43. resp = self._session.post(url, data=params, timeout=10,
  44. auth=(client_id, client_secret))
  45. json = resp.json()
  46. except (requests.RequestException, ValueError):
  47. self._logger.exception("Access token fetch failed")
  48. raise EVEAPIError()
  49. if not resp.ok or "error" in json:
  50. self._debug("Access token fetch error: %s", json["error"])
  51. return None
  52. if json.get("token_type") != "Bearer":
  53. self._logger.error("Invalid token_type in response body: %s",
  54. json.get("token_type"))
  55. raise EVEAPIError()
  56. token = json.get("access_token")
  57. expiry = json.get("expires_in")
  58. refresh = json.get("refresh_token")
  59. if not token or not expiry or not refresh:
  60. self._logger.error("Missing data in token response body")
  61. raise EVEAPIError()
  62. return token, expiry, refresh
  63. def get_character_info(self, token):
  64. """Given an access token, return character info.
  65. If successful, returns a 2-tuple of (character_id, character_name).
  66. Returns None if the token isn't valid. Raises EVEAPIError if the API
  67. did not respond in a sensible way or looks to be down.
  68. """
  69. url = "https://login.eveonline.com/oauth/verify"
  70. headers = {"Authorization": "Bearer " + token}
  71. self._debug("[GET] /oauth/verify")
  72. try:
  73. resp = self._session.get(url, timeout=10, headers=headers)
  74. json = resp.json()
  75. except (requests.RequestException, ValueError):
  76. self._logger.exception("Access token verify failed")
  77. raise EVEAPIError()
  78. if not resp.ok or "error" in json:
  79. self._debug("Access token verify error: %s", json["error"])
  80. return None
  81. char_id = json.get("CharacterID")
  82. char_name = json.get("CharacterName")
  83. if not char_id or not char_name:
  84. self._logger.error("Missing character ID or name in response body")
  85. raise EVEAPIError()
  86. return char_id, char_name