A corporation manager and dashboard for EVE Online
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

97 lines
3.3 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):
  9. self._session = session
  10. def get_authorize_url(self, client_id, redirect_uri, scopes=None,
  11. state=None):
  12. """Return a URL that the end user can use to start a login."""
  13. baseurl = "https://login.eveonline.com/oauth/authorize?"
  14. params = {
  15. "response_type": "code",
  16. "redirect_uri": redirect_uri,
  17. "client_id": client_id
  18. }
  19. if scopes:
  20. params["scope"] = " ".join(scopes)
  21. if state is not None:
  22. params["state"] = state
  23. return baseurl + urlencode(params)
  24. def get_access_token(self, client_id, client_secret, code, refresh=False):
  25. """Given an auth code or refresh token, return an access token.
  26. If refresh is True, code should be a refresh token. Otherwise, it
  27. should be an authorization code.
  28. Does a step of OAuth2 and returns a 3-tuple of (access_token,
  29. token_expiry, refresh_token) if successful. Returns None if one of the
  30. arguments is not valid. Raises EVEAPIError if the API did not respond
  31. in a sensible way or looks to be down.
  32. """
  33. url = "https://login.eveonline.com/oauth/token"
  34. params = {"code": code}
  35. if refresh:
  36. params["grant_type"] = "refresh_token"
  37. else:
  38. params["grant_type"] = "authorization_code"
  39. try:
  40. resp = self._session.post(url, data=params, timeout=10,
  41. auth=(client_id, client_secret))
  42. json = resp.json()
  43. except (requests.RequestException, ValueError) as exc:
  44. raise EVEAPIError(str(exc))
  45. if not resp.ok or "error" in json:
  46. return None
  47. if json.get("token_type") != "Bearer":
  48. raise EVEAPIError("invalid token_type in response body")
  49. token = json.get("access_token")
  50. expiry = json.get("expires_in")
  51. refresh = json.get("refresh_token")
  52. if not token or not expiry or not refresh:
  53. raise EVEAPIError("missing data in token response body")
  54. return token, expiry, refresh
  55. def get_character_info(self, token):
  56. """Given an access token, return character info.
  57. If successful, returns a 2-tuple of (character_id, character_name).
  58. Returns None if the token isn't valid. Raises EVEAPIError if the API
  59. did not respond in a sensible way or looks to be down.
  60. """
  61. url = "https://login.eveonline.com/oauth/verify"
  62. headers = {"Authorization": "Bearer " + token}
  63. try:
  64. resp = self._session.get(url, timeout=10, headers=headers)
  65. json = resp.json()
  66. except (requests.RequestException, ValueError) as exc:
  67. raise EVEAPIError(str(exc))
  68. if not resp.ok or "error" in json:
  69. return None
  70. char_id = json.get("CharacterID")
  71. char_name = json.get("CharacterName")
  72. if not char_id or not char_name:
  73. raise EVEAPIError("missing character ID or name in response body")
  74. return char_id, char_name