The Problem
When a user registers at a BOINC Project, a 32 character key called the authenticator is created for the user. Due to the way that this key is used, it is unchangeable. Some of the ways that it is used are as follows:
- After registering within the BOINC client, the user is sent to /account_finish.php?auth=<authenticator> where they are able to set a username and join a team. It does this by logging in the user after checking their authenticator. This mechanism can be used by anyone at any time to gain full access to an account by only knowing the authenticator for the account.
- The web_rpcs documented at WebRpc use the authenticator to identify and authorize updates to a user account. These web rpcs include one that can change the user's email address and password. As a result, these web rpcs use the authenticator in a way that allows full access to a user's account by only knowing the authenticator for the account.
- When a user logs into a BOINC project website, the website stores the authenticator in a cookie called "auth". This is used as the session token for the users access to the website. It is easy to add a cookie to a browser (for example using chrome dev tools). Thus if the authenticator is known for an account, the "auth" cookie could be easily added with the value of the authenticator and full access to users account would be allowed.
- The client requests the users email address and password from the user and then submits information to the lookup_account.php web rpc to obtain the authenticator for the account. It then uses the authenticator to identify itself as belonging to a specific account each time it communicates with the scheduler. However, the scheduler only allows limited access to an account (attach a new host, update information about jobs assigned to a host, request new jobs, update client prefs)
It is not secure for an unchangeable token that is present on clients connected to an account allowed to be used to gain full access to a user's account. As a result, all uses of the authenticator except for the case #4 above (i.e. use during scheduler requests) must be changed to use other mechanisms.
Other uses of the authenticator other than item 4 above need to be identified and removed as well.
High Level Solutions
Each of items 1-3 above, need to be replaced with another mechanism. Potential solutions are described at a high level below:
Post-Account Creation (Scenario 1)
The client creates an account by calling the create_account.php RPC. If this call is successful, the server returns the authenticator. The client then uses the authenticator in a scheduler request to register the client under the account and it uses the authenticator to allow the user to further set up their account by calling the account_finish.php RPC.
The create_account.php should be modified to return the authenticator but also return a one-time login token (see technical implementation details). The account_finish.php will be modified so that the value of auth is assumed to be a one-time login token and it will check to see if it is a valid unused one-time login token. Note that the website will not be backwards compatible with older clients. Users of older clients will be asked to login to finish setting up their account. This is necessary in order to allow updated websites to benefit from the improved security.
The client will be modified to use the one-time login token, if found, otherwise it will use the authenticator when it creates the link to account_finish.php. This will allow the client to be backwards compatible with BOINC projects that have not yet updated.
BOINC Web RPCS (Scenario 2)
Each of the BOINC web rpcs validates the user by accepting the authenticator. This should be replaced by implementing OAuth 2.0 and making BOINC Projects OAuth providers.
OAuth 2.0 (https://oauth.net/2/) allows the following benefits:
- Access to the BOINC web rpcs will be done using an authorization token that is specific and unique to a given external application.
- Each token will be individually revocable by the user at the BOINC project website. This allows the user to revoke access from a given external application when they want to without impacting the access of other external applications.
- A well defined standard that is in common use (and thus there exists many libraries in many different languages that can be used to implement it).
BOINC will support both confidential and public client types (https://oauth.net/2/client-types/). BOINC will support the following grant types:
- Authorization Grant Type (https://developer.okta.com/blog/2018/04/10/oauth-authorization-code-grant-type) with the PKCE extension (https://www.loginradius.com/engineering/blog/pkce/)
- Refresh Token Grant Type (https://oauth.net/2/grant-types/refresh-token/)
BOINC will be modified as follows:
- A feature flag will be added to enable or disable OAuth features. The feature flag will also enable or disable self-registration by oauth clients (some projects will want to approve and manually add oauth clients and some will be ok with self-registration by clients)
- Create new user facing web pages necessary to support the OAuth 2.0 Authorization flow for web apps (like BAM) and public clients (see https://aaronparecki.com/oauth-2-simplified/ for a brief overview of how this works)
- Create a new user facing web page to display their current set of authorized accesses, including a way for them to individually revoke that access
- Create a new admin page to allow the project admin to add or remove OAuth clients
- Create the Refresh Token API to obtain a fresh access token when the existing access token expires
- Modify the web rpcs to use the access tokens instead of the authenticator
Website Session Cookies (Scenario #3)
The "auth" cookie, which currently contains the authenticator, will instead use a "web session token" (see below) for its value. The expiration time for the token will be extended after each access to the web page.
If the user checks the "remember me" checkbox, then an additional token "rememberme" will be created that stores a "Remember me token". If the user accesses a project website and they do not have a valid "auth" cookie (i.e. a valid web session token), then the site will check to see if they have a valid "rememberme" cookie/token. If they do, then the website create a new web session token and set the "auth" cookie as well as it will replace the "rememberme" cookie/token with a new "Remember me token" and then delete the one that was just used.
Implementation Details
Please see Reduce usage of authenticator implementation for details about the proposed implementation. Note that most of the implementation describes the implementation for OAuth (scenario 2) as the implementations for scenario #1 and #3 are relatively straightforward but should still reuse the existing token code and make sure they take the OAuth implementation in mind when the work is done for those two.