Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question Leaderboard API required scopes

Discussion in 'Leaderboards' started by jackward84, Jun 27, 2023.

  1. jackward84

    jackward84

    Joined:
    Jan 26, 2017
    Posts:
    87
    I cannot for the life of me find where the required scopes for the leaderboards are documented (if they are at all).

    I want to use a serviceaccount to push scores to a leaderboard: https://services.docs.unity.com/lea...derboards/operation/addLeaderboardPlayerScore

    The only way I can do this is with a service account that has limited permissions, since the leaderboard scopes are not listed. Where can I find the leaderboard scopes, or can anyone tell me what they are?
     
  2. IainUnity3D

    IainUnity3D

    Unity Technologies

    Joined:
    Oct 5, 2022
    Posts:
    20
    Hi! Thanks for raising the issue that we can improve on the documentation for service accounts.

    When calling Leaderboards from Cloud Code you should be able to call addLeaderboardPlayerScore() and pass a Player ID without any specific setup or configuration.

    If that's not your use case (e.g. you are using a game server, or a script?) could you expand a little on how you are using a service account and what sort of permissions / scope it would ideally have. Thanks!
     
  3. jackward84

    jackward84

    Joined:
    Jan 26, 2017
    Posts:
    87
    Hi Iain,

    For my game server, I am using the access token that is provided with the game server at http://localhost:8086/v1/payload/token

    However for development purposes, I use a service account in order to fetch an access token to use with the leaderboard (and other) UGS APIs. When the service account has a lot of scopes, it requires you to request the access bearer token with only specific scopes. Like, for example, the allocations LIST endpoint requires me to fetch an access token with the scope
    multiplay.allocations.list
    .

    However, for leaderboards, I cannot work out what scope I need to request to be able to push player scores. The only way I can do it is if I specially set up a service account that has less than 100 scopes, because I don't know what scope I'm supposed to be requesting. Here is an example of where I am using the leaderboard in a server authoritive fashion for testing purposes. I also use it in my Unity Game code (which is running as a server) using web requests, because the SDK does not fit my purposes, and for various reasons, I don't want to use Cloud Code.

    Code (CSharp):
    1. def fill_leaderboard_with_fake_data(bracket: str, data: list):
    2.     loop = asyncio.get_event_loop()
    3.     header = get_access_token()
    4.     header = {"Authorization": f"Bearer {header}"}
    5.     rqs = []
    6.     for i in range(100):
    7.         player_id = random.randrange(0, 1_000_000, 1)
    8.         score = random.triangular(500, 2500)
    9.         score_payload = {"score": score}
    10.         url = f"https://leaderboards.services.api.unity.com/v1/projects/{PROJECT_ID}/leaderboards/{bracket}v{bracket}/scores/players/{player_id}"
    11.         rqs.append(post_request(url, header, score_payload))
    12.         url = f"https://leaderboards.services.api.unity.com/v1/projects/{PROJECT_ID}/leaderboards/{bracket}v{bracket}-elo/scores/players/{player_id}"
    13.         rqs.append(post_request(url, header, score_payload))
    14.     tasks = asyncio.gather(*rqs)
    15.     loop.run_until_complete(tasks)
    16.  
    get_access_token looks like:

    Code (CSharp):
    1. def get_service_account_auth_headers() -> dict:
    2.     plain_text_secret = f"{SA_KEY_ID}:{SA_KEY_SECRET}"
    3.     secret_encoded = plain_text_secret.encode("ascii")
    4.     secret_b64_bytes = base64.b64encode(secret_encoded)
    5.     secret_b64 = secret_b64_bytes.decode("ascii")
    6.     return {"Authorization": f"Basic {secret_b64}"}
    7.  
    8.  
    9. def get_access_token(scopes: list[str] | str | None = None) -> str | None:
    10.     if isinstance(scopes, str):
    11.         scopes = [scopes]
    12.  
    13.     header = get_service_account_auth_headers()
    14.     token_exchange = f"https://services.api.unity.com/auth/v1/token-exchange?projectId={PROJECT_ID}&environmentId={ENVIRONMENT_ID}"
    15.     if scopes:
    16.         r = requests.post(token_exchange, headers=header, json={"scopes": scopes})
    17.     else:
    18.         r = requests.post(token_exchange, headers=header)
    19.     try:
    20.         return r.json()["accessToken"]
    21.     except (json.JSONDecodeError, KeyError):
    22.         logging.exception(f"bad response: {r.text}")
    23.     return None
    24.  
    What I am missing, is what are the required scopes in the token exchange request. I can find the read scopes on this page:https://services.docs.unity.com/docs/service-account-auth/

    But not the write scopes. It would be really nice if the API documentation examples included the required scope in either the request sample or under the Service Account authorization part, ie: (https://services.docs.unity.com/leaderboards/#tag/Leaderboards/operation/addLeaderboardPlayerScore)
     
    Last edited: Jun 27, 2023