walle89 / SwedbankJson

Unofficial API client for the Swedbank's and Sparbankerna's mobile apps in Sweden.
MIT License
75 stars 14 forks source link

Update MobileBankID.php #42

Closed matthiaspalmer closed 3 years ago

matthiaspalmer commented 3 years ago

Authentication stopped working with the following exception: Uncaught SwedbankJson\Exception\ApiException: general (1): BankIdOnSameDeviceAttributeNotProvided - Det gick inte att logga in. Din klient skickade inte in valet om BankID finns installerad på detta enhet eller ej.; fields (1): Valet av enhet för BankID angavs ej.

From the name of the error it was quite easy to guess that the attribute needed was "bankIdOnSameDevice".

matthiaspalmer commented 3 years ago

I was a bit to quick to declare success. I do not get the same exception anymore, but I do not get a confirm message in the BankId mobile app unfortunately. I guess someone need to take a deeper look on why it is not working.

Sunnanangs commented 3 years ago

If you have Mobile Bank ID installed on the device. Then the bankIdOnSameDevice parameter should be true and open with the autostarttoken parameter returned from the API together with a redirect URL (reference).

If you use another device (e.g. a computer), then the bankIdOnSameDevice parameter should be false, and you have to show the QR code returned from the identification/bankid/mobile/image endpoint and scan it with the Bank ID app.

walle89 commented 3 years ago

I have done some tests and have done some quick initial look into it.

It appears that Swedbank in the latest version of the app have changed the implementation method of the mobile bank ID to a updated one. The old method worked by sending the username along with the request to Swedbank's servers and they did initiate the authentication to BankID on there end. The new one seems that the Swedbank app is either directly communicating with the local BankID app, or sign in with an animated QR code if you sign in with an external device. Either method sends the username, it uses whatever personal identity number that is connected to the BankID app.

In other words there is no quick fix for this issue, I think rewrite of the BankID authentication method needs to be done in this case (if it's possible to do in the first place). Currently I don't really have the time to do this in the near feature and the only workaround would be to use hardware security token authentication instead.

Thank you @matthiaspalmer for your contribution with this pull request. You are welcome to update the code until it's working, or create a separate pull request with working code. :)

NisseDILLIGAF commented 3 years ago

Hi

I looked at @matthiaspalmer code in AbstractAuth.php and MobileBankID.php. I did it a bit different, but his looks better 👍 Very nice!

Only things I've done different is I return contents in function QRCode. link

return (string) $output->getBody()->getContents();

My PHP login looks like this.

session_start();

// Step 1 - Start the authentication process
if (!isset($_SESSION['swedbankjson_auth']))
{
    $appData = new SwedbankJson\AppData($bankApp, __DIR__.'/AppData.json');
    $auth    = new SwedbankJson\Auth\MobileBankID($appData);
    $auth->initAuth();
}

// Step 2 - Verify authentication
$auth = unserialize($_SESSION['swedbankjson_auth']);
if (!$auth->verify()){
    $img = $auth->QRCode();
    $src = 'data: image/png ;base64,'.base64_encode($img);
    echo "<p><img src=\"$src\" ></p>";
    exit("Open the BankID app and scan the QR code. Then refresh the page.");
}

// Step 3 - You are in!
$bankConn = new SwedbankJson\SwedbankJson($auth);

and I removed private $_username;, because what I can see you don't need It anymore.

I also changed 'setBaseUri' in UnAuth.php

$this->setBaseUri('https://auth.api.swedbank.se/TDE_DAP_Portal_REST_WEB/api/');

And changed to 'v5' in AbstractAuth.php

private $_apiVersion = 'v5';

or else I cant get quick balance..

walle89 commented 3 years ago

Nice work @NisseDILLIGAF!

Do you get the QR code as regular static PNG or as an animated PNG (APNG)? If static, do you know how long is that image valid?

If you want to, you cloud make a pull request so that I can include your changes in upcoming release. Otherwise I will write my on solution based on your findings. Would you like in that case to credit you for your contribution? I have the same offer for you too @matthiaspalmer. :)

NisseDILLIGAF commented 3 years ago

