Skip to content

New app with MFA - #554

Draft
charsbar wants to merge 51 commits into
andk:masterfrom
charsbar:pause_2025
Draft

charsbar wants to merge 51 commits into
andk:masterfrom
charsbar:pause_2025

Conversation

@charsbar

@charsbar charsbar commented Apr 26, 2025 •

Copy link
Copy Markdown
Collaborator

This PR adds a new pause_2025 application that allows you to log in from a login form (not by the good-old basic authentication). The new app mounts on /, and uses the path info to decide what to do (instead of the ACTION query parameter). If you use the new app, and enable multifactor authentication, you need to send another authentication code when you log in. If you need the current interface, the pause_2017 app is still available.

Not everything is ready yet; some links may be broken or point to the old interface; tests are not migrated; sessions are not stored in the database; not all the upload methods are tested; apply fixes suggested in #455; there may be more, but I hope you can get the picture.

Some of the things we need to discuss later: should we allow users who enable MFA to use the old interface (ie. basic auth)?; should we still use the pause99_ prefix? (well, it's 2025 now); can we replace ACTIONREQ with something like Mojo's $c->flash or something?

@charsbar
charsbar marked this pull request as draft April 26, 2025 18:00
@charsbar
charsbar requested review from rjbs and wolfsage April 26, 2025 18:00
charsbar added 27 commits May 4, 2025 22:58
Now that we use the path_info to find a route, it may be enough just to move the ACTION to $c->url_for() and keep the rest in the ->query(), but I feel it's easier just to remove ->query and pass all the params to my_url.
For the time being, let's use $c->my_url() and tweak the result, but it might be better to use $c->url_for here as well.
my_url() may use a different action stored in the stash, but the menu links do not need such a trick.
As pause_2025 mounts on the /, not on the /pause, the links also need to be modified
pause_2025 just uses $c->url_for(), so we don't need to "fix" the action
Now that FixAction is removed, we should set the Action somewhere
It's easier just to use action names as paths, but I feed it better to prepend group names to make it clear which action belongs to which group.
 ->name() is added to help $c->url_for() return the correct path.
Almost all the login code is taken from ::Middleware::Auth::Basic::authentication. Instead of setting REMOTE_USER, we use Mojolicious's session to keep the user's id (for now; eventually it should be stored in the database).
We can't use mfa_secret32 to decide if the user uses MFA or not, because mfa_secret32 needs to be stored in the database as soon as the user first visit the MFA page; otherwise Auth::GoogleAuth generates a different secret32 when the user posts the authentication code (and thus the verification fails).
Right now we only use the Mojo's session, we just need to clear the session. Eventually we'll also need to remove a session table entry.
The secret should be the same for all the workers. It is used to encrypt Mojo's cookie(-based session).
…er (taken from a session)

is_allowed_action is factored out from ConfigPerRequest::_set_allowed_actions
charsbar added 24 commits May 4, 2025 22:59
user_secrets was used to be retrieved when a user is authenticated via Basic Auth, but we don't use it now. Maybe _retrieve_user is the best place to retrieve the secrets.
…m a session

maybe because of session timeout
as it is usually used in an email or side menu
(until I release a new version of Mojolicious::Plugin::WithCSRFProtection)
as the current tests under action expects things work the same as app_2017. (We'll add action_2025 next)
@rjbs

rjbs commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator

I'm not sure if you plan to bring this onto master and the new work there, but I was looking at the auth code (as part of my interest in getting us off Basic), and turned up some stuff worth noting.

  1. when prompted for code in a new form, the old form state is filled out again, including password, which means the server is round-tripping the pw back to the user
  2. you can use a code twice; I had remarked on this in a previous iteration of this code (Add MFA protection to several pages of the PAUSE #455); once used, a code shouldn't work again; this prevents a MITM from intercepting a code and using it right away
  3. there's no way provided, afaict, to invalidate old sessions

@charsbar

Copy link
Copy Markdown
Collaborator Author

As I noted in the first description, this PR is incomplete. I plan to revisit it before the next PTS, but if you want to take it over and implement the backend details now, please do.

However, before deploying MFA (or implementing further details), we need to agree on how to proceed: how long we allow users to upload distributions using basic auth; whether we want to force MFA eventually; how we let them know they need to use a new uploader. We need to modify CPAN::Uploader and its friends to either interact with MFA or post via the API from app2026. We may also need to add more API endpoints beforehand so that other scripts can use them to manage permissions, delete files, and so on. Or we may want to provide a new client app that does everything we need, instead of asking others to update their scripts. We may need to add features to manage login state and tokens to the client. There must be more.

@rjbs

rjbs commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator

👍🏽 I'll send an email this week and make sure we're on one page. I don't want to be a pest!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants