A corporation manager and dashboard for EVE Online
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 

111 rader
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