Login to PremiumSim with Scriptable iOS

742 views Asked by At

I want to create a widget for iOS that shows my mobile traffic usage. To create this widget I want to use Scriptable

I tried to create the needed Http GET and POST requests to login into my account and than to read the needed values, but I failed already with the login.

Here is my code:

// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: red; icon-glyph: magic;

const loginPageUrl = "https://service.premiumsim.de";
const loginUrl = "https://service.premiumsim.de/public/login_check";

let cookies = null;
let sid = null;
let csrf_token = null;

//TODO: Use scriptable parameter
const username = "USERNAME";
const password = "PASSWORD";

await prepareLoginData();
await doLogin();

async function doLogin()
{
    try
    {
        // Post login data
        let req = new Request(loginUrl);
        req.method = 'POST';

        req.headers = {
            'Cookie': cookies,
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
            'Content-Type': 'application/x-www-form-urlencoded',
            'Origin': loginPageUrl,
            'Connection': 'keep-alive',
            'Referer': loginPageUrl,
            'Upgrade-Insecure-Requests': '1',
            'TE': 'Trailers'
        };

        // This looks the same as in firefox
        req.body = "_SID=" + sid + "&UserLoginType%5Balias%5D=" + username + "&UserLoginType%5Bpassword%5D=" + password + "&UserLoginType%5Blogindata%5D=&UserLoginType%5Bcsrf_token%5D=" + csrf_token;

        var resp = await req.loadString();
        await QuickLook.present(req.response);
        console.log(req.response.statusCode); // This should be 302 but is 200

        let view = new WebView();
        view.loadHTML(resp);
        await view.present();
    }
    catch (e)
    {
        console.error(e);
    }
}

async function prepareLoginData()
{
    try
    {
        // Get login page
        let req;
        req = new Request(loginPageUrl);
        req.method = 'GET';
        req.headers = {
            'Cookie': '',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
            'Content-Type': 'application/x-www-form-urlencoded',
            'Connection': 'keep-alive',
            'Upgrade-Insecure-Requests': '1',
            'TE': 'Trailers'
        };

        var resp = await req.loadString();

        // Get setted cookies
        let CookieValues = req.response.cookies.map(function (v)
        {
            return v.name + "=" + v.value
        });

        // Parse csrf token
        resp = resp.substr(resp.indexOf('UserLoginType_csrf_token'), 500);
        resp = resp.substr(resp.indexOf('value="') + 7);
        csrf_token = resp.substr(0, resp.indexOf('"'));

        console.log("Found csrf_token: " + csrf_token);

        cookies = CookieValues.join('; ') + '; isCookieAllowed=true';
        console.log("Found cookies: " + cookies);

        // Get sid
        sid = cookies.substring(5, cookies.indexOf(';'));
        console.log("Got _SID: " + sid);
    }
    catch (e)
    {
        console.error(e);
    }
}

Loading the login page works as expected. Parsing out csrf token works also. When posting these values to the login url, I expect to get the status code 302 with an redirect to https://service.premiumsim.de/start This is, what I've seen using firefox.

I already copied all headers that firefox also send and I did POST and GET requests to my local webserver, to see if the passed form values comes correct to the webserver. I don't know what's going wrong.

See also: How to generate UserLoginType[_token] for login request It's done here with another technique but it's the same content that is send.

1

There are 1 answers

0
Codeinator On

I found out, why it hasn't worked.

Scriptable is automatically loading redirects. This wouldn't work here, because new cookies that was send with the 302 Response weren't used for the redirect.

The solution was to block this redirect and to handle it on my own.

// This blocks the automatic redirect.
req.onRedirect = function (request)
{
    return null;
}

See a full workking scriptable widget here: https://github.com/BergenSoft/scriptable_premiumsim

Edit: I couldn’t found an working example for the onRedirect function, so I ask the Scriptable makers and this was the response:

let url = "https://apple.com";
let req = new Request(url);
req.onRedirect = (req) => {
    log(req.url);
    return req;
}
await req.load();

Hope this will help anyone.