It's a static PNG, you can update the page just before you scan the QR code. I think It's only valid for a second or two?

I have used @matthiaspalmer code, because it was nicer than my 'fast and easy' way :) So I don't know if I should make a pull request with his code. I think we'll wait and see what he says.

EDIT: Maybe he can make a pull request with his code and after I make the changes I made in my pull request? Doesn't matter to me...

One other thing I've noticed is that my quickBalance ID stops working after a while. And now when I intercepted the trafik on swedbank I noticed this. It's a PUT request for quickBalance

{
    "balanceForCustomer": true,
    "expirationDate": "2021-06-18T21:20:11+02:00",
    "expirationMessage": "Var 90:e dag behöver du godkänna din användning av snabbsaldo. Ditt snabbsaldo har avaktiverats eftersom vi inte har fått ditt godkännande.",
    "links": {
        "edit": {
            "method": "PUT",
            "uri": "/v5/quickbalance/subscription/pb06K6RkPxxxxxxxxxxxxxxxxxxxxx6iIJqTbclwn0="
        }
    }
}

I made a PUT request now, but I get this error

AUTHORIZATION_FAILED - Wrong user role NEUTRAL in /home/pi/SwedbankJson/vendor/walle89/swedbank-json/src/Auth/AbstractAuth.php:312

Do you know what this mean?

walle89 commented 3 years ago

Okey, it would be nice to implement a super simple javascript based reload of the QR code. That's something I can look into after 1.0.0 (beta/RC) release, otherwise adding text such as "Reload page before scan" in the example code would probably be enough for someone that's trying to use SwedbankJson for the first time.

EDIT: Maybe he can make a pull request with his code and after I make the changes I made in my pull request? Doesn't matter to me...

Either that or you do a pull request to this repo and your commits will be added in Mattias's pull request. Do what works for both of you. :)

Do you know what this mean?

My best guess is you are trying to do the PUT-request with the "No authentication" method. I think this needs to be done with BankID or Hardware token if this works at all. I don't use Quickbalance, so I have no practical experience other than testing the endpoints and document them. :(

matthiaspalmer commented 3 years ago

Alright, so I made a new PR with the code mentioned as I could not figure out how to update this one. This is the new PR https://github.com/walle89/SwedbankJson/pull/43.

@NisseDILLIGAF feel free to do further improvements!

Always nice with getting credit @walle89 :-)

In case you are interested in projects using the repository, here is a wrapper project (it provides a simple REST API) to make it easier to integrate into non-PHP projects.

Overall, big thanks for maintaing this project @walle89 , it really makes a difference for us at Uppsala Makerspace.

walle89 commented 3 years ago

Good news, I have updated the pre-alfa-1.0.0 branch with the following:

That's right, if you want to authentication with SwedbankJson in a web browser on a mobile device with BankID app installed you can now authenticate with BankID. I discovered the Swedbank API do provide an Auto Starter Token, witch is used to initiate the authentication process in the app.

Now I need some help with a bit of testing and input if I need to do any changes or have any suggestions how this can be improved.

How do I test?

1a I have existing pre-alpha-1.0.0 project

Run composer update, move to step 2.

1b. I have not used pre-alpha-1.0.0

In short, read this comment and follow the thread. Hopefully I will have more proper documentation in place for version 1.0.0 launch.

2. Update BankID authentication

I haven't spend any time on documentation such as change log or migration guides. My tips is to check the latest commits in the pre-alpha-1.0.0 branch or use this example code:

Updated 2021-08-14

<?php
session_start();
require_once '../vendor/autoload.php';

if (!isset($_GET['authType'])) {
    echo '<strong>Select Mobile BankID Method</strong><br><a href="?authType=0">QR Code</a> - <a href="?authType=1">Same Device</a>';
    exit;
}

