femueller / python-n26

💵 Unofficial Python client for n26 (Number 26) - https://n26.com/
MIT License
195 stars 34 forks source link

Authentication error 400 Bad Request #81

Closed nathanmarcos closed 4 years ago

nathanmarcos commented 4 years ago

Something seams changed on their side since the /oauth2/token is always failing with status 400. 😞

➜  n26 balance
Initiating authentication flow, please check your phone to approve login.
Traceback (most recent call last):
  File "/usr/local/bin/n26", line 10, in <module>
    sys.exit(cli())
  File "/usr/local/lib/python3.7/site-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.7/site-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python3.7/site-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.7/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/n26/cli.py", line 44, in wrapper
    API_CLIENT.authenticate()
  File "/usr/local/lib/python3.7/site-packages/n26/api.py", line 315, in authenticate
    token_data = self._request_token(self.config.USERNAME.value, self.config.PASSWORD.value)
  File "/usr/local/lib/python3.7/site-packages/n26/api.py", line 382, in _request_token
    mfa_token = self._initiate_authentication_flow(username, password)
  File "/usr/local/lib/python3.7/site-packages/n26/api.py", line 397, in _initiate_authentication_flow
    raise ValueError("Unexpected response for initial auth request: {}".format(response.text))
ValueError: Unexpected response for initial auth request: {"timestamp":"2020-06-17T08:04:29.170+0000","status":400,"error":"Bad Request","message":"invalid_request","path":"/oauth2/token"}
robbieffm commented 4 years ago

same here... any solutions? ;)

femueller commented 4 years ago

I've been reaching out to N26 about this. Let's see.

ivallesp commented 4 years ago

Same issue here :). Thanks for looking at it @femueller. Is there anything we can help with?

markusressel commented 4 years ago

@ivallesp Currently we are only awaiting if and how N26 responds to our "call". If you can spare the time feel free to deep dive into figuring out a solution, but I have to warn you, I don't believe we can fix it easily this time... PSD2 doesn't exactly make our lifes easier 😞

robbieffm commented 4 years ago

I got a solution via trail and error:

just enter a slash "/" after token in the request url :)

oauth2/token/

ivallesp commented 4 years ago

I got a solution via trail and error:

just enter a slash "/" after token in the request url :)

oauth2/token/

Any pull request? :)

robbieffm commented 4 years ago

I wrote my script in php, so no pull request for this code here :)

But does the solution works for you, too?

femueller commented 4 years ago

@robbieffm Yes, I can confirm that it's working with the Python code as well. Thanks for your observation! :smiley:

femueller commented 4 years ago

The Python package has just been updated. Please verify via:

pip install --upgrade n26
ivallesp commented 4 years ago

I can confirm. It's working like a charm again. Thanks @robbieffm and @femueller!

For poetry users, you can run poetry update n26 😉

nathanmarcos commented 4 years ago

I also confirmed here, that works like a charm. Thanks a lot!

robbieffm commented 4 years ago

unfortunately the same issue again

stdClass Object
(
    [timestamp] => 2020-06-25T20:58:55.804+0000
    [status] => 400
    [error] => Bad Request
    [message] => invalid_request
    [path] => /oauth2/token/
)
robbieffm commented 4 years ago

I contacted N26 Support. I hope I will get response.

But by the way, do you have the same issue like me, again?

gsalvatori commented 4 years ago

Same issue for me:

requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://api.tech26.global/oauth/token/

nathanmarcos commented 4 years ago

Did you try to remove the / that we just added? This sounds silly but, why not?

robbieffm commented 4 years ago

Did you try to remove the / that we just added? This sounds silly but, why not?

Yes, but don’t work. 😕

ivallesp commented 4 years ago

I confirm I have the issue too... I can also confirm that removing the bar (or switching python-n26 from 2.2.2 version to 2.2.1) doesn't work, raising:

requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://api.tech26.global/oauth/token

