Having trouble with getting authenticated App when deployed remotely

Hi. I am a Speckle newbie and a Streamlit newbie. But I have managed to get Streamlit to talk to Speckle and I can get commits, change their attributes and put a new commit back on the server all through Streamlit and specklepy (and Topologic).
I have also successfully deployed the app to the Streamlit Cloud. Topologic work, speckle works, but I am having trouble getting an authenticated app to see the streams etc.
I DID add an Application to my speckle profile and noted down the App ID and the App Secret.
I also managed to input that into Streamlit and go to the authentication page, click on Allow and it redirects back to my Streamlit app. And when that happens, I can even get the ‘access_code’ as they call it which I assume is the token that I need, but then, this code does not authenticate the app

 #-------
    #CLIENT
    client = SpeckleClient(host=speckleServer)
    #Get account from Token
    account = get_account_from_token(speckleToken, speckleServer)
    #Authenticate
    client.authenticate_with_account(account)
    #-------

Thank you for any help you can provide.

1 Like

In brief, the speckleToken will be an OAuth token. The access_code is what your APP should use to complete the authorization flow.

i.e. your APP (registered as an app in your profile settings) should exchange the access_code for it as the next step in the authentication flow.

by way of a python example:

user = {
        "email": "{{USER_EMAIL}}",
        "password": "{{USER_PASSWORD}}"
}

# How your app registers itself as approved by the user
response = requests.post(
    url=f"HTTP(s)://{{HOST_URL}}/auth/local/register?challenge={{CODE_CHALLENGE}}",
    data=user,
)
access_code = response.url.split("access_code=")[1]

Where CODE_CHALLENGE is the plain text OAuth code challenge. (read more here)

tokens = requests.post(
        url=f"http(s)://{{HOST_URL}}/auth/token",
        json={
            "appSecret": "{{YOUR_APP_SECRET}}",
            "appId": "{{YOUR_APP_ID}}",
            "accessCode": access_code,
            "challenge": "{{CODE_CHALLENGE}}",
        },
    )

At this point, tokens should be a JSON object with both a token and a refreshToken

If we ignore the latter distinction, for now, the token is what is the speckleToken in your example code. The token expiry rate of a :speckle:Speckle server escapes me for now. In truth, there is no harm in always requesting a new token using a refreshToken between sessions. If you pay by the HTTP request, hold on to the token for as long as possible. :thinking:


EDIT: The default lifespan of a token appears to be 10 minutes, and the default lifespan of a refreshToken is 6 months. Or 100000 years - I haven’t quite gotten the bottom of it :smiley:

3 Likes

That is, of course, assuming you want users to authenticate your APP to use their Speckle accounts and content. If you just want to run it as yourself, then you can use Personal Access Tokens instead.

4 Likes

Hi @jonathon. This had worked in past iterations (and I have tweeted about it), but for some reason, now it stopped working. I can verify that:

  1. I have added access to an app with an appID and an AppSecret and verified the strings are correct
  2. I am able to create the challenge and it is accepted by Speckle when it redirects me there.
  3. It redirects to the correct URL
  4. I am able to get an access code upon return from speckle and have verified it.

But when I send:

response = requests.post(
                url=f"https://speckle.xyz/auth/token",
                json={
                    "appSecret": appSecret,
                    "appId": appID,
                    "accessCode": access_code,
                    "challenge": challenge,
                },
            )

I am getting a 401 Unauthorized.
Any help is much appreciated.

Hi @Wassim_Jabi,

I believe you need to include headers in your code as well. Can you try if below code works for you?

response = requests.post(
                url=f"https://speckle.xyz/auth/token",
                headers={
                "Content-Type": "application/json",
                },
                json={
                    "appSecret": appSecret,
                    "appId": appID,
                    "accessCode": access_code,
                    "challenge": challenge,
                },
            )

Hi @gokermu I added the headers, but sadly I still get the 401 response. You can try the app yourself at:
https://wassimj-topologichb-01-app-o4lo2s.streamlitapp.com/
The code is at: TopologicHB/01_app.py at main · wassimj/TopologicHB · GitHub
Thanks for any help you can provide

1 Like

Hey @Wassim_Jabi ,

I’m not going to be very helpful as the code looks correct!
I’d just try registering another app and trying again…

Any more info in the response about the error?

2 Likes

Thank you. I think I found the issue and it has nothing to do with Speckle. It seems upon return from getting an access code, the Streamlit app code is generating a brand new challenge string rather than using the one saved in the session. It seems it is creating a new session at the redirect url.

4 Likes