$bankApp    = 'swedbank';   // Select bank app
$auth       = null;
$sameDevice = (bool)$_GET['authType'];
try {
    // Step 1 - Start the authentication process
    if (!isset($_SESSION['swedbankjson_auth']))  {
        $appData = new SwedbankJson\AppData($bankApp, __DIR__.'/AppData.json');
        $auth    = new SwedbankJson\Auth\MobileBankID($appData);
        $auth->sameDevice($sameDevice);
        $auth->initAuth();

        if ($sameDevice)  {
            // For automatic redirect from BankID app, replace "null" with URL to this script.
            $redirectURL = urlencode('null');
            $bankIdAppUrl = sprintf(
                 'https://app.bankid.com/?autostarttoken=%s&redirect=%s',
                 $auth->getAutoStartToken(),
                 $redirectURL
           );
            echo '<strong>Instructions: Sign in with Mobile BankID on same device</strong>';
            printf('
                <ol>
                    <li><a href="%s">Use this link to authenticate in BankID app</a></li>
                    <li>Go back to this page and reload it</li>
                </ol>',
                $bankIdAppUrl
            );
        }  else  {
            // Need to reload page
            echo '<meta http-equiv="refresh" content="0">';
        }
        exit;
    }
    // Step 2 - Verify authentication
    $auth = unserialize($_SESSION['swedbankjson_auth']);

    if (!$auth->verify())   {
        if ($sameDevice)   {
            echo '<p>Waiting for verification. This page will update automatically.</p>';
        }  else  {
            // Reload page once per 2 seconds.
            echo '<meta http-equiv="refresh" content="2">';
            echo '<strong>Instructions</strong>
                  <ol>
                      <li>Open the BankID app</li>
                      <li>Press "Scan QR code" and scan the QR code below.</li>
                      <li>Done, this page will update automatically.</li>
                  </ol>';
            printf(
                '<img src="data:image/png;base64,%s" style="max-width:100%%">',
                base64_encode($auth->getChallengeImage())
            );
        }
        exit;
    }
    // Step 3 - You are in!
    $bankConn = new SwedbankJson\SwedbankJson($auth);
} catch (Exception $e) {
    exit($e->getMessage());
}

// Example of account details call. See documentation for details.
echo '<h1>Account details</h1><pre>';
print_r($bankConn->accountDetails());

// Sign out. If you want to keep the session to next page load, remove this line.
$bankConn->terminate();

3. Run the code

Note that same device tests need to be done in the browser of the phone. Copy the link and run it in the browser is tricky, sense the link like the QR code are only valid for a very short period.

TODO

Mostly write documentation, maybe also write a migration guide. Otherwise I try to minimize the scope of 1.0.0 just in order to get this out soon as possible so that people can start fixing there projects.

walle89 commented 3 years ago

@matthiaspalmer Glad that to hear that Uppsala Makerspace have use of this project. :) The wrapper is an interesting approach allow to interact with the this project.

walle89 commented 3 years ago

It has been a while, but I finally got around to document and changed some things. I would appreciate if you cloud leave any feedback, otherwise I think I will just publish this more or less "as is".

What changed:

If you want to test the new code, follow instructions in one of my previous comments.

NisseDILLIGAF commented 3 years ago

It has been a while, but I finally got around to document and changed some things. I would appreciate if you cloud leave any feedback, otherwise I think I will just publish this more or less "as is". ....

Sorry for the late response. This looks really good and as far as I tested, works as it should 👍

Great work!

I like the 'sameDevice' solution... you can even pass that link to your mobile from your computer to verify. (dont know how secure that is) But it works :) I used joaoapps Join to send it through my local network (encrypted) to my Android phone

Now we just have to figure out how to generate the 'new Dosa' with color qr-code :stuck_out_tongue_winking_eye: image

walle89 commented 3 years ago

Great work!

Thank you.

I like the 'sameDevice' solution... you can even pass that link to your mobile from your computer to verify. (dont know how secure that is) But it works :)

Well it depends. The token itself has very short lived (I believe less than 1 minute) and you need to verify the authentication with the BankID app. So in that regard I don't see any major issues with it. But with that said, I think it's safer to just share the link to the script instead of the same device URL. Then you can make sure that the token stays on the device and is only handled by the browser and the BankID app. In other words, just use the sample code and it should be reasonable safe if the communication is restricted to a safe private network or over an encrypted connection (eg. HTTPS). Or just use the BankID QR-code instead. :)

walle89 commented 3 years ago

Version 1.0.0 released with pre-alfa fixes.

Read this comment for more info.