Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible new auth flow? #6

Open
IdealText opened this issue Dec 30, 2024 · 23 comments
Open

Possible new auth flow? #6

IdealText opened this issue Dec 30, 2024 · 23 comments

Comments

@IdealText
Copy link

Python version: 3.11
OS: MacOS 15.2
fetched from master, v1.1.0

I have recently signed up to ubank and looking for a way to get my transaction history and was trying out this project. I hit a few issues with the sign up process.

In the response to https://api.ubank.com.au/app/v1/challenge/otp I was getting the error:

{'message': 'Invalid request: flowId not valid uuid', 'stackError': {'code': 'FEA-400'}}

I looked at the response payload from https://api.ubank.com.au/app/v1/challenge/password and saw it included the flowId. I included this in the json of the request to otp and got back a payload, but it was different to what was expected. It was the following

{
  "accessToken": "removed",
  "sessionToken": "removed",
  "expiresIn": 600,
  "userId": "removed",
  "username": "removed",
  "mobileNumber": "removed",
  "email": "removed",
  "refreshToken": "removed",
  "refreshExpiresIn": 600,
  "type": "bearer"
}

Missing authKey.

I played around further to see what may be going on, I noticed that when I login to the app on my phone I am unable to have a persistent login. If I use username + password + SMS, then each time I access the app I have to reauthenticate. This is then pushing me to use a passkey in the UI.

Is it possible that ubank have moved to remove long lived logins, at least for new users?

@jakepronger
Copy link
Contributor

I've noticed this myself and don't think it evens works now even with a device already registered. Will look into this later when I get more time, but it does appear that they've changed some internal auth things to make it more complicated. Maybe there is a way to automate or generate a passkey instead and replicate the same behavior with this new auth method.

@eidorb
Copy link
Owner

eidorb commented Jan 6, 2025

Yes enrolling fails for me after the OTP step too. But using my existing credentials still works.

I will look into the passkey route as that should be more future proof. A fun challenge too I'm sure.

@jakepronger
Copy link
Contributor

Yes enrolling fails for me after the OTP step too. But using my existing credentials still works.

I will look into the passkey route as that should be more future proof. A fun challenge too I'm sure.

Yes. Been looking at this now and notice the request doesn't return the authKey needed to access the account. Been debugging with this but I wanted to know whether you used any tools to intercept any https traffic with the app itself when you started out this project?

@jakepronger
Copy link
Contributor

jakepronger commented Feb 8, 2025

I need to understand the structure of the request referencing this section of code

            response = client.post(
                "https://api.ubank.com.au/app/v1/long-life-token/login",
                json={
                    #"authKey": device.auth_key,
                    "deviceUuid": device.device_id,
                    "secret": device.secret,
                    "token": device.token,
                    "username": device.username,
                },
            )

@jakepronger
Copy link
Contributor

I can use inspect element and connect my mobile to track all of the requests and see it's contents. I've done some things but the authKey is missing from one of the request's responses. Does anyone know the format of the authKey or does it look like the normal token.

@eidorb
Copy link
Owner

eidorb commented Feb 10, 2025

Looks base64ish. Same as token.

See towards top of README. I'm pretty sure that's the actual format and I changed some characters here and there.

@jakepronger
Copy link
Contributor

Is it the same value as 'token' or should be different?

@eidorb
Copy link
Owner

eidorb commented Feb 10, 2025

They are different. You get them at various stages during initial device enrolment:

ubank/ubank.py

Line 274 in eced2e7

auth_key=otp_response.json()["authKey"],

ubank/ubank.py

Line 279 in eced2e7

token=response.json()["token"],

And when you login, I think they update with new values.

@jakepronger
Copy link
Contributor

jakepronger commented Feb 11, 2025

They don't send an authKey in the otp response anymore. Nothing new in the headers either.

This is all we are given in the otp response:

{
    "accessToken": "",
    "sessionToken": "",
    "expiresIn": 600,
    "userId": "",
    "username": "",
    "mobileNumber": "",
    "email": "",
    "refreshToken": "",
    "refreshExpiresIn": 600,
    "type": "bearer"
}