:(

ivallesp commented 4 years ago

I contacted N26 Support. I hope I will get response.

But by the way, do you have the same issue like me, again?

Is there any news? It's already end of month :(

robbieffm commented 4 years ago

I contacted N26 Support. I hope I will get response. But by the way, do you have the same issue like me, again?

Is there any news? It's already end of month :(

I got no answer until now. ;(

robbieffm commented 4 years ago

As an interim solution, I login and read the website with a script. After login is a JavaScript data array available, which I convert in a json object.

Not the best way, but it works to get the account amount and the transactions including the Id.

But anyway, I hope there is a solution for the api available soon.

charlesvestal commented 4 years ago

As an interim solution, I login and read the website with a script. After login is a JavaScript data array available, which I convert in a json object.

Could you share the script? 😅

robbieffm commented 4 years ago

As an interim solution, I login and read the website with a script. After login is a JavaScript data array available, which I convert in a json object.

Could you share the script? 😅

Well, 😂

My PHP script is just a interim solution, without any comments and written in a (bad) fast way. So I guess it’s not a good idea to share. 😋

But you can use these steps:

  1. call the Website app.n26.com/login (curl, enable the cookie file) to get the hidden form fields

  2. post your login values to the form action including the hidden field’s

  3. you get a confirmation push to you Mobile Phone

  4. call the Webseite again. Your are logged in And you will get requested data and the JavaScript data array.

markusressel commented 4 years ago

@robbieffm can you retrieve the auth token that way too? Would be a hack, but maybe the easiest workaround for now. I am not sure how to find out the new API endpoint (if it even exists).

ivallesp commented 4 years ago

I have contacted the N26 Support. They directed me to the live chat. I’ve contacted the Live chat and they have no idea about what is an API. Did you get any successful technical help in the past? Where did you find official docs to implement the Python API?

ivallesp commented 4 years ago

@robbieffm can you retrieve the auth token that way too? Would be a hack, but maybe the easiest workaround for now. I am not sure how to find out the new API endpoint (if it even exists).

Fully agree on the token part. That would be a great workaround. I tried but no success but I am not an expert on that.

ivallesp commented 4 years ago

They have sent me this now: https://support.n26.com/en-de/security/open-banking-psd2/psd2-open-banking-for-third-party-providers

dequis commented 4 years ago

Yeah, just ignore token.io and other open banking/PSD2 stuff. It's not usable by individuals.

  1. you have to be a "Qualified Third Party Service Provider" https://n26.docs.token.io/#on-boarding-for-tpps
  2. it's very likely to be a paid service that isn't cheap (has no public pricing page) and has no interest in dealing with anyone but corporations

They usually bring that up when you ask support about API stuff (see for example https://github.com/femueller/python-n26/issues/67#issuecomment-558885719)

If this keeps up i'm just going to move to bunq, you gotta pay for the account but at least they have a nice officially supported developer friendly API, and not having to worry about this anymore would be worth it. I'm not giving up yet though, maybe the next time they break it, because changing main accounts is hard.

I'll give this thing a look on the weekend.

robbieffm commented 4 years ago

@robbieffm can you retrieve the auth token that way too? Would be a hack, but maybe the easiest workaround for now. I am not sure how to find out the new API endpoint (if it even exists).

I tried to explore the token on the website, but unfortunately i didn’t found a working token. I guess there are different token for the api.tech26 and app.n26.de

They have sent me this now: https://support.n26.com/en-de/security/open-banking-psd2/psd2-open-banking-for-third-party-providers

i found this site as well, but with this api you need to send a very expensive certificate while requesting the data. https://www.sslmarket.de/ssl/quovadis-qualified-website-authentication-certificate-qwac/

markusressel commented 4 years ago

@ivallesp On github, gathered by other, more intelligent people than me. I guess they extracted them from sniffing the App's network traffic. @dequis I am so sad that N26 isn't doing that :( As a bank for the young people I thought they would do exactly that, instead they don't even answer our messages. I am very dissappointed of the way N26 is working now. Maybe I will change to a different bank too, but how long before they kill their API too? PSD2 is one of the worst things that happened to online banking :(

ivallesp commented 4 years ago

Yeah, just ignore token.io and other open banking/PSD2 stuff. It's not usable by individuals.

  1. you have to be a "Qualified Third Party Service Provider" https://n26.docs.token.io/#on-boarding-for-tpps
  2. it's very likely to be a paid service that isn't cheap (has no public pricing page) and has no interest in dealing with anyone but corporations

They usually bring that up when you ask support about API stuff (see for example #67 (comment))

If this keeps up i'm just going to move to bunq, you gotta pay for the account but at least they have a nice officially supported developer friendly API, and not having to worry about this anymore would be worth it. I'm not giving up yet though, maybe the next time they break it, because changing main accounts is hard.

I'll give this thing a look on the weekend.

Thanks for looking at it.

I checked Banq and yes, their API is official and well documented. Are you sure you have to pay for using it? They seem to have free plans.

pscheit commented 4 years ago

@markusressel theres is unfortunately nothing what N26 is allowed to do. They had this bounty programm and within it the ability to get the transactions with this api, but PSD2 was introduced to remove those not documentend and open api accesses to everyone to make it more safe. Bad for us, who just want to have a quick hack. Good for the security. I hate it too, but I see why this was done. It's not N26s fault!

I will try tink for accessing n26

rautex commented 4 years ago

@markusressel theres is unfortunately nothing what N26 is allowed to do. They had this bounty programm and within it the ability to get the transactions with this api, but PSD2 was introduced to remove those not documentend and open api accesses to everyone to make it more safe. Bad for us, who just want to have a quick hack. Good for the security. I hate it too, but I see why this was done. It's not N26s fault!

I will try tink for accessing n26

Is it not now thaht they changed theyre system and req now a ssl cert? Nginx told me this.

In my opinion its a shame for a bank which call themself a bank for IT and Freelancer but dont support such things compared to other who support hbci.

The Windows Version of Banking4 who also used the api dont support it anymore.

dequis commented 4 years ago

I will try tink for accessing n26

Ooh, thanks for mentioning tink! Looks like a PSD2 API that's usable by individuals and supports n26.

I just created an account, an app, a tink link, used the link to log in with my user/pass, confirmed the login on the n26 phone app, got a code, and ran this to get account details and the last transaction.

http -f POST https://api.tink.com/api/v1/oauth/token code=... client_id=... client_secret=... grant_type=authorization_code
token=...
http https://api.tink.com/api/v1/accounts/list "Authorization: Bearer $token"
http https://api.tink.com/api/v1/search "Authorization: Bearer $token" sort=date limit=1

Hardest part was figuring out that I needed to look for the search docs to list transactions, and figuring out what they mean by aggregation (seems to mean bank log in). The rest was super smooth.

This looks like it achieves what everything else failed to deliver about PSD2.

Things I'm not a fan of:

Cheaper than bunq, but I'm pretty sure this weird login flow wouldn't be an issue there.

I checked Banq and yes, their API is official and well documented. Are you sure you have to pay for using it? They seem to have free plans.

Yeah bunq's new free plans are weird (what even is a travel card?) but API support says "N/A" for those.

They had this bounty programm and within it the ability to get the transactions with this api, but PSD2 was introduced to remove those not documentend and open api accesses to everyone to make it more safe.

It's still there, https://n26.com/en-eu/bug-bounty-program says "If you Google N26 API you may find some un-officials wrapper to our API", which I always found funny.

but PSD2 was introduced to remove those not documentend and open api accesses to everyone to make it more safe.

They can't remove this, their own phone app uses it. They can only break it (and every time they do so, they force updates of their own app, because you gotta have backwards compat to deal with people who have automatic updates disabled)

markusressel commented 4 years ago

I am also not buying this "make it more safe" stuff. Its just a way to have banks (or third parties) make even more money on basic stuff like listing transactions. There is nothing "open" about it as far as I am concerned. I will not support this crap by paying money to some third Party service, thats probably selling all my transaction data to some data broker anyway. DiBa currently still supports FinTS, which still works great, and I hope they dont drop support, but there is nothing stopping them from doing so...

rautex commented 4 years ago

I am also not buying this "make it more safe" stuff. Its just a way to have banks (or third parties) make even more money on basic stuff like listing transactions. There is nothing "open" about it as far as I am concerned. I will not support this crap by paying money to some third Party service, thats probably selling all my transaction data to some data broker anyway. DiBa currently still supports FinTS, which still works great, and I hope they dont drop support, but there is nothing stopping them from doing so...

this is also complete nonsense by n26, even that u every time have to do this 2 factor auth.

Ing Diba and DKB also the German Sparkasse req the tan every 90 days for read transactions, that is what PSD2 req, i have talked long time with guys from IT of the Sparkasse.

HBCI is used by tax accountants and some other, i don’t think they will drop it and well on n26 the tax accountant "cried" since some years that the connection is more than shit.

To bad that ING and DKB don’t offers B2B for companies.

limolitz commented 4 years ago

I just decompiled the N26 app and it looks like the new URL is /oauth2/token. But if you just change it to that, it doesn't work yet, so something else changed as well.

rautex commented 4 years ago

@wasmitnetzen yap i had used this some time ago, i had sniffed me the url from banking4 but now its seems not work anymore

ivallesp commented 4 years ago

I tried this too based in the message of error that we were having, but no luck, unfortunately.

El 3 jul 2020, a las 20:36, wasmitnetzen notifications@github.com escribió:

 I just decompiled the N26 app and it looks like the new URL is /oauth2/token. But if you just change it to that, it doesn't work yet, so something else changed as well.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

robbieffm commented 4 years ago

I just decompiled the N26 app and it looks like the new URL is /oauth2/token. But if you just change it to that, it doesn't work yet, so something else changed as well.

I used this URL „oauth2/token“ all the time. It stopped working at the same time like „oauth/token“

I guess we need to know a hidden parameter while requesting the first token with grand_type password. The error message is invalid request. I think the path did not change.

Quote from: https://www.oauth.com/oauth2-servers/access-tokens/access-token-response/

„The request is missing a parameter so the server can’t proceed with the request. This may also be returned if the request includes an unsupported parameter or repeats a parameter.“

joehoyle commented 4 years ago

Has anyone managed to bypass the SSL certificate pinning in the n26 app? Reading https://blog.netspi.com/four-ways-to-bypass-ios-ssl-verification-and-certificate-pinning/ it looks like it might be doable on jailbroken iOS devices.

limolitz commented 4 years ago

I guess we need to know a hidden parameter while requesting the first token with grand_type password. The error message is invalid request. I think the path did not change.

There are four possible parameter sets in the code:

    • refresh_token
    • grant_type
    • username
    • password
    • grant_type
    • mfaToken
    • grant_type
    • challenge
    • nonce
    • signature.value
    • signature.oneStepPayload
    • mfaToken
    • grant_type
    • otp

Our current parameter set is is still there (2.). I can't tell if it is still being used, that requires a lot more digging in the decompiled code.

dequis commented 4 years ago

To bypass pinning on android:

  1. Have your cert in /system/etc/security/cacerts/
  2. Setup frida per https://frida.re/docs/android/
  3. frida --no-pause -U de.number26.android
  4. Java.perform(function(){Java.use("okhttp3.CertificatePinner")['check$okhttp'].implementation = function(){}})

There are other variants of this bypass in frida codeshare, but apparently check$okhttp is the important bit because the current version of okhttp moved the actual implementation to an internal method, and the public one isn't called.

dequis commented 4 years ago

The first four requests (lightly edited/redacted), from a paired device with fingerprint login:

First request, GET /fpt ``` GET /fpt HTTP/1.1 User-Agent: n26-android_3.46.1 Accept-Language: en n26-locale: en-GB n26-timezone: UTC+02:00 device-token: [redacted] Connection: Keep-Alive Accept-Encoding: gzip If-Modified-Since: Fri, 03 Jul 2020 22:29:33 GMT HTTP/1.1 200 OK Server: awselb/2.0 Date: Fri, 03 Jul 2020 22:34:03 GMT Content-Type: application/json; charset=utf-8 Content-Length: 44 Connection: keep-alive {"login": {"delay": 10, "probability": 100}} ```
Second request, GET /api/version/mobile?os=android ``` GET /api/version/mobile?os=android HTTP/1.1 User-Agent: n26-android_3.46.1 Accept-Language: en n26-locale: en-GB n26-timezone: UTC+02:00 device-token: [redacted] Connection: Keep-Alive Accept-Encoding: gzip If-Modified-Since: Fri, 03 Jul 2020 22:29:33 GMT HTTP/1.1 200 OK Date: Fri, 03 Jul 2020 22:34:03 GMT Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Connection: keep-alive Server: nginx Vary: Accept-Encoding x-content-type-options: nosniff x-frame-options: DENY x-xss-protection: 1; mode=block x-request-id: [redacted] X-Frame-Options: SAMEORIGIN X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block content-length: 1098 44a { "mandatory": { "description": { "de": "Deine Version der N26 App ist veraltet. Bitte lade die neuste Version im Google Play Store herunter, um die aktuellsten Features und Sicherheitsverbesserungen zu erhalten.", "en": "Your version of the N26 app is out of date. Please download the most recent version from the Google Play Store to get the latest features and security enhancements." }, "timestamp": 1473948227000, "version": "3.36", "marketPlaceUrl": null }, "latest": { "description": { "de": "Deine Version der N26 App ist veraltet. Bitte lade die neuste Version im Google Play Store herunter, um die aktuellsten Features und Sicherheitsverbesserungen zu erhalten.", "en": "Your version of the N26 app is out of date. Please download the most recent version from the Google Play Store to get the latest features and security enhancements." }, "timestamp": 1473948227000, "version": "3.36", "marketPlaceUrl": null }, "featureToggles": [ { "id": "b65480dc-ccc1-48be-8e4f-1e55de64d668", "enabled": true, "feature": "WEB_CHAT_SUPPORT" }, { "id": "d9b37587-c278-43d8-bd08-86d1810299b0", "enabled": true, "feature": "SIGNUP_WITHOUT_INVITECODE" } ] } 0 ```
Third request, POST /oauth2/token ``` POST /oauth2/token HTTP/1.1 User-Agent: n26-android_3.46.1 Accept-Language: en n26-locale: en-GB n26-timezone: UTC+02:00 device-token: [redacted] Authorization: Basic bmF0aXZlYW5kcm9pZDo= Content-Type: application/x-www-form-urlencoded Connection: Keep-Alive Accept-Encoding: gzip refresh_token=[redacted]&grant_type=refresh_token HTTP/1.1 403 Forbidden Date: Fri, 03 Jul 2020 22:34:04 GMT Content-Type: application/problem+json Content-Length: 517 Connection: keep-alive Server: nginx cache-control: no-store x-xss-protection: 1; mode=block pragma: no-cache x-frame-options: DENY x-content-type-options: nosniff x-content-type-options: nosniff x-frame-options: DENY x-xss-protection: 1; mode=block x-request-id: [redacted] { "userMessage": { "title": "A second authentication factor is required.", "detail": "Please provide your second form of authentication." }, "mfaToken": "[redacted mfatoken]", "error_description": "MFA token is required", "detail": "MFA token is required", "hostUrl": "https://api.tech26.de", "type": "mfa_required", "error": "mfa_required", "title": "A second authentication factor is required.", "message": "Please provide your second form of authentication.", "userId": "[redacted]", "status": 403 } ```
Fourth request, POST /oauth2/token ``` POST /oauth2/token HTTP/1.1 User-Agent: n26-android_3.46.1 Accept-Language: en n26-locale: en-GB n26-timezone: UTC+02:00 device-token: [redacted] Authorization: Basic bmF0aXZlYW5kcm9pZDo= Content-Type: application/x-www-form-urlencoded Connection: Keep-Alive Accept-Encoding: gzip mfaToken=[redacted mfatoken]&grant_type=mfa_osc&challenge=[redacted]&nonce=[redacted]&signature.value=[redacted long base64]&signature.oneStepPayload=%7B%22challenge%22%3A%22[redacted]%22%2C%22grant_type%22%3A%22mfa_osc%22%2C%22nonce%22%3A%22[redacted]%22%7D HTTP/1.1 200 OK Date: Fri, 03 Jul 2020 22:34:04 GMT Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Connection: keep-alive Server: nginx Vary: Accept-Encoding cache-control: no-store x-xss-protection: 1; mode=block pragma: no-cache x-frame-options: DENY x-content-type-options: nosniff x-content-type-options: nosniff x-frame-options: DENY x-xss-protection: 1; mode=block x-request-id: [redacted] X-Frame-Options: SAMEORIGIN X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block content-length: 185 b9 {"access_token":"[redacted]","token_type":"bearer","refresh_token":"[redacted]","expires_in":1799,"host_url":"https://api.tech26.de"} 0 ```
julian-klode commented 4 years ago

I think what would be useful would be to see data for first login from an unpaired device. Unfortunately, I don't have a rooted device laying around here :-( - I certainly don't see anything new in here.

I wish N26 would just allow us to create personal access tokens and provide a documented API, like bunq does.

bastiandev commented 4 years ago

After playing with the sniffed data by @dequis, I found out, that there is a new mandatory http-header "device-token". The value must be set to the same uuid during the auth flow. I have created the pull request https://github.com/femueller/python-n26/pull/83 for a solution. I also explained my thoughts there.

femueller commented 4 years ago

Thanks a lot for your PR @bastiandev 🎉! The new release 3.0.0 includes the fix proposed by @bastiandev.

FYI: Please make sure to configure a device token ID once you upgraded as described here: https://github.com/femueller/python-n26#device-token

rautex commented 4 years ago

Thanks a lot for your PR @bastiandev 🎉! The new release 3.0.0 includes the fix proposed by @bastiandev.

FYI: Please make sure to configure a device token ID once you upgraded as described here: https://github.com/femueller/python-n26#device-token

thanks, this is now also working for me, perfect, i hope the solution will work longer.

Do u know how long the token is alive withouth reauth it by phone?

markusressel commented 4 years ago

@rautex I dont know if it is still applicable, but see this: https://github.com/femueller/python-n26/issues/67

dequis commented 4 years ago

Device tokens are permanent (and probably best to not rotate them too much)

Access tokens last 30 mins (see the expires_in of the last http response in my previous comment), and fetching a new one will trigger 2fa.