OJS API authentication issues

In OJS 3.3 one can add the API token as a query parameter, as described here: https://docs.pkp.sfu.ca/dev/api/usage#api-token . I have no problem with this method. Works everywhere.

In OJS 3.4-3.5, I don’t really know why (presumably for security reasons) this authentication method is deprecated and the developers suggest using API Token in the Authorization header (see here https://docs.pkp.sfu.ca/dev/api/ojs/3.4#tag/Authentication/API-Token ). Now, it leads to the following issues:

  • I cannot use HTTP basic auth on my test server anymore, because it is overwritten by another Authorization header required by API. Now, if I want to restrict access, I have to do this via IP addresses, which is not very convenient if you work from several places with dynamic IPs in each of them.
  • I’d like to make a simple static single-page app that will be hosted on a different domain from that of the OJS website. It will fetch (with Fetch API) some data from the OJS API and do some things with it. The API Token will be stored in the localStorage, so the whole thing is supposed to be kinda secure. Now, in OJS 3.4-3.5 I cannot even develop the app because the development server throws CORS errors at me (missing Access-Control-Allow-Origin header), which didn’t happen in OJS 3.3 with the query parameter authorization. Mind that I do not have this issue when requesting from the python script, which doesn’t respect CORS, but I’d like to make a client-side javascript app that runs in browsers. I’ve tried to put Header set Access-Control-Allow-Origin “*” in several places in my vhost and .htaccess, but didn’t succeed. I guess maybe some rewrites (since I have to use restful URLs there are several) or the fact that I’m proxying php-fpm get in the way… I really don’t know.

I’d very much appreciate if someone explained to me

  • Why exactly was API token as a query parameter deprecated?
  • While “the old ways are gone”, what are the recommended new ways? What do I have to do to allow the CORS requests to API for my use case?

On the server I use debian, apache and php-fpm.

This old post CORS (Cross-Origin Resource Sharing) errors when trying to use the OJS (Open Journal Systems) API may also be related, although they used OJS 3.3 in which there’s no such problem if the query parameter auth is used.

Looks as if I have managed to add the CORS headers to my API responses by putting this somewhere at the end of my vhost in apache:

  <LocationMatch "api/v1">
    <If "%{HTTP:Origin} =~ m#^(https?://localhost:\d{4})$#">
      RewriteEngine On
      RewriteCond %{REQUEST_METHOD} OPTIONS
      RewriteRule ^(.*)$ $1 [R=200,NE]
      SetEnvIf Origin "^(.*)$" AccessControlAllowOrigin=$0
      Header always set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
      Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE"
      Header always set Access-Control-Allow-Headers "Origin, Content-Type, Accept, Authorization"
    </If>
  </LocationMatch>

The rewrite rules are for handling the browser’s preflight request. The regular expression ^(https?://localhost:\d{4})$ corresponds to the dev servers that use 4-digit ports (e.g., http://localhost:5173 for vite), and it should be easy to add the production domain with the or operator | when it comes to that. This way, we do not allow just any origin to use our API, as would be the case with Headers always set Access-Control-Allow-Origin “*”. The methods can also be restricted to just get and options for better security.

I’d be glad if someone commented on how (in)secure and excessive this solution is, because I don’t see any obvious problem.