@jakepronger
Copy link
Contributor

jakepronger commented Feb 11, 2025

Not sure what can be done about this but still looking into it. I'm not able to replicate any long life token requests using the app normally in any way so I can't see if anything is different with how that works either. But yeah, we don't get an auth key and the long life token request 'https://api.ubank.com.au/app/v1/long-life-token/login' seems to be wanting one.

@eidorb
Copy link
Owner

eidorb commented Feb 11, 2025

Yeah I think this method is busted for enrolling new devices. They are forcing SMS OTP for every login with password auth.

Interestingly my old auth key and token still works ok.

@jakepronger
Copy link
Contributor

Very interesting. If only there was a way to find that auth key that they are not providing us. My old auth key doesn't work but I'm pretty sure that's because of something I may have done, I don't remember.

error response: {'message': '', 'stackError': {'detailMessage': {}, 'message': 'Invalid device binding. Rebind device via device activation', 'code': 'IDENTITY-LOGIN_FAILED_INVALID_BINDING'}}

@jakepronger
Copy link
Contributor

jakepronger commented Feb 11, 2025

The flowId is an easy fix just by providing it in the otp_response post.

        # Authenticate with second factor: a security code sent to mobile.
        otp_response = client.post(
            url="https://api.ubank.com.au/app/v1/challenge/otp",
            # Set parameters returned in previous response.
            params={
                "nonce": response.json()["nonce"],
                "state": response.json()["state"],
                "session": response.json()["session"],
            },
            json={
                "deviceId": device_id,
                "hashedPin": hashed_pin,
                "flowId": flowId,
                # Prompt interactively for security code.
                "otpValue": input(
                    f'Enter security code sent to {response.json()["maskedMobileNumber"]}: '
                ),
            },
            # Set access and auth token headers from previous response.
            headers={
                "x-access-token": response.json()["accessToken"],
                "x-auth-token": response.json()["accessToken"],
            },
        )

and getting the flowId from the previous request

        # Next, authenticate with password.
        response = client.post(
            url="https://api.ubank.com.au/app/v1/challenge/password",
            json={"deviceName": device_name, "password": password},
            # Set access and auth token headers from previous response.
            headers={
                "x-access-token": response.json()["accessToken"],
                "x-auth-token": response.json()["accessToken"],
            },
        )

        flowId = response.json()["flowId"]

@jakepronger
Copy link
Contributor

jakepronger commented Feb 12, 2025

It does look like we will need to change this up and use some kind of passkey authentication. They use FIDO2 password less passkeys which I'm just looking into now and seeing what I can try and do with this. I've got no work tomorrow so I should be able to draft up something after learning a bit about this tonight.

@eidorb
Copy link
Owner

eidorb commented Feb 12, 2025

Cool! I've started to look into it too. I'm able to create virtual passkeys without a browser or hardware device using this https://github.com/bodik/soft-webauthn

@jakepronger
Copy link
Contributor

Very interesting. I will look at that too.

@eidorb
Copy link
Owner

eidorb commented Feb 12, 2025

I've managed to add a new passkey with Python. There's a bit more to do, but a promising step.

Image

@jakepronger
Copy link
Contributor

Very cool. I got called into work so I guess i will have to look into this tonight.

@eidorb
Copy link
Owner

eidorb commented Feb 14, 2025

I've released a package with passkey support. The README has been updated with new instructions.

It's pre-release so you'll have to specify the version when installing: pip install ubank==2.0.0rc0.

@eidorb
Copy link
Owner

eidorb commented Feb 14, 2025

New pre-release changes the passkey serialization format: pip install --pre --upgrade ubank

@jakepronger
Copy link
Contributor

Woah. You did good stuff. I'm going to look into doing CommBank as I want to automate transactions between my two accounts but that passkey thing is so good.

@eidorb
Copy link
Owner

eidorb commented Feb 22, 2025

Image

😆

@jakepronger
Copy link
Contributor

Nice. I need to look into commbank but can't see the requests easily.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants