WPIntell

Source evidence

Programmatically obtaining OAuth Token (for testing)

Enable Mastodon Apps · support · 2024-09-19T22:52:00+00:00

mixedsentiment
highseverity
0.95relevance
9replies
Evidence onlycommercial context

Proof Health

Open evidence

Commercial opportunities need traceable source links before they are treated as build-worthy.

1 / 1 rows with source links

100.0% of this page's analysis has direct source links.

0 build-decision rows missing links

0 rows here require auditable proof before promotion.

0 rows with no attached evidence

0 rows have source counts but still need direct links.

Conversation

support
johannes.ernst resolved
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… 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! Ah, very nice! Will try, ty!! Where do the tokens get stored? I’m not familiar with the WordPress APIs. They are stored as taxonomy items. What are you trying to do with them? Just checking that my code works and puts some reasonable-looking values into some reasonable places. 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). 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> I’m not seeing anything obviously wrong and I have been staring at it for a while … 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 …

Comments

9 shown
Alex Kirk 2024-09-20T00:02:00+00:00

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!

johannes.ernst 2024-09-20T00:11:00+00:00

Ah, very nice! Will try, ty!!

johannes.ernst 2024-09-23T18:14:00+00:00

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

Alex Kirk 2024-09-23T18:21:00+00:00

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

johannes.ernst 2024-09-23T18:26:00+00:00

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

Alex Kirk 2024-09-23T18:34:00+00:00

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).

johannes.ernst 2024-09-29T00:01:00+00:00

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/...

johannes.ernst 2024-09-29T00:06:00+00:00

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

johannes.ernst 2024-09-29T00:11:00+00:00

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 …