Olen/Spond

Login API No longer working

Closed this issue · 3 comments

Hi wondering if others are seeing the same but it appears some time in the last 30days Spond have made changes to there login api as been using this project for a while to upload our running club events to spond and it appear to no longer work this month.

when adding some debug I get:

login result: {'message': 'Not authenticated'}

But supplied creds are all good so can only assume api has been modified. Tried a trace in browser but that seems to now use api.spond.com and not sure why but haven't been able to trace the login step yet as seems to be masked somehow.

Same issue here, has failed since 7 Aug:

Traceback (most recent call last):
...
  File "/home/[redacted]/lib/python3.10/site-packages/spond/spond.py", line 67, in get_group
    await self.login()
  File "/home/[redacted]/lib/python3.10/site-packages/spond/spond.py", line 25, in login
    self.cookie = r.cookies["auth"]
KeyError: 'auth'
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x7f29ff876470>
Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x7f29ff8824a0>, 11274797.606713338)]']
connector: <aiohttp.connector.TCPConnector object at 0x7f29ff875a50>

2023-08-07 23:27:12 -- Completed task, took 6.65 seconds, return code was 1.

I'll try and get a merge request sorted for original code as my version is heavily customised for my needs but below is crux of the changes if want to get it sorted sooner. Bascially seems they moved to bearer tokens and new api endpoint

NEW API ENDPOINT

        #self.apiurl = "https://spond.com/api/2.1/"
        self.apiurl = "https://api.spond.com/core/v1/"

Get new Bearer Token

    async def login(self):
        loginurl = self.apiurl + "login"
        data = { 'email': self.username, 'password': self.password }
        logger.info(f"login data: {data}")
        async with self.clientsession.post(loginurl, json=data) as r:
            logger.info(f"login r: {r}")
            # if r.cookies and "auth" in r.cookies:
            #     self.cookie = r.cookies['auth']
            loginresult = await r.json()
            logger.info(f"loginresult result: {loginresult}")
            self.token = loginresult["loginToken"]

        apichaturl = self.apiurl + "chat"
        
        headers = { 
            'content-type': 'application/json', 
            'Authorization': f'Bearer {self.token }'
        }
        res = await self.clientsession.post(apichaturl, headers=headers)
        result = await res.json()
        logger.info(f"login result: {result}")
        self.chaturl = result['url']
        self.auth = result['auth']

Add a property for the auth headers needed for API calls. Merged the chat header as doesn't seem to care if it provided on non chat calls so keeps it easier to have one standard set.

    @property
    def auth_headers(self):
        headers = { 
            'content-type': 'application/json', 
            'Authorization': f'Bearer {self.token}',
            'auth': f'{self.auth}'  
        }
        return headers

modify calls to add auth_headers. single example all need mod

    async def getGroups(self):
        if not self.cookie:
            await self.login()
        url = self.apiurl + "groups/"
        async with self.clientsession.get(url,headers=self.auth_headers) as r:
            self.groups = await r.json()
            return self.groups

Resolved by PR #84. Thanks @jamestutton!