• Resolved johannes.ernst

    (@johannesernst)


    This is for the FediTest.org project, which develops a test suite for the Fediverse. We are working to integrate a configuration of WordPress (base + ActivityPub + this plugin) that can participate in automated ActivityPub protocol testing. There are lots of parts to this, and one of them is that we want FediTest tests to be able to use the Mastodon API that you implemented (yay!) to cause WordPress to take certain actions, like create a post or check that a follower has arrived. To do that, we need an OAuth token, and we are wondering whether there is a way to obtain such a token in an automated fashion that does NOT require a user going through the UI.

    To get such a token, we are willing to take unnatural acts :-), all the way to inserting a value directly into the SQL database. In the context of FediTest, assume we have root access to the machine that runs WordPress.

    To be clear, we are not asking for functionality that should ever be run in production. We are asking for a “hack” the FediTest can use in a disconnected container environment, as root, on the same machine as WordPress.

    Wouldn’t be surprised if it was as simple as a single INSERT, or calling a single PHP script. Pointers appreciated…

Viewing 9 replies - 1 through 9 (of 9 total)
  • Plugin Author Alex Kirk

    (@akirk)

    Hi!

    As per the Mastodon API, you first need to register an app. You could POST to the /api/v1/apps API endpoint but since you’ll later want to create an access token anyway, you might also want to do this from PHP:

    $app_name = 'feditest';
    $redirect_uri = 'https://feditest.org/'; // you can also use: Enable_Mastodon_Apps\Mastodon_OAuth::OOB_REDIRECT_URI;
    $scopes = 'read write follow push';
    $website = 'https://feditest.org/';
    $app = Enable_Mastodon_Apps\Mastodon_App::save( $app_name, array( $redirect_uri ), $scopes, $website );

    You can then use this snippet to create an access token:

    $desired_token = '123';
    $user_id = 1;
    $oauth = new Enable_Mastodon_Apps\Mastodon_OAuth();
    $oauth->get_token_storage()->setAccessToken( $desired_token, $app->get_client_id(), $user_id, time() + HOUR_IN_SECONDS, $app->get_scopes() );

    This is a simplified version of what is done in the unit tests.

    Hope this helps! Let me know if you need anything else to get things working with Feditest, I think it’s a great initiative!

    Thread Starter johannes.ernst

    (@johannesernst)

    Ah, very nice! Will try, ty!!

    Thread Starter johannes.ernst

    (@johannesernst)

    Where do the tokens get stored? I’m not familiar with the WordPress APIs.

    Plugin Author Alex Kirk

    (@akirk)

    They are stored as taxonomy items. What are you trying to do with them?

    Thread Starter johannes.ernst

    (@johannesernst)

    Just checking that my code works and puts some reasonable-looking values into some reasonable places.

    Plugin Author Alex Kirk

    (@akirk)

    Easiest through the UI at wp-admin/options-general.php?page=enable-mastodon-apps&tab=registered-apps and then click on the app name to see the tokens.

    Or use wp cli with wp term list mastoapi-at (don’t forget to specify the --url parameter when you talk to a multisite).

    Thread Starter johannes.ernst

    (@johannesernst)

    When attempting to post or any other operation, I’m getting a “token required” error although the token is there. I’m going through the Mastodon.py Python library, with code that’s largely the same that works against Mastodon itself.

    HTTP debug output from that library for the call in question:

    Mastodon: Request to endpoint "https://wordpress-1.1234.lan/api/v1/statuses" using method "POST".
    Parameters: OrderedDict([('status', 'Tooting from Python using #mastodonpy !')])
    Headers: {'Authorization': 'Bearer 11223344', 'User-Agent': 'mastodonpy'}
    Files: {}
    Mastodon: Response received with code 401.
    response headers: {'Date': 'Sat, 28 Sep 2024 23:43:54 GMT', 'Server': 'Apache', 'X-Powered-By': 'PHP/8.3.3', 'X-Robots-Tag': 'noindex', 'Link': 'https://wordpress-1.1234.lan/wp-json/; rel="https://api.w.org/"', 'X-Content-Type-Options': 'nosniff', 'Access-Control-Expose-Headers': 'X-WP-Total, X-WP-TotalPages, Link', 'Access-Control-Allow-Headers': 'content-type, authorization', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', 'Access-Control-Allow-Credentials': 'true', 'Content-Length': '63', 'Keep-Alive': 'timeout=5, max=100', 'Connection': 'Keep-Alive', 'Content-Type': 'application/json; charset=UTF-8'}
    Response text content: {"error":"token-required","error_description":"Token required"}

    The token has been set on the WordPress side:

    sudo -u http wp term list mastoapi-at
    PHP Warning: Undefined array key "HTTP_HOST" in phar:///usr/bin/wp/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(1334) : eval()'d code on line 5
    +---------+------------------+------------------------------------------+------------------------------------------+-------------+--------+-------+
    | term_id | term_taxonomy_id | name | slug | description | parent | count |
    +---------+------------------+------------------------------------------+------------------------------------------+-------------+--------+-------+
    | 7 | 7 | 0405a8a2016378de3442dfd467f75e18078d3da2 | 0405a8a2016378de3442dfd467f75e18078d3da2 | | 0 | 0 |
    | 20 | 20 | 11223344 | 11223344 | | 0 | 0 |
    | 3 | 3 | 7c0fb4ab4038213e05cb49887a1736ce | 7c0fb4ab4038213e05cb49887a1736ce | | 0 | 0 |
    +---------+------------------+------------------------------------------+------------------------------------------+-------------+--------+-------+

    Here’s my entire test code:

    from mastodon import Mastodon
    import subprocess

    user = 'feditestadmin'
    server = 'wordpress-1.1234.lan'
    token = '11223344'

    client_id, client_secret = Mastodon.create_app(
    'testapp',
    api_base_url = f'https://{ server }'
    )
    print(f'XXX: client_id = "{ client_id }", client_secret="{ client_secret }"')

    php = f"""<?php
    $_SERVER['HTTP_HOST'] = '{ server }';

    include 'wp-load.php';

    $oauth = new Enable_Mastodon_Apps\Mastodon_OAuth();
    $oauth->get_token_storage()->setAccessToken( "{ token }", "{ client_id }", "{ user }", time() + HOUR_IN_SECONDS, 'read write follow push' );
    """

    print(f'XXX: PHP is="{ php }"')

    cmd = 'cd /ubos/http/sites/s276c4d76696ce6c54cc3c2fe4e305aceec5caf78 && sudo sudo -u http php'
    phpret = subprocess.run(cmd, shell=True, check=False, text=True, input=php, capture_output=True)

    print(f'XXX: phpret.returncode="{ phpret.returncode }"')

    mastodon = Mastodon(
    client_id = client_id,
    client_secret = client_secret,
    api_base_url = f'https://{ server }',
    version_check_mode = 'none',
    access_token = token,
    debug_requests = True
    )
    print(f'XXX mastodon={ mastodon }')

    tootret = mastodon.toot('Tooting from Python using #mastodonpy !')

    print(f'XXX tootret="{ tootret }"')

    And here’s the transcript before that HTTP debug message above:

    XXX: client_id = "drtiky6r3wp3ih6xsmucofygguwzhwfe", client_secret="fzCIgWFK4X4QhYiQRpfLbHdlKrjDmCsxcIeZC9luHcyXA7TTVeZJOXz6ZyqhvylQ1cLTwZxkXH8eXotGH9Ww2scS48y9CHumXp3Fvxdjmycq11b0secBUSizCopFuKnN"
    XXX: PHP is="<?php
    $_SERVER['HTTP_HOST'] = 'wordpress-1.1234.lan';

    include 'wp-load.php';

    $oauth = new Enable_Mastodon_Apps\Mastodon_OAuth();
    $oauth->get_token_storage()->setAccessToken( "11223344", "drtiky6r3wp3ih6xsmucofygguwzhwfe", "feditestadmin", time() + HOUR_IN_SECONDS, 'read write follow push' );
    "
    XXX: phpret.returncode="0"
    XXX mastodon=<mastodon.Mastodon.Mastodon object at 0xffff7dc55890>
    Thread Starter johannes.ernst

    (@johannesernst)

    I’m not seeing anything obviously wrong and I have been staring at it for a while …

    Thread Starter johannes.ernst

    (@johannesernst)

    But of course! As soon as I post this, I notice the setAccessToken call needs the numeric user id, not the string user name! Sorry …

Viewing 9 replies - 1 through 9 (of 9 total)
  • You must be logged in to reply to this topic.